diff --git a/P-Face_SFACT.rar b/P-Face_SFACT.rar deleted file mode 100644 index d3b13b5..0000000 Binary files a/P-Face_SFACT.rar and /dev/null differ diff --git a/sfact_profiles/profiles/cutting.csv b/sfact_profiles/profiles/cutting.csv deleted file mode 100644 index 3ffa660..0000000 --- a/sfact_profiles/profiles/cutting.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated cutting settings. -_Name Value -WindowPosition 0+400 -Profile Selection: end_mill diff --git a/sfact_profiles/profiles/extrusion.csv b/sfact_profiles/profiles/extrusion.csv deleted file mode 100644 index 7d14791..0000000 --- a/sfact_profiles/profiles/extrusion.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated extrusion settings. -_Name Value -WindowPosition 0+400 -Profile Selection: PLA diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/bottom.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/bottom.csv deleted file mode 100644 index 0a24bd9..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/bottom.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated bottom settings. -_Name Value -WindowPosition 700+0 -Open File for Bottom -Activate Bottom... and dont change anything else here!!! True -Additional Height (ratio): 0.5 -Altitude (mm): 0.0 -SVG Viewer: webbrowser diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/carve.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/carve.csv deleted file mode 100644 index 03cd070..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/carve.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated carve settings. -_Name Value -WindowPosition 700+0 -Open File for Carve -Layer Height = Extrusion Thickness (mm): 0.33 -Extrusion Width (mm): 0.5 -Print from Layer No:: 0 -Print up to Layer No: 912345678 -Infill in Direction of Bridge True -Correct Mesh True -Unproven Mesh False -SVG Viewer: webbrowser -Add Layer Template to SVG True -Extra Decimal Places (float): 2.0 -Import Coarseness (ratio): 1.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/chamber.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/chamber.csv deleted file mode 100644 index 08ccd9c..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/chamber.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated chamber settings. -_Name Value -WindowPosition 700+0 -Open File for Chamber -Activate Chamber..if you want below functions to work True -Heated PrintBed Temperature (Celcius): 60.0 -Turn print Bed Heater Off at Shut Down True -Turn Extruder Heater Off at Shut Down True diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/clairvoyance.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/clairvoyance.csv deleted file mode 100644 index 8aadf4f..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/clairvoyance.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated clairvoyance settings. -_Name Value -WindowPosition 700+0 -Activate Clairvoyance False -Open File to Generate Clairvoyances for -Gcode Program: webbrowser diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/clip.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/clip.csv deleted file mode 100644 index c61adb8..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/clip.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated clip settings. -_Name Value -WindowPosition 700+0 -Open File for Clip -Activate Clip..to clip the extrusion that overlaps when printing perimeters True -Clip Over Perimeter Width adjuster (decrease for bigger gap): 1.0 -Threshold for connecting inner loops (ratio): 2.5 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/comb.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/comb.csv deleted file mode 100644 index 403d19b..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/comb.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated comb settings. -_Name Value -WindowPosition 700+0 -Open File for Comb -Activate Comb if you cant stop the extruder stringing by retraction -it will avoid moving over loops so the strings will be there -but not visible anymore. -Comb bends the extruder travel paths around holes in the slices, to avoid stringing. -so any start up ooze will be inside the shape. True diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/comment.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/comment.csv deleted file mode 100644 index c140205..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/comment.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated comment settings. -_Name Value -WindowPosition 700+0 -Activate Comment False -Open File to Write Comments for diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/cool.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/cool.csv deleted file mode 100644 index ed931a0..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/cool.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated cool settings. -_Name Value -WindowPosition 700+0 -Open File for Cool -Activate Cool.. but use with a fan! False -Use Cool if layer takes shorter than(seconds): 10.0 -Turn Fan On at Beginning True -Turn Fan Off at Ending True -Execute when Cool starts: cool_start.gmc -Execute when Cool ends: cool_end.gmc -Orbiting around Object False -Slow Down during print True -Maximum Cool (Celcius): 2.0 -Bridge Cool (Celcius): 1.0 -Minimum Orbital Radius (millimeters): 10.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/dimension.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/dimension.csv deleted file mode 100644 index e2272b6..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/dimension.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated dimension settings. -_Name Value -WindowPosition 700+0 -Open File for Dimension -Activate Volumetric Extrusion (Stepper driven Extruders) True -Filament Diameter (mm): 1.75 -Filament Packing Density (ratio) lower=more extrusion: 1.0 -Retraction Distance (millimeters): 1.0 -Restart Extra Distance (millimeters): 0.0 -Extruder Retraction Speed (mm/s): 15.0 -Force to retract when crossing over spaces True -Minimum Extrusion before Retraction (millimeters): 1.0 -Minimum Travelmove after Retraction (millimeters): 1.0 -in Absolute units (Sprinter, FiveD a.o.) True -in Relative units (Teacup a.o.) False diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/export.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/export.csv deleted file mode 100644 index be5764b..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/export.csv +++ /dev/null @@ -1,20 +0,0 @@ -Format is tab separated export settings. -_Name Value -WindowPosition 700+0 -Open File for Export -Activate Export True -Add _export to filename (filename_export) True -Also Send Output To: -Do Not Delete Comments False -Delete Crafting Comments False -Delete All Comments True -Do Not Change Output False -gcode_small True -File Extension (gcode): gcode -Name of Replace File: replace.csv -Save Penultimate Gcode False -Archive Used Profile As Zip False -Export Profile Values As CSV File False -Add Profile Name to Filename False -Add Description to Filename False -Add Timestamp to Filename False diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/fill.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/fill.csv deleted file mode 100644 index 682b1eb..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/fill.csv +++ /dev/null @@ -1,34 +0,0 @@ -Format is tab separated fill settings. -_Name Value -WindowPosition 700+0 -Open File for Fill -Activate Fill: True -Infill Solidity (ratio): 0.35 -Extrusion Lines extra Spacing (Scaler): 1.0 -Infill Overlap over Perimeter (Scaler): 1.0 -Extra Shells on Alternating Solid Layer (layers): 1 -Extra Shells on Base (layers): 1 -Extra Shells on Sparse Layer (layers): 1 -Fully filled Layers (each top and bottom): 2 -Lower Left True -Nearest False -Infill > Loops > Perimeter False -Infill > Perimeter > Loops False -Loops > Infill > Perimeter False -Loops > Perimeter > Infill False -Perimeter > Infill > Loops False -Perimeter > Loops > Infill True -Line True -Grid Circular False -Grid Hexagonal False -Grid Rectangular False -Diaphragm at every ...th Layer: 100 -Diaphragm Thickness (layers): 0 -Grid Circle Separation over Perimeter Width (ratio): 0.2 -Grid Extra Overlap (ratio): 0.1 -Grid Junction Separation Band Height (layers): 10 -Grid Junction Separation over Octogon Radius At End (ratio): 0.0 -Grid Junction Separation over Octogon Radius At Middle (ratio): 0.0 -Infill Begin Rotation (degrees): 45.0 -Infill Begin Rotation Repeat (layers): 1 -Infill Odd Layer Extra Rotation (degrees): 90.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/home.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/home.csv deleted file mode 100644 index 430a33a..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/home.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated home settings. -_Name Value -WindowPosition 700+0 -Open File for Home -Activate Home ... Not needed True -Name of Homing File: homing.gcode diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/inset.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/inset.csv deleted file mode 100644 index 6c3d57c..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/inset.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated inset settings. -_Name Value -WindowPosition 700+0 -Open File for Inset -Bridge Width Multiplier (ratio): 1.0 -Prefer Loops False -Prefer Perimeter True -Overlap Removal(Scaler): 1.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/interpret.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/interpret.csv deleted file mode 100644 index 76cdc59..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/interpret.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated interpret settings. -_Name Value -WindowPosition 700+0 -Open File for Interpret -Activate Interpret False -Print Interpretion False -Text Program: webbrowser diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/jitter.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/jitter.csv deleted file mode 100644 index 781738d..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/jitter.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated jitter settings. -_Name Value -WindowPosition 700+0 -Open File for Jitter -Activate Jitter to have your perimeter and loop endpoints scattered False -Jitter Over Perimeter Width (ratio): 2.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/lash.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/lash.csv deleted file mode 100644 index 32ccb3b..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/lash.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated lash settings. -_Name Value -WindowPosition 700+0 -Open File for Lash -Activate Lash if you have backlash in your axes. -But its better to fix the mechanical problem! False -X Backlash (mm): 0.0 -Y Backlash (mm): 0.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/limit.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/limit.csv deleted file mode 100644 index 9671405..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/limit.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated limit settings. -_Name Value -WindowPosition 700+0 -Open File for Limit -Activate Limit if your Firmware is unable to Limiting your Z-Speed. False -Maximum Initial Feed Rate (mm/s): 5.0 -Maximum Z Feed Rate (mm/s): 5.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/multiply.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/multiply.csv deleted file mode 100644 index 269d53f..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/multiply.csv +++ /dev/null @@ -1,10 +0,0 @@ -Format is tab separated multiply settings. -_Name Value -WindowPosition 700+0 -Open File for Multiply -Activate Multiply: True -Center X (mm): 100.0 -Center Y (mm): 100.0 -Number of Columns (integer): 1 -Number of Rows (integer): 1 -Separation over Perimeter Width (ratio): 15.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/polyfile.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/polyfile.csv deleted file mode 100644 index 6e7d9bb..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/polyfile.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated polyfile settings. -_Name Value -WindowPosition 700+0 -Execute All Unmodified Files in a Directory False -Execute File True diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/preface.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/preface.csv deleted file mode 100644 index 937a406..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/preface.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated preface settings. -Home before Print False -_Name Value -WindowPosition 700+0 -Open File for Preface -Reset Extruder before Print True -Meta: -Name of End File: end.gmc -Name of Start File: start.gmc -Set Positioning to Absolute True -Set Units to Millimeters True diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/raft.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/raft.csv deleted file mode 100644 index 8d4b00a..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/raft.csv +++ /dev/null @@ -1,38 +0,0 @@ -Format is tab separated raft settings. -_Name Value -WindowPosition 700+0 -Open File for Raft -Activate Raft True -Add Raft, Elevate Nozzle, Orbit: True -None True -Empty Layers Only False -Everywhere False -Exterior Only False -Add support if flatter than (degrees): 50.0 -Cross Hatch instead of Lines False -Interface/Support Lines Density (ratio): 0.25 -Interface/Support Layer Thickness over Layer Thickness: 1.0 -Support Feed Rate mm/sec: 15.0 -Support Flow Rate (scaler): 1.0 -Support Gap over Perimeter Extrusion Width (ratio): 1.0 -Raft/Support extension in (%): 5.0 -Raft/Support extension in(mm): 2.0 -Name of Support End File: support_end.gmc -Name of Support Start File: support_start.gmc -Extra Nozzle clearance over Object(ratio): 0.0 -First Layer Main Feedrate (mm/s): 35.0 -First Layer Perimeter Feedrate (mm/s): 25.0 -First Layer Flow Rate Infill(scaler): 1.0 -First Layer Flow Rate Perimeter(scaler): 1.0 -Interface Layers (integer): 0 -Interface Feed Rate Multiplier (ratio): 1.0 -Interface Flow Rate Multiplier (ratio): 1.0 -Interface Nozzle Lift over Interface Layer Thickness (ratio): 0.45 -Base Layers (integer): 0 -Base Feed Rate Multiplier (ratio): 0.5 -Base Flow Rate Multiplier (ratio): 0.5 -Base Infill Density (ratio): 0.5 -Base Layer Thickness over Layer Thickness: 2.0 -Base Nozzle Lift over Base Layer Thickness (ratio): 0.4 -Initial Circling: False -Infill Overhang over Extrusion Width (ratio): 3.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/scale.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/scale.csv deleted file mode 100644 index a479f8b..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/scale.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated scale settings. -_Name Value -WindowPosition 700+0 -Open File for Scale -Activate Scale to finetune print size (try to find the fault somewhere else..): False -XY Plane Scale (ratio): 1.0 -Z Axis Scale (ratio): 1.0 -SVG Viewer: webbrowser diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge.csv deleted file mode 100644 index 22338a4..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated skeinforge settings. -_Name Value -WindowPosition 1187+2 -Open File for Skeinforge C:/Users/Ahmet/STL/_Screw Holder Bottom.stl -analyze False -craft True -help False -meta False -profile False diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_analyze.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_analyze.csv deleted file mode 100644 index 8826bcb..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_analyze.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated skeinforge analyze settings. -_Name Value -WindowPosition 600+0 -Open File for Analyze -clairvoyance False -comment False -interpret False -skeiniso True -skeinlayer False -statistic False -vectorwrite False diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_craft.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_craft.csv deleted file mode 100644 index 0943077..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_craft.csv +++ /dev/null @@ -1,27 +0,0 @@ -Format is tab separated skeinforge craft settings. -_Name Value -WindowPosition 600+0 -Open File for Craft -bottom False -carve False -chamber False -clip False -comb False -cool False -dimension True -export False -fill False -inset False -jitter False -lash False -limit False -multiply False -preface False -raft False -scale False -skin False -skirt False -speed False -stretch False -temperature False -wipe False diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_help.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_help.csv deleted file mode 100644 index 6447399..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_help.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated skeinforge help settings. -_Name Value -WindowPosition 600+0 -Wiki Manual Primary True diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeiniso.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeiniso.csv deleted file mode 100644 index a0bf075..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeiniso.csv +++ /dev/null @@ -1,41 +0,0 @@ -Format is tab separated skeiniso settings. -_Name Value -WindowPosition 700+0 -Open File for Skeiniso -Activate Skeiniso True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Axis Rulings True -Band Height (layers): 5 -Bottom Band Brightness (ratio): 0.7 -Bottom Layer Brightness (ratio): 1.0 -From the Bottom False -From the Top True -Draw Arrows False -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 912345678 -Line (index): 24 -Display Line True -View Move False -View Rotate False -Number of Fill Bottom Layers (integer): 1 -Number of Fill Top Layers (integer): 1 -Scale (pixels per millimeter): 15.0 -Screen Horizontal Inset (pixels): 100 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Viewpoint Latitude (degrees): 15.0 -Viewpoint Longitude (degrees): 210.0 -Width of Axis Negative Side (pixels): 2 -Width of Axis Positive Side (pixels): 6 -Width of Fill Bottom Thread (pixels): 2 -Width of Fill Top Thread (pixels): 2 -Width of Infill Thread (pixels): 1 -Width of Loop Thread (pixels): 2 -Width of Perimeter Inside Thread (pixels): 8 -Width of Perimeter Outside Thread (pixels): 8 -Width of Raft Thread (pixels): 1 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinlayer.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinlayer.csv deleted file mode 100644 index 5273776..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinlayer.csv +++ /dev/null @@ -1,23 +0,0 @@ -Format is tab separated skeinlayer settings. -_Name Value -WindowPosition 700+0 -Open File for Skeinlayer -Activate Skeinlayer True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Draw Arrows True -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 0 -Line (index): 430 -Display Line True -View Move False -Scale (pixels per millimeter): 25.0 -Screen Horizontal Inset (pixels): 100 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Show Position True -Width of Extrusion Thread (pixels): 3 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 1 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skin.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skin.csv deleted file mode 100644 index 9154030..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skin.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skin settings. -_Name Value -WindowPosition 700+0 -Open File for Skin -Activate Skin: this is experimental. -It prints the perimeters and loops only at half the layer height that is specified under carve. False -Clip Over Perimeter Width (scaler): 1.0 -Do Not Skin the first ... Layers: 3 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skirt.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skirt.csv deleted file mode 100644 index 80cd328..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skirt.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skirt settings. -_Name Value -WindowPosition 700+0 -Open File for Skirt -Activate Skirt: True -Convex: True -Gap over Perimeter Width (ratio): 5.0 -Layers To (index): 3 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/speed.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/speed.csv deleted file mode 100644 index e2685f3..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/speed.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated speed settings. -_Name Value -WindowPosition 700+0 -Open File for Speed -Activate Speed: True -Add Flow Rate: True -Main Feed Rate (mm/s): 60.0 -Main Flow Rate (scaler): 1.0 -Feed Rate ratio for Orbiting move (ratio): 0.5 -Perimeter Feed Rate (mm/s): 30.0 -Perimeter Flow Rate (scaler): 1.0 -Bridge Feed Rate (ratio): 1.0 -Bridge Flow Rate (scaler): 1.0 -Travel Feed Rate (mm/s): 130.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/statistic.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/statistic.csv deleted file mode 100644 index 4a1f127..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/statistic.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated statistic settings. -_Name Value -WindowPosition 700+0 -Activate Statistic True -Machine Time ($/hour): 1.0 -Material ($/kg): 20.0 -Density (kg/m3): 930.0 -Extrusion Diameter over Thickness (ratio): 1.25 -Open File to Generate Statistics for -Print Statistics True -Save Statistics False diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/stretch.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/stretch.csv deleted file mode 100644 index 5bc618d..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/stretch.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated stretch settings. -_Name Value -WindowPosition 700+0 -Open File for Stretch -Activate Stretch to correct for diameter shrink in small diameter holes False -Cross Limit Distance Over Perimeter Width (ratio): 5.0 -Loop Stretch Over Perimeter Width (ratio): 0.11 -Path Stretch Over Perimeter Width (ratio): 0.0 -Perimeter Inside Stretch Over Perimeter Width (ratio): 0.32 -Perimeter Outside Stretch Over Perimeter Width (ratio): 0.1 -Stretch From Distance Over Perimeter Width (ratio): 2.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/temperature.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/temperature.csv deleted file mode 100644 index ce2ef6e..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/temperature.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated temperature settings. -_Name Value -WindowPosition 700+0 -Open File for Temperature -Activate Temperature: False -Cooling Rate (Celcius/second): 3.0 -Heating Rate (Celcius/second): 3.0 -Base Temperature (Celcius): 210.0 -Interface Temperature (Celcius): 210.0 -Object First Layer Infill Temperature (Celcius): 210.0 -Object First Layer Perimeter Temperature (Celcius): 210.0 -Object Next Layers Temperature (Celcius): 210.0 -Support Layers Temperature (Celcius): 210.0 -Supported Layers Temperature (Celcius): 210.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/vectorwrite.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/vectorwrite.csv deleted file mode 100644 index e03372b..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/vectorwrite.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated vectorwrite settings. -_Name Value -WindowPosition 700+0 -Activate Vectorwrite False -Open File to Write Vector Graphics for -Add Loops True -Add Paths True -Add Perimeters True -Layers From (index): 0 -Layers To (index): 912345678 -SVG Viewer: webbrowser diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/wipe.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/wipe.csv deleted file mode 100644 index 855c684..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/wipe.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated wipe settings. -_Name Value -WindowPosition 700+0 -Open File for Wipe -Activate Wipe False -Location Arrival X (mm): 0.0 -Location Arrival Y (mm): 5.0 -Location Arrival Z (mm): 0.0 -Location Departure X (mm): 5.0 -Location Departure Y (mm): 0.0 -Location Departure Z (mm): 0.0 -Location Wipe X (mm): 0.0 -Location Wipe Y (mm): 0.0 -Location Wipe Z (mm): 0.0 -Wipe Period (layers): 15 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/bottom.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/bottom.csv deleted file mode 100644 index 0a24bd9..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/bottom.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated bottom settings. -_Name Value -WindowPosition 700+0 -Open File for Bottom -Activate Bottom... and dont change anything else here!!! True -Additional Height (ratio): 0.5 -Altitude (mm): 0.0 -SVG Viewer: webbrowser diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/carve.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/carve.csv deleted file mode 100644 index 3a65503..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/carve.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated carve settings. -_Name Value -WindowPosition 700+0 -Open File for Carve -Layer Height = Extrusion Thickness (mm): 0.4 -Extrusion Width (mm): 0.6 -Print from Layer No:: 0 -Print up to Layer No: 912345678 -Infill in Direction of Bridge True -Correct Mesh True -Unproven Mesh False -SVG Viewer: webbrowser -Add Layer Template to SVG True -Extra Decimal Places (float): 2.0 -Import Coarseness (ratio): 1.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/chamber.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/chamber.csv deleted file mode 100644 index 08ccd9c..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/chamber.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated chamber settings. -_Name Value -WindowPosition 700+0 -Open File for Chamber -Activate Chamber..if you want below functions to work True -Heated PrintBed Temperature (Celcius): 60.0 -Turn print Bed Heater Off at Shut Down True -Turn Extruder Heater Off at Shut Down True diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/clairvoyance.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/clairvoyance.csv deleted file mode 100644 index 8aadf4f..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/clairvoyance.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated clairvoyance settings. -_Name Value -WindowPosition 700+0 -Activate Clairvoyance False -Open File to Generate Clairvoyances for -Gcode Program: webbrowser diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/clip.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/clip.csv deleted file mode 100644 index c61adb8..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/clip.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated clip settings. -_Name Value -WindowPosition 700+0 -Open File for Clip -Activate Clip..to clip the extrusion that overlaps when printing perimeters True -Clip Over Perimeter Width adjuster (decrease for bigger gap): 1.0 -Threshold for connecting inner loops (ratio): 2.5 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/comb.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/comb.csv deleted file mode 100644 index 403d19b..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/comb.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated comb settings. -_Name Value -WindowPosition 700+0 -Open File for Comb -Activate Comb if you cant stop the extruder stringing by retraction -it will avoid moving over loops so the strings will be there -but not visible anymore. -Comb bends the extruder travel paths around holes in the slices, to avoid stringing. -so any start up ooze will be inside the shape. True diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/comment.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/comment.csv deleted file mode 100644 index c140205..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/comment.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated comment settings. -_Name Value -WindowPosition 700+0 -Activate Comment False -Open File to Write Comments for diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/cool.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/cool.csv deleted file mode 100644 index ed931a0..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/cool.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated cool settings. -_Name Value -WindowPosition 700+0 -Open File for Cool -Activate Cool.. but use with a fan! False -Use Cool if layer takes shorter than(seconds): 10.0 -Turn Fan On at Beginning True -Turn Fan Off at Ending True -Execute when Cool starts: cool_start.gmc -Execute when Cool ends: cool_end.gmc -Orbiting around Object False -Slow Down during print True -Maximum Cool (Celcius): 2.0 -Bridge Cool (Celcius): 1.0 -Minimum Orbital Radius (millimeters): 10.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/dimension.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/dimension.csv deleted file mode 100644 index e2272b6..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/dimension.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated dimension settings. -_Name Value -WindowPosition 700+0 -Open File for Dimension -Activate Volumetric Extrusion (Stepper driven Extruders) True -Filament Diameter (mm): 1.75 -Filament Packing Density (ratio) lower=more extrusion: 1.0 -Retraction Distance (millimeters): 1.0 -Restart Extra Distance (millimeters): 0.0 -Extruder Retraction Speed (mm/s): 15.0 -Force to retract when crossing over spaces True -Minimum Extrusion before Retraction (millimeters): 1.0 -Minimum Travelmove after Retraction (millimeters): 1.0 -in Absolute units (Sprinter, FiveD a.o.) True -in Relative units (Teacup a.o.) False diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/export.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/export.csv deleted file mode 100644 index be5764b..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/export.csv +++ /dev/null @@ -1,20 +0,0 @@ -Format is tab separated export settings. -_Name Value -WindowPosition 700+0 -Open File for Export -Activate Export True -Add _export to filename (filename_export) True -Also Send Output To: -Do Not Delete Comments False -Delete Crafting Comments False -Delete All Comments True -Do Not Change Output False -gcode_small True -File Extension (gcode): gcode -Name of Replace File: replace.csv -Save Penultimate Gcode False -Archive Used Profile As Zip False -Export Profile Values As CSV File False -Add Profile Name to Filename False -Add Description to Filename False -Add Timestamp to Filename False diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/fill.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/fill.csv deleted file mode 100644 index 682b1eb..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/fill.csv +++ /dev/null @@ -1,34 +0,0 @@ -Format is tab separated fill settings. -_Name Value -WindowPosition 700+0 -Open File for Fill -Activate Fill: True -Infill Solidity (ratio): 0.35 -Extrusion Lines extra Spacing (Scaler): 1.0 -Infill Overlap over Perimeter (Scaler): 1.0 -Extra Shells on Alternating Solid Layer (layers): 1 -Extra Shells on Base (layers): 1 -Extra Shells on Sparse Layer (layers): 1 -Fully filled Layers (each top and bottom): 2 -Lower Left True -Nearest False -Infill > Loops > Perimeter False -Infill > Perimeter > Loops False -Loops > Infill > Perimeter False -Loops > Perimeter > Infill False -Perimeter > Infill > Loops False -Perimeter > Loops > Infill True -Line True -Grid Circular False -Grid Hexagonal False -Grid Rectangular False -Diaphragm at every ...th Layer: 100 -Diaphragm Thickness (layers): 0 -Grid Circle Separation over Perimeter Width (ratio): 0.2 -Grid Extra Overlap (ratio): 0.1 -Grid Junction Separation Band Height (layers): 10 -Grid Junction Separation over Octogon Radius At End (ratio): 0.0 -Grid Junction Separation over Octogon Radius At Middle (ratio): 0.0 -Infill Begin Rotation (degrees): 45.0 -Infill Begin Rotation Repeat (layers): 1 -Infill Odd Layer Extra Rotation (degrees): 90.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/home.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/home.csv deleted file mode 100644 index 430a33a..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/home.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated home settings. -_Name Value -WindowPosition 700+0 -Open File for Home -Activate Home ... Not needed True -Name of Homing File: homing.gcode diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/inset.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/inset.csv deleted file mode 100644 index 6c3d57c..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/inset.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated inset settings. -_Name Value -WindowPosition 700+0 -Open File for Inset -Bridge Width Multiplier (ratio): 1.0 -Prefer Loops False -Prefer Perimeter True -Overlap Removal(Scaler): 1.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/interpret.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/interpret.csv deleted file mode 100644 index 76cdc59..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/interpret.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated interpret settings. -_Name Value -WindowPosition 700+0 -Open File for Interpret -Activate Interpret False -Print Interpretion False -Text Program: webbrowser diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/jitter.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/jitter.csv deleted file mode 100644 index 781738d..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/jitter.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated jitter settings. -_Name Value -WindowPosition 700+0 -Open File for Jitter -Activate Jitter to have your perimeter and loop endpoints scattered False -Jitter Over Perimeter Width (ratio): 2.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/lash.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/lash.csv deleted file mode 100644 index 32ccb3b..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/lash.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated lash settings. -_Name Value -WindowPosition 700+0 -Open File for Lash -Activate Lash if you have backlash in your axes. -But its better to fix the mechanical problem! False -X Backlash (mm): 0.0 -Y Backlash (mm): 0.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/limit.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/limit.csv deleted file mode 100644 index 9671405..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/limit.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated limit settings. -_Name Value -WindowPosition 700+0 -Open File for Limit -Activate Limit if your Firmware is unable to Limiting your Z-Speed. False -Maximum Initial Feed Rate (mm/s): 5.0 -Maximum Z Feed Rate (mm/s): 5.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/multiply.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/multiply.csv deleted file mode 100644 index 269d53f..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/multiply.csv +++ /dev/null @@ -1,10 +0,0 @@ -Format is tab separated multiply settings. -_Name Value -WindowPosition 700+0 -Open File for Multiply -Activate Multiply: True -Center X (mm): 100.0 -Center Y (mm): 100.0 -Number of Columns (integer): 1 -Number of Rows (integer): 1 -Separation over Perimeter Width (ratio): 15.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/polyfile.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/polyfile.csv deleted file mode 100644 index 6e7d9bb..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/polyfile.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated polyfile settings. -_Name Value -WindowPosition 700+0 -Execute All Unmodified Files in a Directory False -Execute File True diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/preface.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/preface.csv deleted file mode 100644 index 937a406..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/preface.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated preface settings. -Home before Print False -_Name Value -WindowPosition 700+0 -Open File for Preface -Reset Extruder before Print True -Meta: -Name of End File: end.gmc -Name of Start File: start.gmc -Set Positioning to Absolute True -Set Units to Millimeters True diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/raft.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/raft.csv deleted file mode 100644 index 8d4b00a..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/raft.csv +++ /dev/null @@ -1,38 +0,0 @@ -Format is tab separated raft settings. -_Name Value -WindowPosition 700+0 -Open File for Raft -Activate Raft True -Add Raft, Elevate Nozzle, Orbit: True -None True -Empty Layers Only False -Everywhere False -Exterior Only False -Add support if flatter than (degrees): 50.0 -Cross Hatch instead of Lines False -Interface/Support Lines Density (ratio): 0.25 -Interface/Support Layer Thickness over Layer Thickness: 1.0 -Support Feed Rate mm/sec: 15.0 -Support Flow Rate (scaler): 1.0 -Support Gap over Perimeter Extrusion Width (ratio): 1.0 -Raft/Support extension in (%): 5.0 -Raft/Support extension in(mm): 2.0 -Name of Support End File: support_end.gmc -Name of Support Start File: support_start.gmc -Extra Nozzle clearance over Object(ratio): 0.0 -First Layer Main Feedrate (mm/s): 35.0 -First Layer Perimeter Feedrate (mm/s): 25.0 -First Layer Flow Rate Infill(scaler): 1.0 -First Layer Flow Rate Perimeter(scaler): 1.0 -Interface Layers (integer): 0 -Interface Feed Rate Multiplier (ratio): 1.0 -Interface Flow Rate Multiplier (ratio): 1.0 -Interface Nozzle Lift over Interface Layer Thickness (ratio): 0.45 -Base Layers (integer): 0 -Base Feed Rate Multiplier (ratio): 0.5 -Base Flow Rate Multiplier (ratio): 0.5 -Base Infill Density (ratio): 0.5 -Base Layer Thickness over Layer Thickness: 2.0 -Base Nozzle Lift over Base Layer Thickness (ratio): 0.4 -Initial Circling: False -Infill Overhang over Extrusion Width (ratio): 3.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/scale.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/scale.csv deleted file mode 100644 index a479f8b..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/scale.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated scale settings. -_Name Value -WindowPosition 700+0 -Open File for Scale -Activate Scale to finetune print size (try to find the fault somewhere else..): False -XY Plane Scale (ratio): 1.0 -Z Axis Scale (ratio): 1.0 -SVG Viewer: webbrowser diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge.csv deleted file mode 100644 index 22338a4..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated skeinforge settings. -_Name Value -WindowPosition 1187+2 -Open File for Skeinforge C:/Users/Ahmet/STL/_Screw Holder Bottom.stl -analyze False -craft True -help False -meta False -profile False diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_analyze.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_analyze.csv deleted file mode 100644 index a399731..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_analyze.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated skeinforge analyze settings. -_Name Value -WindowPosition 600+0 -Open File for Analyze -clairvoyance False -comment False -interpret False -skeiniso True -skeinlayer True -statistic False -vectorwrite False diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_craft.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_craft.csv deleted file mode 100644 index 0943077..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_craft.csv +++ /dev/null @@ -1,27 +0,0 @@ -Format is tab separated skeinforge craft settings. -_Name Value -WindowPosition 600+0 -Open File for Craft -bottom False -carve False -chamber False -clip False -comb False -cool False -dimension True -export False -fill False -inset False -jitter False -lash False -limit False -multiply False -preface False -raft False -scale False -skin False -skirt False -speed False -stretch False -temperature False -wipe False diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_help.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_help.csv deleted file mode 100644 index 6447399..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_help.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated skeinforge help settings. -_Name Value -WindowPosition 600+0 -Wiki Manual Primary True diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeiniso.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeiniso.csv deleted file mode 100644 index a0bf075..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeiniso.csv +++ /dev/null @@ -1,41 +0,0 @@ -Format is tab separated skeiniso settings. -_Name Value -WindowPosition 700+0 -Open File for Skeiniso -Activate Skeiniso True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Axis Rulings True -Band Height (layers): 5 -Bottom Band Brightness (ratio): 0.7 -Bottom Layer Brightness (ratio): 1.0 -From the Bottom False -From the Top True -Draw Arrows False -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 912345678 -Line (index): 24 -Display Line True -View Move False -View Rotate False -Number of Fill Bottom Layers (integer): 1 -Number of Fill Top Layers (integer): 1 -Scale (pixels per millimeter): 15.0 -Screen Horizontal Inset (pixels): 100 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Viewpoint Latitude (degrees): 15.0 -Viewpoint Longitude (degrees): 210.0 -Width of Axis Negative Side (pixels): 2 -Width of Axis Positive Side (pixels): 6 -Width of Fill Bottom Thread (pixels): 2 -Width of Fill Top Thread (pixels): 2 -Width of Infill Thread (pixels): 1 -Width of Loop Thread (pixels): 2 -Width of Perimeter Inside Thread (pixels): 8 -Width of Perimeter Outside Thread (pixels): 8 -Width of Raft Thread (pixels): 1 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinlayer.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinlayer.csv deleted file mode 100644 index 5273776..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinlayer.csv +++ /dev/null @@ -1,23 +0,0 @@ -Format is tab separated skeinlayer settings. -_Name Value -WindowPosition 700+0 -Open File for Skeinlayer -Activate Skeinlayer True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Draw Arrows True -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 0 -Line (index): 430 -Display Line True -View Move False -Scale (pixels per millimeter): 25.0 -Screen Horizontal Inset (pixels): 100 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Show Position True -Width of Extrusion Thread (pixels): 3 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 1 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skin.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skin.csv deleted file mode 100644 index 9154030..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skin.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skin settings. -_Name Value -WindowPosition 700+0 -Open File for Skin -Activate Skin: this is experimental. -It prints the perimeters and loops only at half the layer height that is specified under carve. False -Clip Over Perimeter Width (scaler): 1.0 -Do Not Skin the first ... Layers: 3 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skirt.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skirt.csv deleted file mode 100644 index 80cd328..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skirt.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skirt settings. -_Name Value -WindowPosition 700+0 -Open File for Skirt -Activate Skirt: True -Convex: True -Gap over Perimeter Width (ratio): 5.0 -Layers To (index): 3 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/speed.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/speed.csv deleted file mode 100644 index e2685f3..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/speed.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated speed settings. -_Name Value -WindowPosition 700+0 -Open File for Speed -Activate Speed: True -Add Flow Rate: True -Main Feed Rate (mm/s): 60.0 -Main Flow Rate (scaler): 1.0 -Feed Rate ratio for Orbiting move (ratio): 0.5 -Perimeter Feed Rate (mm/s): 30.0 -Perimeter Flow Rate (scaler): 1.0 -Bridge Feed Rate (ratio): 1.0 -Bridge Flow Rate (scaler): 1.0 -Travel Feed Rate (mm/s): 130.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/statistic.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/statistic.csv deleted file mode 100644 index 4a1f127..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/statistic.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated statistic settings. -_Name Value -WindowPosition 700+0 -Activate Statistic True -Machine Time ($/hour): 1.0 -Material ($/kg): 20.0 -Density (kg/m3): 930.0 -Extrusion Diameter over Thickness (ratio): 1.25 -Open File to Generate Statistics for -Print Statistics True -Save Statistics False diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/stretch.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/stretch.csv deleted file mode 100644 index 5bc618d..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/stretch.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated stretch settings. -_Name Value -WindowPosition 700+0 -Open File for Stretch -Activate Stretch to correct for diameter shrink in small diameter holes False -Cross Limit Distance Over Perimeter Width (ratio): 5.0 -Loop Stretch Over Perimeter Width (ratio): 0.11 -Path Stretch Over Perimeter Width (ratio): 0.0 -Perimeter Inside Stretch Over Perimeter Width (ratio): 0.32 -Perimeter Outside Stretch Over Perimeter Width (ratio): 0.1 -Stretch From Distance Over Perimeter Width (ratio): 2.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/temperature.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/temperature.csv deleted file mode 100644 index ce2ef6e..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/temperature.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated temperature settings. -_Name Value -WindowPosition 700+0 -Open File for Temperature -Activate Temperature: False -Cooling Rate (Celcius/second): 3.0 -Heating Rate (Celcius/second): 3.0 -Base Temperature (Celcius): 210.0 -Interface Temperature (Celcius): 210.0 -Object First Layer Infill Temperature (Celcius): 210.0 -Object First Layer Perimeter Temperature (Celcius): 210.0 -Object Next Layers Temperature (Celcius): 210.0 -Support Layers Temperature (Celcius): 210.0 -Supported Layers Temperature (Celcius): 210.0 diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/vectorwrite.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/vectorwrite.csv deleted file mode 100644 index e03372b..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/vectorwrite.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated vectorwrite settings. -_Name Value -WindowPosition 700+0 -Activate Vectorwrite False -Open File to Write Vector Graphics for -Add Loops True -Add Paths True -Add Perimeters True -Layers From (index): 0 -Layers To (index): 912345678 -SVG Viewer: webbrowser diff --git a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/wipe.csv b/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/wipe.csv deleted file mode 100644 index 2533703..0000000 --- a/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/wipe.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated wipe settings. -_Name Value -WindowPosition 700+0 -Open File for Wipe -Activate Wipe False -Location Arrival X (mm): 0.0 -Location Arrival Y (mm): 5.0 -Location Arrival Z (mm): 0.0 -Location Departure X (mm): 5.0 -Location Departure Y (mm): 0.0 -Location Departure Z (mm): 0.0 -Location Wipe X (mm): 0.0 -Location Wipe Y (mm): 0.0 -Location Wipe Z (mm): 0.0 -Wipe Period (layers): 33333 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/bottom.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/bottom.csv deleted file mode 100644 index 0a24bd9..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/bottom.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated bottom settings. -_Name Value -WindowPosition 700+0 -Open File for Bottom -Activate Bottom... and dont change anything else here!!! True -Additional Height (ratio): 0.5 -Altitude (mm): 0.0 -SVG Viewer: webbrowser diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/carve.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/carve.csv deleted file mode 100644 index 03cd070..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/carve.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated carve settings. -_Name Value -WindowPosition 700+0 -Open File for Carve -Layer Height = Extrusion Thickness (mm): 0.33 -Extrusion Width (mm): 0.5 -Print from Layer No:: 0 -Print up to Layer No: 912345678 -Infill in Direction of Bridge True -Correct Mesh True -Unproven Mesh False -SVG Viewer: webbrowser -Add Layer Template to SVG True -Extra Decimal Places (float): 2.0 -Import Coarseness (ratio): 1.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/chamber.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/chamber.csv deleted file mode 100644 index 08ccd9c..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/chamber.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated chamber settings. -_Name Value -WindowPosition 700+0 -Open File for Chamber -Activate Chamber..if you want below functions to work True -Heated PrintBed Temperature (Celcius): 60.0 -Turn print Bed Heater Off at Shut Down True -Turn Extruder Heater Off at Shut Down True diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/clairvoyance.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/clairvoyance.csv deleted file mode 100644 index 8aadf4f..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/clairvoyance.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated clairvoyance settings. -_Name Value -WindowPosition 700+0 -Activate Clairvoyance False -Open File to Generate Clairvoyances for -Gcode Program: webbrowser diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/clip.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/clip.csv deleted file mode 100644 index c61adb8..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/clip.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated clip settings. -_Name Value -WindowPosition 700+0 -Open File for Clip -Activate Clip..to clip the extrusion that overlaps when printing perimeters True -Clip Over Perimeter Width adjuster (decrease for bigger gap): 1.0 -Threshold for connecting inner loops (ratio): 2.5 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/comb.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/comb.csv deleted file mode 100644 index 403d19b..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/comb.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated comb settings. -_Name Value -WindowPosition 700+0 -Open File for Comb -Activate Comb if you cant stop the extruder stringing by retraction -it will avoid moving over loops so the strings will be there -but not visible anymore. -Comb bends the extruder travel paths around holes in the slices, to avoid stringing. -so any start up ooze will be inside the shape. True diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/comment.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/comment.csv deleted file mode 100644 index c140205..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/comment.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated comment settings. -_Name Value -WindowPosition 700+0 -Activate Comment False -Open File to Write Comments for diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/cool.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/cool.csv deleted file mode 100644 index ed931a0..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/cool.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated cool settings. -_Name Value -WindowPosition 700+0 -Open File for Cool -Activate Cool.. but use with a fan! False -Use Cool if layer takes shorter than(seconds): 10.0 -Turn Fan On at Beginning True -Turn Fan Off at Ending True -Execute when Cool starts: cool_start.gmc -Execute when Cool ends: cool_end.gmc -Orbiting around Object False -Slow Down during print True -Maximum Cool (Celcius): 2.0 -Bridge Cool (Celcius): 1.0 -Minimum Orbital Radius (millimeters): 10.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/dimension.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/dimension.csv deleted file mode 100644 index 4c110d3..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/dimension.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated dimension settings. -_Name Value -WindowPosition 700+0 -Open File for Dimension -Activate Volumetric Extrusion (Stepper driven Extruders) True -Filament Diameter (mm): 2.85 -Filament Packing Density (ratio) lower=more extrusion: 1.0 -Retraction Distance (millimeters): 1.0 -Restart Extra Distance (millimeters): 0.0 -Extruder Retraction Speed (mm/s): 15.0 -Force to retract when crossing over spaces True -Minimum Extrusion before Retraction (millimeters): 1.0 -Minimum Travelmove after Retraction (millimeters): 1.0 -in Absolute units (Sprinter, FiveD a.o.) True -in Relative units (Teacup a.o.) False diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/export.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/export.csv deleted file mode 100644 index be5764b..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/export.csv +++ /dev/null @@ -1,20 +0,0 @@ -Format is tab separated export settings. -_Name Value -WindowPosition 700+0 -Open File for Export -Activate Export True -Add _export to filename (filename_export) True -Also Send Output To: -Do Not Delete Comments False -Delete Crafting Comments False -Delete All Comments True -Do Not Change Output False -gcode_small True -File Extension (gcode): gcode -Name of Replace File: replace.csv -Save Penultimate Gcode False -Archive Used Profile As Zip False -Export Profile Values As CSV File False -Add Profile Name to Filename False -Add Description to Filename False -Add Timestamp to Filename False diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/fill.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/fill.csv deleted file mode 100644 index 682b1eb..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/fill.csv +++ /dev/null @@ -1,34 +0,0 @@ -Format is tab separated fill settings. -_Name Value -WindowPosition 700+0 -Open File for Fill -Activate Fill: True -Infill Solidity (ratio): 0.35 -Extrusion Lines extra Spacing (Scaler): 1.0 -Infill Overlap over Perimeter (Scaler): 1.0 -Extra Shells on Alternating Solid Layer (layers): 1 -Extra Shells on Base (layers): 1 -Extra Shells on Sparse Layer (layers): 1 -Fully filled Layers (each top and bottom): 2 -Lower Left True -Nearest False -Infill > Loops > Perimeter False -Infill > Perimeter > Loops False -Loops > Infill > Perimeter False -Loops > Perimeter > Infill False -Perimeter > Infill > Loops False -Perimeter > Loops > Infill True -Line True -Grid Circular False -Grid Hexagonal False -Grid Rectangular False -Diaphragm at every ...th Layer: 100 -Diaphragm Thickness (layers): 0 -Grid Circle Separation over Perimeter Width (ratio): 0.2 -Grid Extra Overlap (ratio): 0.1 -Grid Junction Separation Band Height (layers): 10 -Grid Junction Separation over Octogon Radius At End (ratio): 0.0 -Grid Junction Separation over Octogon Radius At Middle (ratio): 0.0 -Infill Begin Rotation (degrees): 45.0 -Infill Begin Rotation Repeat (layers): 1 -Infill Odd Layer Extra Rotation (degrees): 90.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/home.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/home.csv deleted file mode 100644 index 430a33a..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/home.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated home settings. -_Name Value -WindowPosition 700+0 -Open File for Home -Activate Home ... Not needed True -Name of Homing File: homing.gcode diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/inset.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/inset.csv deleted file mode 100644 index 6c3d57c..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/inset.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated inset settings. -_Name Value -WindowPosition 700+0 -Open File for Inset -Bridge Width Multiplier (ratio): 1.0 -Prefer Loops False -Prefer Perimeter True -Overlap Removal(Scaler): 1.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/interpret.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/interpret.csv deleted file mode 100644 index 76cdc59..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/interpret.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated interpret settings. -_Name Value -WindowPosition 700+0 -Open File for Interpret -Activate Interpret False -Print Interpretion False -Text Program: webbrowser diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/jitter.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/jitter.csv deleted file mode 100644 index 781738d..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/jitter.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated jitter settings. -_Name Value -WindowPosition 700+0 -Open File for Jitter -Activate Jitter to have your perimeter and loop endpoints scattered False -Jitter Over Perimeter Width (ratio): 2.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/lash.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/lash.csv deleted file mode 100644 index 32ccb3b..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/lash.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated lash settings. -_Name Value -WindowPosition 700+0 -Open File for Lash -Activate Lash if you have backlash in your axes. -But its better to fix the mechanical problem! False -X Backlash (mm): 0.0 -Y Backlash (mm): 0.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/limit.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/limit.csv deleted file mode 100644 index 9671405..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/limit.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated limit settings. -_Name Value -WindowPosition 700+0 -Open File for Limit -Activate Limit if your Firmware is unable to Limiting your Z-Speed. False -Maximum Initial Feed Rate (mm/s): 5.0 -Maximum Z Feed Rate (mm/s): 5.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/multiply.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/multiply.csv deleted file mode 100644 index 269d53f..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/multiply.csv +++ /dev/null @@ -1,10 +0,0 @@ -Format is tab separated multiply settings. -_Name Value -WindowPosition 700+0 -Open File for Multiply -Activate Multiply: True -Center X (mm): 100.0 -Center Y (mm): 100.0 -Number of Columns (integer): 1 -Number of Rows (integer): 1 -Separation over Perimeter Width (ratio): 15.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/polyfile.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/polyfile.csv deleted file mode 100644 index 6e7d9bb..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/polyfile.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated polyfile settings. -_Name Value -WindowPosition 700+0 -Execute All Unmodified Files in a Directory False -Execute File True diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/preface.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/preface.csv deleted file mode 100644 index ff7f52f..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/preface.csv +++ /dev/null @@ -1,11 +0,0 @@ -_Name Value -Format is tab separated preface settings. -Home before Print False -Meta: -Name of End File: end.gmc -Name of Start File: start.gmc -Open File for Preface -Reset Extruder before Print True -Set Positioning to Absolute True -Set Units to Millimeters True -WindowPosition 700+0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/raft.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/raft.csv deleted file mode 100644 index 8d4b00a..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/raft.csv +++ /dev/null @@ -1,38 +0,0 @@ -Format is tab separated raft settings. -_Name Value -WindowPosition 700+0 -Open File for Raft -Activate Raft True -Add Raft, Elevate Nozzle, Orbit: True -None True -Empty Layers Only False -Everywhere False -Exterior Only False -Add support if flatter than (degrees): 50.0 -Cross Hatch instead of Lines False -Interface/Support Lines Density (ratio): 0.25 -Interface/Support Layer Thickness over Layer Thickness: 1.0 -Support Feed Rate mm/sec: 15.0 -Support Flow Rate (scaler): 1.0 -Support Gap over Perimeter Extrusion Width (ratio): 1.0 -Raft/Support extension in (%): 5.0 -Raft/Support extension in(mm): 2.0 -Name of Support End File: support_end.gmc -Name of Support Start File: support_start.gmc -Extra Nozzle clearance over Object(ratio): 0.0 -First Layer Main Feedrate (mm/s): 35.0 -First Layer Perimeter Feedrate (mm/s): 25.0 -First Layer Flow Rate Infill(scaler): 1.0 -First Layer Flow Rate Perimeter(scaler): 1.0 -Interface Layers (integer): 0 -Interface Feed Rate Multiplier (ratio): 1.0 -Interface Flow Rate Multiplier (ratio): 1.0 -Interface Nozzle Lift over Interface Layer Thickness (ratio): 0.45 -Base Layers (integer): 0 -Base Feed Rate Multiplier (ratio): 0.5 -Base Flow Rate Multiplier (ratio): 0.5 -Base Infill Density (ratio): 0.5 -Base Layer Thickness over Layer Thickness: 2.0 -Base Nozzle Lift over Base Layer Thickness (ratio): 0.4 -Initial Circling: False -Infill Overhang over Extrusion Width (ratio): 3.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/scale.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/scale.csv deleted file mode 100644 index a479f8b..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/scale.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated scale settings. -_Name Value -WindowPosition 700+0 -Open File for Scale -Activate Scale to finetune print size (try to find the fault somewhere else..): False -XY Plane Scale (ratio): 1.0 -Z Axis Scale (ratio): 1.0 -SVG Viewer: webbrowser diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge.csv deleted file mode 100644 index 22338a4..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated skeinforge settings. -_Name Value -WindowPosition 1187+2 -Open File for Skeinforge C:/Users/Ahmet/STL/_Screw Holder Bottom.stl -analyze False -craft True -help False -meta False -profile False diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_analyze.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_analyze.csv deleted file mode 100644 index 8826bcb..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_analyze.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated skeinforge analyze settings. -_Name Value -WindowPosition 600+0 -Open File for Analyze -clairvoyance False -comment False -interpret False -skeiniso True -skeinlayer False -statistic False -vectorwrite False diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_craft.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_craft.csv deleted file mode 100644 index 0943077..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_craft.csv +++ /dev/null @@ -1,27 +0,0 @@ -Format is tab separated skeinforge craft settings. -_Name Value -WindowPosition 600+0 -Open File for Craft -bottom False -carve False -chamber False -clip False -comb False -cool False -dimension True -export False -fill False -inset False -jitter False -lash False -limit False -multiply False -preface False -raft False -scale False -skin False -skirt False -speed False -stretch False -temperature False -wipe False diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_help.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_help.csv deleted file mode 100644 index 6447399..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_help.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated skeinforge help settings. -_Name Value -WindowPosition 600+0 -Wiki Manual Primary True diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeiniso.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeiniso.csv deleted file mode 100644 index a0bf075..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeiniso.csv +++ /dev/null @@ -1,41 +0,0 @@ -Format is tab separated skeiniso settings. -_Name Value -WindowPosition 700+0 -Open File for Skeiniso -Activate Skeiniso True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Axis Rulings True -Band Height (layers): 5 -Bottom Band Brightness (ratio): 0.7 -Bottom Layer Brightness (ratio): 1.0 -From the Bottom False -From the Top True -Draw Arrows False -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 912345678 -Line (index): 24 -Display Line True -View Move False -View Rotate False -Number of Fill Bottom Layers (integer): 1 -Number of Fill Top Layers (integer): 1 -Scale (pixels per millimeter): 15.0 -Screen Horizontal Inset (pixels): 100 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Viewpoint Latitude (degrees): 15.0 -Viewpoint Longitude (degrees): 210.0 -Width of Axis Negative Side (pixels): 2 -Width of Axis Positive Side (pixels): 6 -Width of Fill Bottom Thread (pixels): 2 -Width of Fill Top Thread (pixels): 2 -Width of Infill Thread (pixels): 1 -Width of Loop Thread (pixels): 2 -Width of Perimeter Inside Thread (pixels): 8 -Width of Perimeter Outside Thread (pixels): 8 -Width of Raft Thread (pixels): 1 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinlayer.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinlayer.csv deleted file mode 100644 index 5273776..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinlayer.csv +++ /dev/null @@ -1,23 +0,0 @@ -Format is tab separated skeinlayer settings. -_Name Value -WindowPosition 700+0 -Open File for Skeinlayer -Activate Skeinlayer True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Draw Arrows True -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 0 -Line (index): 430 -Display Line True -View Move False -Scale (pixels per millimeter): 25.0 -Screen Horizontal Inset (pixels): 100 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Show Position True -Width of Extrusion Thread (pixels): 3 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 1 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skin.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skin.csv deleted file mode 100644 index 9154030..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skin.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skin settings. -_Name Value -WindowPosition 700+0 -Open File for Skin -Activate Skin: this is experimental. -It prints the perimeters and loops only at half the layer height that is specified under carve. False -Clip Over Perimeter Width (scaler): 1.0 -Do Not Skin the first ... Layers: 3 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skirt.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skirt.csv deleted file mode 100644 index 80cd328..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skirt.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skirt settings. -_Name Value -WindowPosition 700+0 -Open File for Skirt -Activate Skirt: True -Convex: True -Gap over Perimeter Width (ratio): 5.0 -Layers To (index): 3 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/speed.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/speed.csv deleted file mode 100644 index e2685f3..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/speed.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated speed settings. -_Name Value -WindowPosition 700+0 -Open File for Speed -Activate Speed: True -Add Flow Rate: True -Main Feed Rate (mm/s): 60.0 -Main Flow Rate (scaler): 1.0 -Feed Rate ratio for Orbiting move (ratio): 0.5 -Perimeter Feed Rate (mm/s): 30.0 -Perimeter Flow Rate (scaler): 1.0 -Bridge Feed Rate (ratio): 1.0 -Bridge Flow Rate (scaler): 1.0 -Travel Feed Rate (mm/s): 130.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/statistic.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/statistic.csv deleted file mode 100644 index 4a1f127..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/statistic.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated statistic settings. -_Name Value -WindowPosition 700+0 -Activate Statistic True -Machine Time ($/hour): 1.0 -Material ($/kg): 20.0 -Density (kg/m3): 930.0 -Extrusion Diameter over Thickness (ratio): 1.25 -Open File to Generate Statistics for -Print Statistics True -Save Statistics False diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/stretch.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/stretch.csv deleted file mode 100644 index 5bc618d..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/stretch.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated stretch settings. -_Name Value -WindowPosition 700+0 -Open File for Stretch -Activate Stretch to correct for diameter shrink in small diameter holes False -Cross Limit Distance Over Perimeter Width (ratio): 5.0 -Loop Stretch Over Perimeter Width (ratio): 0.11 -Path Stretch Over Perimeter Width (ratio): 0.0 -Perimeter Inside Stretch Over Perimeter Width (ratio): 0.32 -Perimeter Outside Stretch Over Perimeter Width (ratio): 0.1 -Stretch From Distance Over Perimeter Width (ratio): 2.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/temperature.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/temperature.csv deleted file mode 100644 index ce2ef6e..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/temperature.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated temperature settings. -_Name Value -WindowPosition 700+0 -Open File for Temperature -Activate Temperature: False -Cooling Rate (Celcius/second): 3.0 -Heating Rate (Celcius/second): 3.0 -Base Temperature (Celcius): 210.0 -Interface Temperature (Celcius): 210.0 -Object First Layer Infill Temperature (Celcius): 210.0 -Object First Layer Perimeter Temperature (Celcius): 210.0 -Object Next Layers Temperature (Celcius): 210.0 -Support Layers Temperature (Celcius): 210.0 -Supported Layers Temperature (Celcius): 210.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/vectorwrite.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/vectorwrite.csv deleted file mode 100644 index e03372b..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/vectorwrite.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated vectorwrite settings. -_Name Value -WindowPosition 700+0 -Activate Vectorwrite False -Open File to Write Vector Graphics for -Add Loops True -Add Paths True -Add Perimeters True -Layers From (index): 0 -Layers To (index): 912345678 -SVG Viewer: webbrowser diff --git a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/wipe.csv b/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/wipe.csv deleted file mode 100644 index 2533703..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/wipe.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated wipe settings. -_Name Value -WindowPosition 700+0 -Open File for Wipe -Activate Wipe False -Location Arrival X (mm): 0.0 -Location Arrival Y (mm): 5.0 -Location Arrival Z (mm): 0.0 -Location Departure X (mm): 5.0 -Location Departure Y (mm): 0.0 -Location Departure Z (mm): 0.0 -Location Wipe X (mm): 0.0 -Location Wipe Y (mm): 0.0 -Location Wipe Z (mm): 0.0 -Wipe Period (layers): 33333 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/bottom.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/bottom.csv deleted file mode 100644 index 0a24bd9..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/bottom.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated bottom settings. -_Name Value -WindowPosition 700+0 -Open File for Bottom -Activate Bottom... and dont change anything else here!!! True -Additional Height (ratio): 0.5 -Altitude (mm): 0.0 -SVG Viewer: webbrowser diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/carve.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/carve.csv deleted file mode 100644 index 3a65503..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/carve.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated carve settings. -_Name Value -WindowPosition 700+0 -Open File for Carve -Layer Height = Extrusion Thickness (mm): 0.4 -Extrusion Width (mm): 0.6 -Print from Layer No:: 0 -Print up to Layer No: 912345678 -Infill in Direction of Bridge True -Correct Mesh True -Unproven Mesh False -SVG Viewer: webbrowser -Add Layer Template to SVG True -Extra Decimal Places (float): 2.0 -Import Coarseness (ratio): 1.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/chamber.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/chamber.csv deleted file mode 100644 index 08ccd9c..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/chamber.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated chamber settings. -_Name Value -WindowPosition 700+0 -Open File for Chamber -Activate Chamber..if you want below functions to work True -Heated PrintBed Temperature (Celcius): 60.0 -Turn print Bed Heater Off at Shut Down True -Turn Extruder Heater Off at Shut Down True diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/clairvoyance.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/clairvoyance.csv deleted file mode 100644 index 8aadf4f..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/clairvoyance.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated clairvoyance settings. -_Name Value -WindowPosition 700+0 -Activate Clairvoyance False -Open File to Generate Clairvoyances for -Gcode Program: webbrowser diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/clip.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/clip.csv deleted file mode 100644 index c61adb8..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/clip.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated clip settings. -_Name Value -WindowPosition 700+0 -Open File for Clip -Activate Clip..to clip the extrusion that overlaps when printing perimeters True -Clip Over Perimeter Width adjuster (decrease for bigger gap): 1.0 -Threshold for connecting inner loops (ratio): 2.5 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/comb.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/comb.csv deleted file mode 100644 index 403d19b..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/comb.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated comb settings. -_Name Value -WindowPosition 700+0 -Open File for Comb -Activate Comb if you cant stop the extruder stringing by retraction -it will avoid moving over loops so the strings will be there -but not visible anymore. -Comb bends the extruder travel paths around holes in the slices, to avoid stringing. -so any start up ooze will be inside the shape. True diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/comment.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/comment.csv deleted file mode 100644 index c140205..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/comment.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated comment settings. -_Name Value -WindowPosition 700+0 -Activate Comment False -Open File to Write Comments for diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/cool.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/cool.csv deleted file mode 100644 index ed931a0..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/cool.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated cool settings. -_Name Value -WindowPosition 700+0 -Open File for Cool -Activate Cool.. but use with a fan! False -Use Cool if layer takes shorter than(seconds): 10.0 -Turn Fan On at Beginning True -Turn Fan Off at Ending True -Execute when Cool starts: cool_start.gmc -Execute when Cool ends: cool_end.gmc -Orbiting around Object False -Slow Down during print True -Maximum Cool (Celcius): 2.0 -Bridge Cool (Celcius): 1.0 -Minimum Orbital Radius (millimeters): 10.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/dimension.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/dimension.csv deleted file mode 100644 index 4c110d3..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/dimension.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated dimension settings. -_Name Value -WindowPosition 700+0 -Open File for Dimension -Activate Volumetric Extrusion (Stepper driven Extruders) True -Filament Diameter (mm): 2.85 -Filament Packing Density (ratio) lower=more extrusion: 1.0 -Retraction Distance (millimeters): 1.0 -Restart Extra Distance (millimeters): 0.0 -Extruder Retraction Speed (mm/s): 15.0 -Force to retract when crossing over spaces True -Minimum Extrusion before Retraction (millimeters): 1.0 -Minimum Travelmove after Retraction (millimeters): 1.0 -in Absolute units (Sprinter, FiveD a.o.) True -in Relative units (Teacup a.o.) False diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/export.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/export.csv deleted file mode 100644 index be5764b..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/export.csv +++ /dev/null @@ -1,20 +0,0 @@ -Format is tab separated export settings. -_Name Value -WindowPosition 700+0 -Open File for Export -Activate Export True -Add _export to filename (filename_export) True -Also Send Output To: -Do Not Delete Comments False -Delete Crafting Comments False -Delete All Comments True -Do Not Change Output False -gcode_small True -File Extension (gcode): gcode -Name of Replace File: replace.csv -Save Penultimate Gcode False -Archive Used Profile As Zip False -Export Profile Values As CSV File False -Add Profile Name to Filename False -Add Description to Filename False -Add Timestamp to Filename False diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/fill.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/fill.csv deleted file mode 100644 index 682b1eb..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/fill.csv +++ /dev/null @@ -1,34 +0,0 @@ -Format is tab separated fill settings. -_Name Value -WindowPosition 700+0 -Open File for Fill -Activate Fill: True -Infill Solidity (ratio): 0.35 -Extrusion Lines extra Spacing (Scaler): 1.0 -Infill Overlap over Perimeter (Scaler): 1.0 -Extra Shells on Alternating Solid Layer (layers): 1 -Extra Shells on Base (layers): 1 -Extra Shells on Sparse Layer (layers): 1 -Fully filled Layers (each top and bottom): 2 -Lower Left True -Nearest False -Infill > Loops > Perimeter False -Infill > Perimeter > Loops False -Loops > Infill > Perimeter False -Loops > Perimeter > Infill False -Perimeter > Infill > Loops False -Perimeter > Loops > Infill True -Line True -Grid Circular False -Grid Hexagonal False -Grid Rectangular False -Diaphragm at every ...th Layer: 100 -Diaphragm Thickness (layers): 0 -Grid Circle Separation over Perimeter Width (ratio): 0.2 -Grid Extra Overlap (ratio): 0.1 -Grid Junction Separation Band Height (layers): 10 -Grid Junction Separation over Octogon Radius At End (ratio): 0.0 -Grid Junction Separation over Octogon Radius At Middle (ratio): 0.0 -Infill Begin Rotation (degrees): 45.0 -Infill Begin Rotation Repeat (layers): 1 -Infill Odd Layer Extra Rotation (degrees): 90.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/home.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/home.csv deleted file mode 100644 index 430a33a..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/home.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated home settings. -_Name Value -WindowPosition 700+0 -Open File for Home -Activate Home ... Not needed True -Name of Homing File: homing.gcode diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/inset.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/inset.csv deleted file mode 100644 index 6c3d57c..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/inset.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated inset settings. -_Name Value -WindowPosition 700+0 -Open File for Inset -Bridge Width Multiplier (ratio): 1.0 -Prefer Loops False -Prefer Perimeter True -Overlap Removal(Scaler): 1.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/interpret.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/interpret.csv deleted file mode 100644 index 76cdc59..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/interpret.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated interpret settings. -_Name Value -WindowPosition 700+0 -Open File for Interpret -Activate Interpret False -Print Interpretion False -Text Program: webbrowser diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/jitter.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/jitter.csv deleted file mode 100644 index 781738d..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/jitter.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated jitter settings. -_Name Value -WindowPosition 700+0 -Open File for Jitter -Activate Jitter to have your perimeter and loop endpoints scattered False -Jitter Over Perimeter Width (ratio): 2.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/lash.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/lash.csv deleted file mode 100644 index 32ccb3b..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/lash.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated lash settings. -_Name Value -WindowPosition 700+0 -Open File for Lash -Activate Lash if you have backlash in your axes. -But its better to fix the mechanical problem! False -X Backlash (mm): 0.0 -Y Backlash (mm): 0.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/limit.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/limit.csv deleted file mode 100644 index 9671405..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/limit.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated limit settings. -_Name Value -WindowPosition 700+0 -Open File for Limit -Activate Limit if your Firmware is unable to Limiting your Z-Speed. False -Maximum Initial Feed Rate (mm/s): 5.0 -Maximum Z Feed Rate (mm/s): 5.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/multiply.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/multiply.csv deleted file mode 100644 index 269d53f..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/multiply.csv +++ /dev/null @@ -1,10 +0,0 @@ -Format is tab separated multiply settings. -_Name Value -WindowPosition 700+0 -Open File for Multiply -Activate Multiply: True -Center X (mm): 100.0 -Center Y (mm): 100.0 -Number of Columns (integer): 1 -Number of Rows (integer): 1 -Separation over Perimeter Width (ratio): 15.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/polyfile.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/polyfile.csv deleted file mode 100644 index 6e7d9bb..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/polyfile.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated polyfile settings. -_Name Value -WindowPosition 700+0 -Execute All Unmodified Files in a Directory False -Execute File True diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/preface.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/preface.csv deleted file mode 100644 index 4c37dad..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/preface.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated preface settings. -_Name Value -WindowPosition 700+0 -Open File for Preface -Meta: -Name of End File: end.gmc -Name of Start File: start.gmc -Set Positioning to Absolute True -Set Units to Millimeters True -Home before Print False -Reset Extruder before Print True diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/raft.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/raft.csv deleted file mode 100644 index 8d4b00a..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/raft.csv +++ /dev/null @@ -1,38 +0,0 @@ -Format is tab separated raft settings. -_Name Value -WindowPosition 700+0 -Open File for Raft -Activate Raft True -Add Raft, Elevate Nozzle, Orbit: True -None True -Empty Layers Only False -Everywhere False -Exterior Only False -Add support if flatter than (degrees): 50.0 -Cross Hatch instead of Lines False -Interface/Support Lines Density (ratio): 0.25 -Interface/Support Layer Thickness over Layer Thickness: 1.0 -Support Feed Rate mm/sec: 15.0 -Support Flow Rate (scaler): 1.0 -Support Gap over Perimeter Extrusion Width (ratio): 1.0 -Raft/Support extension in (%): 5.0 -Raft/Support extension in(mm): 2.0 -Name of Support End File: support_end.gmc -Name of Support Start File: support_start.gmc -Extra Nozzle clearance over Object(ratio): 0.0 -First Layer Main Feedrate (mm/s): 35.0 -First Layer Perimeter Feedrate (mm/s): 25.0 -First Layer Flow Rate Infill(scaler): 1.0 -First Layer Flow Rate Perimeter(scaler): 1.0 -Interface Layers (integer): 0 -Interface Feed Rate Multiplier (ratio): 1.0 -Interface Flow Rate Multiplier (ratio): 1.0 -Interface Nozzle Lift over Interface Layer Thickness (ratio): 0.45 -Base Layers (integer): 0 -Base Feed Rate Multiplier (ratio): 0.5 -Base Flow Rate Multiplier (ratio): 0.5 -Base Infill Density (ratio): 0.5 -Base Layer Thickness over Layer Thickness: 2.0 -Base Nozzle Lift over Base Layer Thickness (ratio): 0.4 -Initial Circling: False -Infill Overhang over Extrusion Width (ratio): 3.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/scale.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/scale.csv deleted file mode 100644 index a479f8b..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/scale.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated scale settings. -_Name Value -WindowPosition 700+0 -Open File for Scale -Activate Scale to finetune print size (try to find the fault somewhere else..): False -XY Plane Scale (ratio): 1.0 -Z Axis Scale (ratio): 1.0 -SVG Viewer: webbrowser diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge.csv deleted file mode 100644 index 22338a4..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated skeinforge settings. -_Name Value -WindowPosition 1187+2 -Open File for Skeinforge C:/Users/Ahmet/STL/_Screw Holder Bottom.stl -analyze False -craft True -help False -meta False -profile False diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_analyze.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_analyze.csv deleted file mode 100644 index e9fca6c..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_analyze.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated skeinforge analyze settings. -_Name Value -WindowPosition 600+0 -Open File for Analyze -clairvoyance False -comment False -interpret False -skeiniso False -skeinlayer True -statistic False -vectorwrite False diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_craft.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_craft.csv deleted file mode 100644 index 0943077..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_craft.csv +++ /dev/null @@ -1,27 +0,0 @@ -Format is tab separated skeinforge craft settings. -_Name Value -WindowPosition 600+0 -Open File for Craft -bottom False -carve False -chamber False -clip False -comb False -cool False -dimension True -export False -fill False -inset False -jitter False -lash False -limit False -multiply False -preface False -raft False -scale False -skin False -skirt False -speed False -stretch False -temperature False -wipe False diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_help.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_help.csv deleted file mode 100644 index 6447399..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_help.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated skeinforge help settings. -_Name Value -WindowPosition 600+0 -Wiki Manual Primary True diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeiniso.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeiniso.csv deleted file mode 100644 index a0bf075..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeiniso.csv +++ /dev/null @@ -1,41 +0,0 @@ -Format is tab separated skeiniso settings. -_Name Value -WindowPosition 700+0 -Open File for Skeiniso -Activate Skeiniso True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Axis Rulings True -Band Height (layers): 5 -Bottom Band Brightness (ratio): 0.7 -Bottom Layer Brightness (ratio): 1.0 -From the Bottom False -From the Top True -Draw Arrows False -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 912345678 -Line (index): 24 -Display Line True -View Move False -View Rotate False -Number of Fill Bottom Layers (integer): 1 -Number of Fill Top Layers (integer): 1 -Scale (pixels per millimeter): 15.0 -Screen Horizontal Inset (pixels): 100 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Viewpoint Latitude (degrees): 15.0 -Viewpoint Longitude (degrees): 210.0 -Width of Axis Negative Side (pixels): 2 -Width of Axis Positive Side (pixels): 6 -Width of Fill Bottom Thread (pixels): 2 -Width of Fill Top Thread (pixels): 2 -Width of Infill Thread (pixels): 1 -Width of Loop Thread (pixels): 2 -Width of Perimeter Inside Thread (pixels): 8 -Width of Perimeter Outside Thread (pixels): 8 -Width of Raft Thread (pixels): 1 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinlayer.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinlayer.csv deleted file mode 100644 index c3101e1..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinlayer.csv +++ /dev/null @@ -1,23 +0,0 @@ -Format is tab separated skeinlayer settings. -_Name Value -WindowPosition 700+0 -Open File for Skeinlayer -Activate Skeinlayer True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Draw Arrows True -Go Around Extruder Off Travel False -Layer (index): 1 -Layer Extra Span (integer): 0 -Line (index): 724 -Display Line True -View Move False -Scale (pixels per millimeter): 70.0 -Screen Horizontal Inset (pixels): 102 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Show Position True -Width of Extrusion Thread (pixels): 3 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 1 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skin.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skin.csv deleted file mode 100644 index 9154030..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skin.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skin settings. -_Name Value -WindowPosition 700+0 -Open File for Skin -Activate Skin: this is experimental. -It prints the perimeters and loops only at half the layer height that is specified under carve. False -Clip Over Perimeter Width (scaler): 1.0 -Do Not Skin the first ... Layers: 3 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skirt.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skirt.csv deleted file mode 100644 index 80cd328..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skirt.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skirt settings. -_Name Value -WindowPosition 700+0 -Open File for Skirt -Activate Skirt: True -Convex: True -Gap over Perimeter Width (ratio): 5.0 -Layers To (index): 3 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/speed.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/speed.csv deleted file mode 100644 index e2685f3..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/speed.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated speed settings. -_Name Value -WindowPosition 700+0 -Open File for Speed -Activate Speed: True -Add Flow Rate: True -Main Feed Rate (mm/s): 60.0 -Main Flow Rate (scaler): 1.0 -Feed Rate ratio for Orbiting move (ratio): 0.5 -Perimeter Feed Rate (mm/s): 30.0 -Perimeter Flow Rate (scaler): 1.0 -Bridge Feed Rate (ratio): 1.0 -Bridge Flow Rate (scaler): 1.0 -Travel Feed Rate (mm/s): 130.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/statistic.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/statistic.csv deleted file mode 100644 index 4a1f127..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/statistic.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated statistic settings. -_Name Value -WindowPosition 700+0 -Activate Statistic True -Machine Time ($/hour): 1.0 -Material ($/kg): 20.0 -Density (kg/m3): 930.0 -Extrusion Diameter over Thickness (ratio): 1.25 -Open File to Generate Statistics for -Print Statistics True -Save Statistics False diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/stretch.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/stretch.csv deleted file mode 100644 index 5bc618d..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/stretch.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated stretch settings. -_Name Value -WindowPosition 700+0 -Open File for Stretch -Activate Stretch to correct for diameter shrink in small diameter holes False -Cross Limit Distance Over Perimeter Width (ratio): 5.0 -Loop Stretch Over Perimeter Width (ratio): 0.11 -Path Stretch Over Perimeter Width (ratio): 0.0 -Perimeter Inside Stretch Over Perimeter Width (ratio): 0.32 -Perimeter Outside Stretch Over Perimeter Width (ratio): 0.1 -Stretch From Distance Over Perimeter Width (ratio): 2.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/temperature.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/temperature.csv deleted file mode 100644 index ce2ef6e..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/temperature.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated temperature settings. -_Name Value -WindowPosition 700+0 -Open File for Temperature -Activate Temperature: False -Cooling Rate (Celcius/second): 3.0 -Heating Rate (Celcius/second): 3.0 -Base Temperature (Celcius): 210.0 -Interface Temperature (Celcius): 210.0 -Object First Layer Infill Temperature (Celcius): 210.0 -Object First Layer Perimeter Temperature (Celcius): 210.0 -Object Next Layers Temperature (Celcius): 210.0 -Support Layers Temperature (Celcius): 210.0 -Supported Layers Temperature (Celcius): 210.0 diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/vectorwrite.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/vectorwrite.csv deleted file mode 100644 index e03372b..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/vectorwrite.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated vectorwrite settings. -_Name Value -WindowPosition 700+0 -Activate Vectorwrite False -Open File to Write Vector Graphics for -Add Loops True -Add Paths True -Add Perimeters True -Layers From (index): 0 -Layers To (index): 912345678 -SVG Viewer: webbrowser diff --git a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/wipe.csv b/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/wipe.csv deleted file mode 100644 index 2533703..0000000 --- a/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/wipe.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated wipe settings. -_Name Value -WindowPosition 700+0 -Open File for Wipe -Activate Wipe False -Location Arrival X (mm): 0.0 -Location Arrival Y (mm): 5.0 -Location Arrival Z (mm): 0.0 -Location Departure X (mm): 5.0 -Location Departure Y (mm): 0.0 -Location Departure Z (mm): 0.0 -Location Wipe X (mm): 0.0 -Location Wipe Y (mm): 0.0 -Location Wipe Z (mm): 0.0 -Wipe Period (layers): 33333 diff --git a/sfact_profiles/profiles/extrusion/PLA/bottom.csv b/sfact_profiles/profiles/extrusion/PLA/bottom.csv deleted file mode 100644 index 0a24bd9..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/bottom.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated bottom settings. -_Name Value -WindowPosition 700+0 -Open File for Bottom -Activate Bottom... and dont change anything else here!!! True -Additional Height (ratio): 0.5 -Altitude (mm): 0.0 -SVG Viewer: webbrowser diff --git a/sfact_profiles/profiles/extrusion/PLA/carve.csv b/sfact_profiles/profiles/extrusion/PLA/carve.csv deleted file mode 100644 index 3a65503..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/carve.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated carve settings. -_Name Value -WindowPosition 700+0 -Open File for Carve -Layer Height = Extrusion Thickness (mm): 0.4 -Extrusion Width (mm): 0.6 -Print from Layer No:: 0 -Print up to Layer No: 912345678 -Infill in Direction of Bridge True -Correct Mesh True -Unproven Mesh False -SVG Viewer: webbrowser -Add Layer Template to SVG True -Extra Decimal Places (float): 2.0 -Import Coarseness (ratio): 1.0 diff --git a/sfact_profiles/profiles/extrusion/PLA/chamber.csv b/sfact_profiles/profiles/extrusion/PLA/chamber.csv deleted file mode 100644 index 049efbe..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/chamber.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated chamber settings. -_Name Value -WindowPosition 700+0 -Open File for Chamber -Activate Chamber..if you want below functions to work False -Heated PrintBed Temperature (Celcius): 60.0 -Turn print Bed Heater Off at Shut Down True -Turn Extruder Heater Off at Shut Down True diff --git a/sfact_profiles/profiles/extrusion/PLA/clairvoyance.csv b/sfact_profiles/profiles/extrusion/PLA/clairvoyance.csv deleted file mode 100644 index 8aadf4f..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/clairvoyance.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated clairvoyance settings. -_Name Value -WindowPosition 700+0 -Activate Clairvoyance False -Open File to Generate Clairvoyances for -Gcode Program: webbrowser diff --git a/sfact_profiles/profiles/extrusion/PLA/clip.csv b/sfact_profiles/profiles/extrusion/PLA/clip.csv deleted file mode 100644 index c61adb8..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/clip.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated clip settings. -_Name Value -WindowPosition 700+0 -Open File for Clip -Activate Clip..to clip the extrusion that overlaps when printing perimeters True -Clip Over Perimeter Width adjuster (decrease for bigger gap): 1.0 -Threshold for connecting inner loops (ratio): 2.5 diff --git a/sfact_profiles/profiles/extrusion/PLA/comb.csv b/sfact_profiles/profiles/extrusion/PLA/comb.csv deleted file mode 100644 index 403d19b..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/comb.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated comb settings. -_Name Value -WindowPosition 700+0 -Open File for Comb -Activate Comb if you cant stop the extruder stringing by retraction -it will avoid moving over loops so the strings will be there -but not visible anymore. -Comb bends the extruder travel paths around holes in the slices, to avoid stringing. -so any start up ooze will be inside the shape. True diff --git a/sfact_profiles/profiles/extrusion/PLA/comment.csv b/sfact_profiles/profiles/extrusion/PLA/comment.csv deleted file mode 100644 index c140205..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/comment.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated comment settings. -_Name Value -WindowPosition 700+0 -Activate Comment False -Open File to Write Comments for diff --git a/sfact_profiles/profiles/extrusion/PLA/cool.csv b/sfact_profiles/profiles/extrusion/PLA/cool.csv deleted file mode 100644 index ed931a0..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/cool.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated cool settings. -_Name Value -WindowPosition 700+0 -Open File for Cool -Activate Cool.. but use with a fan! False -Use Cool if layer takes shorter than(seconds): 10.0 -Turn Fan On at Beginning True -Turn Fan Off at Ending True -Execute when Cool starts: cool_start.gmc -Execute when Cool ends: cool_end.gmc -Orbiting around Object False -Slow Down during print True -Maximum Cool (Celcius): 2.0 -Bridge Cool (Celcius): 1.0 -Minimum Orbital Radius (millimeters): 10.0 diff --git a/sfact_profiles/profiles/extrusion/PLA/dimension.csv b/sfact_profiles/profiles/extrusion/PLA/dimension.csv deleted file mode 100644 index 26d06b8..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/dimension.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated dimension settings. -_Name Value -WindowPosition 700+0 -Open File for Dimension -Activate Volumetric Extrusion (Stepper driven Extruders) True -Filament Diameter (mm): 2.8 -Filament Packing Density (ratio) lower=more extrusion: 1.0 -Retraction Distance (millimeters): 1.0 -Restart Extra Distance (millimeters): 0.0 -Extruder Retraction Speed (mm/s): 15.0 -Force to retract when crossing over spaces True -Minimum Extrusion before Retraction (millimeters): 1.0 -Minimum Travelmove after Retraction (millimeters): 1.0 -in Absolute units (Sprinter, FiveD a.o.) True -in Relative units (Teacup a.o.) False diff --git a/sfact_profiles/profiles/extrusion/PLA/export.csv b/sfact_profiles/profiles/extrusion/PLA/export.csv deleted file mode 100644 index e709635..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/export.csv +++ /dev/null @@ -1,20 +0,0 @@ -Format is tab separated export settings. -_Name Value -WindowPosition 700+0 -Open File for Export -Activate Export True -Add _export to filename (filename_export) True -Also Send Output To: -Do Not Delete Comments False -Delete Crafting Comments False -Delete All Comments True -Do Not Change Output True -gcode_small False -File Extension (gcode): gcode -Name of Replace File: replace.csv -Save Penultimate Gcode False -Archive Used Profile As Zip False -Export Profile Values As CSV File False -Add Profile Name to Filename False -Add Description to Filename False -Add Timestamp to Filename False diff --git a/sfact_profiles/profiles/extrusion/PLA/fill.csv b/sfact_profiles/profiles/extrusion/PLA/fill.csv deleted file mode 100644 index 682b1eb..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/fill.csv +++ /dev/null @@ -1,34 +0,0 @@ -Format is tab separated fill settings. -_Name Value -WindowPosition 700+0 -Open File for Fill -Activate Fill: True -Infill Solidity (ratio): 0.35 -Extrusion Lines extra Spacing (Scaler): 1.0 -Infill Overlap over Perimeter (Scaler): 1.0 -Extra Shells on Alternating Solid Layer (layers): 1 -Extra Shells on Base (layers): 1 -Extra Shells on Sparse Layer (layers): 1 -Fully filled Layers (each top and bottom): 2 -Lower Left True -Nearest False -Infill > Loops > Perimeter False -Infill > Perimeter > Loops False -Loops > Infill > Perimeter False -Loops > Perimeter > Infill False -Perimeter > Infill > Loops False -Perimeter > Loops > Infill True -Line True -Grid Circular False -Grid Hexagonal False -Grid Rectangular False -Diaphragm at every ...th Layer: 100 -Diaphragm Thickness (layers): 0 -Grid Circle Separation over Perimeter Width (ratio): 0.2 -Grid Extra Overlap (ratio): 0.1 -Grid Junction Separation Band Height (layers): 10 -Grid Junction Separation over Octogon Radius At End (ratio): 0.0 -Grid Junction Separation over Octogon Radius At Middle (ratio): 0.0 -Infill Begin Rotation (degrees): 45.0 -Infill Begin Rotation Repeat (layers): 1 -Infill Odd Layer Extra Rotation (degrees): 90.0 diff --git a/sfact_profiles/profiles/extrusion/PLA/home.csv b/sfact_profiles/profiles/extrusion/PLA/home.csv deleted file mode 100644 index 430a33a..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/home.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated home settings. -_Name Value -WindowPosition 700+0 -Open File for Home -Activate Home ... Not needed True -Name of Homing File: homing.gcode diff --git a/sfact_profiles/profiles/extrusion/PLA/inset.csv b/sfact_profiles/profiles/extrusion/PLA/inset.csv deleted file mode 100644 index 6c3d57c..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/inset.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated inset settings. -_Name Value -WindowPosition 700+0 -Open File for Inset -Bridge Width Multiplier (ratio): 1.0 -Prefer Loops False -Prefer Perimeter True -Overlap Removal(Scaler): 1.0 diff --git a/sfact_profiles/profiles/extrusion/PLA/interpret.csv b/sfact_profiles/profiles/extrusion/PLA/interpret.csv deleted file mode 100644 index 76cdc59..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/interpret.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated interpret settings. -_Name Value -WindowPosition 700+0 -Open File for Interpret -Activate Interpret False -Print Interpretion False -Text Program: webbrowser diff --git a/sfact_profiles/profiles/extrusion/PLA/jitter.csv b/sfact_profiles/profiles/extrusion/PLA/jitter.csv deleted file mode 100644 index 781738d..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/jitter.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated jitter settings. -_Name Value -WindowPosition 700+0 -Open File for Jitter -Activate Jitter to have your perimeter and loop endpoints scattered False -Jitter Over Perimeter Width (ratio): 2.0 diff --git a/sfact_profiles/profiles/extrusion/PLA/lash.csv b/sfact_profiles/profiles/extrusion/PLA/lash.csv deleted file mode 100644 index 32ccb3b..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/lash.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated lash settings. -_Name Value -WindowPosition 700+0 -Open File for Lash -Activate Lash if you have backlash in your axes. -But its better to fix the mechanical problem! False -X Backlash (mm): 0.0 -Y Backlash (mm): 0.0 diff --git a/sfact_profiles/profiles/extrusion/PLA/limit.csv b/sfact_profiles/profiles/extrusion/PLA/limit.csv deleted file mode 100644 index 9671405..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/limit.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated limit settings. -_Name Value -WindowPosition 700+0 -Open File for Limit -Activate Limit if your Firmware is unable to Limiting your Z-Speed. False -Maximum Initial Feed Rate (mm/s): 5.0 -Maximum Z Feed Rate (mm/s): 5.0 diff --git a/sfact_profiles/profiles/extrusion/PLA/multiply.csv b/sfact_profiles/profiles/extrusion/PLA/multiply.csv deleted file mode 100644 index 269d53f..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/multiply.csv +++ /dev/null @@ -1,10 +0,0 @@ -Format is tab separated multiply settings. -_Name Value -WindowPosition 700+0 -Open File for Multiply -Activate Multiply: True -Center X (mm): 100.0 -Center Y (mm): 100.0 -Number of Columns (integer): 1 -Number of Rows (integer): 1 -Separation over Perimeter Width (ratio): 15.0 diff --git a/sfact_profiles/profiles/extrusion/PLA/polyfile.csv b/sfact_profiles/profiles/extrusion/PLA/polyfile.csv deleted file mode 100644 index 6e7d9bb..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/polyfile.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated polyfile settings. -_Name Value -WindowPosition 700+0 -Execute All Unmodified Files in a Directory False -Execute File True diff --git a/sfact_profiles/profiles/extrusion/PLA/preface.csv b/sfact_profiles/profiles/extrusion/PLA/preface.csv deleted file mode 100644 index a220066..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/preface.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated preface settings. -_Name Value -WindowPosition 700+0 -Open File for Preface -Meta: -Name of End File: end.gcode -Name of Start File: start.gcode -Set Positioning to Absolute True -Set Units to Millimeters True -Home before Print False -Reset Extruder before Print True diff --git a/sfact_profiles/profiles/extrusion/PLA/raft.csv b/sfact_profiles/profiles/extrusion/PLA/raft.csv deleted file mode 100644 index fdfc1a5..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/raft.csv +++ /dev/null @@ -1,38 +0,0 @@ -Format is tab separated raft settings. -_Name Value -WindowPosition 700+0 -Open File for Raft -Activate Raft True -Add Raft, Elevate Nozzle, Orbit: True -None True -Empty Layers Only False -Everywhere False -Exterior Only False -Add support if flatter than (degrees): 50.0 -Cross Hatch instead of Lines False -Interface/Support Lines Density (ratio): 0.25 -Interface/Support Layer Thickness over Layer Thickness: 1.0 -Support Feed Rate mm/sec: 15.0 -Support Flow Rate (scaler): 1.0 -Support Gap over Perimeter Extrusion Width (ratio): 1.0 -Raft/Support extension in (%): 5.0 -Raft/Support extension in(mm): 2.0 -Name of Support End File: support_end.gcode -Name of Support Start File: support_start.gcode -Extra Nozzle clearance over Object(ratio): 0.0 -First Layer Main Feedrate (mm/s): 35 -First Layer Perimeter Feedrate (mm/s): 25 -First Layer Flow Rate Infill(scaler): 1.0 -First Layer Flow Rate Perimeter(scaler): 1.0 -Interface Layers (integer): 0 -Interface Feed Rate Multiplier (ratio): 1.0 -Interface Flow Rate Multiplier (ratio): 1.0 -Interface Nozzle Lift over Interface Layer Thickness (ratio): 0.45 -Base Layers (integer): 0 -Base Feed Rate Multiplier (ratio): 0.5 -Base Flow Rate Multiplier (ratio): 0.5 -Base Infill Density (ratio): 0.5 -Base Layer Thickness over Layer Thickness: 2.0 -Base Nozzle Lift over Base Layer Thickness (ratio): 0.4 -Initial Circling: False -Infill Overhang over Extrusion Width (ratio): 3.0 diff --git a/sfact_profiles/profiles/extrusion/PLA/scale.csv b/sfact_profiles/profiles/extrusion/PLA/scale.csv deleted file mode 100644 index a479f8b..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/scale.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated scale settings. -_Name Value -WindowPosition 700+0 -Open File for Scale -Activate Scale to finetune print size (try to find the fault somewhere else..): False -XY Plane Scale (ratio): 1.0 -Z Axis Scale (ratio): 1.0 -SVG Viewer: webbrowser diff --git a/sfact_profiles/profiles/extrusion/PLA/skeinforge.csv b/sfact_profiles/profiles/extrusion/PLA/skeinforge.csv deleted file mode 100644 index b854c81..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/skeinforge.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated skeinforge settings. -_Name Value -WindowPosition 400+0 -Open File for Skeinforge -analyze False -craft True -help False -meta False -profile False diff --git a/sfact_profiles/profiles/extrusion/PLA/skeinforge_analyze.csv b/sfact_profiles/profiles/extrusion/PLA/skeinforge_analyze.csv deleted file mode 100644 index 8826bcb..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/skeinforge_analyze.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated skeinforge analyze settings. -_Name Value -WindowPosition 600+0 -Open File for Analyze -clairvoyance False -comment False -interpret False -skeiniso True -skeinlayer False -statistic False -vectorwrite False diff --git a/sfact_profiles/profiles/extrusion/PLA/skeinforge_craft.csv b/sfact_profiles/profiles/extrusion/PLA/skeinforge_craft.csv deleted file mode 100644 index 0943077..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/skeinforge_craft.csv +++ /dev/null @@ -1,27 +0,0 @@ -Format is tab separated skeinforge craft settings. -_Name Value -WindowPosition 600+0 -Open File for Craft -bottom False -carve False -chamber False -clip False -comb False -cool False -dimension True -export False -fill False -inset False -jitter False -lash False -limit False -multiply False -preface False -raft False -scale False -skin False -skirt False -speed False -stretch False -temperature False -wipe False diff --git a/sfact_profiles/profiles/extrusion/PLA/skeinforge_help.csv b/sfact_profiles/profiles/extrusion/PLA/skeinforge_help.csv deleted file mode 100644 index 6447399..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/skeinforge_help.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated skeinforge help settings. -_Name Value -WindowPosition 600+0 -Wiki Manual Primary True diff --git a/sfact_profiles/profiles/extrusion/PLA/skeiniso.csv b/sfact_profiles/profiles/extrusion/PLA/skeiniso.csv deleted file mode 100644 index dce1290..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/skeiniso.csv +++ /dev/null @@ -1,41 +0,0 @@ -Format is tab separated skeiniso settings. -_Name Value -WindowPosition 700+0 -Open File for Skeiniso -Activate Skeiniso True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Axis Rulings True -Band Height (layers): 5 -Bottom Band Brightness (ratio): 0.7 -Bottom Layer Brightness (ratio): 1.0 -From the Bottom False -From the Top True -Draw Arrows False -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 912345678 -Line (index): 7 -Display Line True -View Move False -View Rotate False -Number of Fill Bottom Layers (integer): 1 -Number of Fill Top Layers (integer): 1 -Scale (pixels per millimeter): 15.0 -Screen Horizontal Inset (pixels): 100 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Viewpoint Latitude (degrees): 15.0 -Viewpoint Longitude (degrees): 210.0 -Width of Axis Negative Side (pixels): 2 -Width of Axis Positive Side (pixels): 6 -Width of Fill Bottom Thread (pixels): 2 -Width of Fill Top Thread (pixels): 2 -Width of Infill Thread (pixels): 1 -Width of Loop Thread (pixels): 2 -Width of Perimeter Inside Thread (pixels): 8 -Width of Perimeter Outside Thread (pixels): 8 -Width of Raft Thread (pixels): 1 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 0 diff --git a/sfact_profiles/profiles/extrusion/PLA/skeinlayer.csv b/sfact_profiles/profiles/extrusion/PLA/skeinlayer.csv deleted file mode 100644 index ae7700f..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/skeinlayer.csv +++ /dev/null @@ -1,23 +0,0 @@ -Format is tab separated skeinlayer settings. -_Name Value -WindowPosition 700+0 -Open File for Skeinlayer -Activate Skeinlayer True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Draw Arrows True -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 0 -Line (index): 120 -Display Line True -View Move False -Scale (pixels per millimeter): 25.0 -Screen Horizontal Inset (pixels): 983 -Screen Vertical Inset (pixels): 292 -Show Gcode True -Show Position True -Width of Extrusion Thread (pixels): 3 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 1 diff --git a/sfact_profiles/profiles/extrusion/PLA/skin.csv b/sfact_profiles/profiles/extrusion/PLA/skin.csv deleted file mode 100644 index 9154030..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/skin.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skin settings. -_Name Value -WindowPosition 700+0 -Open File for Skin -Activate Skin: this is experimental. -It prints the perimeters and loops only at half the layer height that is specified under carve. False -Clip Over Perimeter Width (scaler): 1.0 -Do Not Skin the first ... Layers: 3 diff --git a/sfact_profiles/profiles/extrusion/PLA/skirt.csv b/sfact_profiles/profiles/extrusion/PLA/skirt.csv deleted file mode 100644 index 80cd328..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/skirt.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skirt settings. -_Name Value -WindowPosition 700+0 -Open File for Skirt -Activate Skirt: True -Convex: True -Gap over Perimeter Width (ratio): 5.0 -Layers To (index): 3 diff --git a/sfact_profiles/profiles/extrusion/PLA/speed.csv b/sfact_profiles/profiles/extrusion/PLA/speed.csv deleted file mode 100644 index 631ced7..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/speed.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated speed settings. -_Name Value -WindowPosition 700+0 -Open File for Speed -Activate Speed: True -Add Flow Rate: True -Main Feed Rate (mm/s): 75.0 -Main Flow Rate (scaler): 1.0 -Feed Rate ratio for Orbiting move (ratio): 0.5 -Perimeter Feed Rate (mm/s): 30.0 -Perimeter Flow Rate (scaler): 1.0 -Bridge Feed Rate (ratio): 1.0 -Bridge Flow Rate (scaler): 1.0 -Travel Feed Rate (mm/s): 130.0 diff --git a/sfact_profiles/profiles/extrusion/PLA/statistic.csv b/sfact_profiles/profiles/extrusion/PLA/statistic.csv deleted file mode 100644 index 4a1f127..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/statistic.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated statistic settings. -_Name Value -WindowPosition 700+0 -Activate Statistic True -Machine Time ($/hour): 1.0 -Material ($/kg): 20.0 -Density (kg/m3): 930.0 -Extrusion Diameter over Thickness (ratio): 1.25 -Open File to Generate Statistics for -Print Statistics True -Save Statistics False diff --git a/sfact_profiles/profiles/extrusion/PLA/stretch.csv b/sfact_profiles/profiles/extrusion/PLA/stretch.csv deleted file mode 100644 index 5bc618d..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/stretch.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated stretch settings. -_Name Value -WindowPosition 700+0 -Open File for Stretch -Activate Stretch to correct for diameter shrink in small diameter holes False -Cross Limit Distance Over Perimeter Width (ratio): 5.0 -Loop Stretch Over Perimeter Width (ratio): 0.11 -Path Stretch Over Perimeter Width (ratio): 0.0 -Perimeter Inside Stretch Over Perimeter Width (ratio): 0.32 -Perimeter Outside Stretch Over Perimeter Width (ratio): 0.1 -Stretch From Distance Over Perimeter Width (ratio): 2.0 diff --git a/sfact_profiles/profiles/extrusion/PLA/temperature.csv b/sfact_profiles/profiles/extrusion/PLA/temperature.csv deleted file mode 100644 index ce2ef6e..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/temperature.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated temperature settings. -_Name Value -WindowPosition 700+0 -Open File for Temperature -Activate Temperature: False -Cooling Rate (Celcius/second): 3.0 -Heating Rate (Celcius/second): 3.0 -Base Temperature (Celcius): 210.0 -Interface Temperature (Celcius): 210.0 -Object First Layer Infill Temperature (Celcius): 210.0 -Object First Layer Perimeter Temperature (Celcius): 210.0 -Object Next Layers Temperature (Celcius): 210.0 -Support Layers Temperature (Celcius): 210.0 -Supported Layers Temperature (Celcius): 210.0 diff --git a/sfact_profiles/profiles/extrusion/PLA/vectorwrite.csv b/sfact_profiles/profiles/extrusion/PLA/vectorwrite.csv deleted file mode 100644 index e03372b..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/vectorwrite.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated vectorwrite settings. -_Name Value -WindowPosition 700+0 -Activate Vectorwrite False -Open File to Write Vector Graphics for -Add Loops True -Add Paths True -Add Perimeters True -Layers From (index): 0 -Layers To (index): 912345678 -SVG Viewer: webbrowser diff --git a/sfact_profiles/profiles/extrusion/PLA/wipe.csv b/sfact_profiles/profiles/extrusion/PLA/wipe.csv deleted file mode 100644 index 2533703..0000000 --- a/sfact_profiles/profiles/extrusion/PLA/wipe.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated wipe settings. -_Name Value -WindowPosition 700+0 -Open File for Wipe -Activate Wipe False -Location Arrival X (mm): 0.0 -Location Arrival Y (mm): 5.0 -Location Arrival Z (mm): 0.0 -Location Departure X (mm): 5.0 -Location Departure Y (mm): 0.0 -Location Departure Z (mm): 0.0 -Location Wipe X (mm): 0.0 -Location Wipe Y (mm): 0.0 -Location Wipe Z (mm): 0.0 -Wipe Period (layers): 33333 diff --git a/sfact_profiles/profiles/milling.csv b/sfact_profiles/profiles/milling.csv deleted file mode 100644 index 5dd4bbc..0000000 --- a/sfact_profiles/profiles/milling.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated milling settings. -_Name Value -WindowPosition 0+400 -Profile Selection: End_Mill diff --git a/sfact_profiles/profiles/skeinforge_profile.csv b/sfact_profiles/profiles/skeinforge_profile.csv deleted file mode 100644 index 48bb0a0..0000000 --- a/sfact_profiles/profiles/skeinforge_profile.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated skeinforge profile settings. -_Name Value -WindowPosition 0+200 -cutting False -extrusion True -milling False -winding False diff --git a/sfact_profiles/profiles/winding.csv b/sfact_profiles/profiles/winding.csv deleted file mode 100644 index a20384b..0000000 --- a/sfact_profiles/profiles/winding.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated winding settings. -_Name Value -WindowPosition 0+400 -Profile Selection: free_wire diff --git a/skeinforge/.gitignore b/skeinforge/.gitignore deleted file mode 100644 index 17b7926..0000000 --- a/skeinforge/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*.pyc -*.gcode -priv_* -zzz* \ No newline at end of file diff --git a/skeinforge/G-code - RepRapWiki.pdf b/skeinforge/G-code - RepRapWiki.pdf deleted file mode 100644 index 1c40de0..0000000 Binary files a/skeinforge/G-code - RepRapWiki.pdf and /dev/null differ diff --git a/skeinforge/SF_Primer.xls b/skeinforge/SF_Primer.xls deleted file mode 100644 index 57a3a07..0000000 Binary files a/skeinforge/SF_Primer.xls and /dev/null differ diff --git a/skeinforge/__init__.py b/skeinforge/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/skeinforge/fabmetheus.kdevelop b/skeinforge/fabmetheus.kdevelop deleted file mode 100644 index f88825c..0000000 --- a/skeinforge/fabmetheus.kdevelop +++ /dev/null @@ -1,106 +0,0 @@ - - - - enrique - perez_enrique@yahoo.com - 1 - KDevScriptProject - Python - - fabmetheus - . - false - - - - - - - executable - - - *.py,*.xml - *~,*.pyc - - - - - bash - bash_bugs - c++_bugs_gcc - clanlib - w3c-dom-level2-html - fortran_bugs_gcc - gnome1 - gnustep - gtk - gtk_bugs - haskell - haskell_bugs_ghc - java_bugs_gcc - java_bugs_sun - kde2book - libc - libstdc++ - opengl - pascal_bugs_fp - php - php_bugs - perl - perl_bugs - qt-kdev3 - ruby - ruby_bugs - sdl - stl - w3c-svg - sw - w3c-uaag10 - wxwidgets_bugs - - - Guide to the Qt Translation Tools - Qt Assistant Manual - Qt Designer Manual - Qt Reference Documentation - qmake User Guide - - - KDE Libraries (Doxygen) - - - - - - - - - - - false - false - - - *.o,*.lo,CVS,*.pyc,*~ - false - - - - - python - true - - - - - - - - - - - - /home/enrique/Desktop/backup/babbleold/script/reprap/fabmetheus/tags - - - diff --git a/skeinforge/fabmetheus.kdevses b/skeinforge/fabmetheus.kdevses deleted file mode 100644 index 80c7f2c..0000000 --- a/skeinforge/fabmetheus.kdevses +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/fabmetheus_utilities/__init__.py b/skeinforge/fabmetheus_utilities/__init__.py deleted file mode 100644 index 1638033..0000000 --- a/skeinforge/fabmetheus_utilities/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -""" -This page is in the table of contents. -This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -""" -import os -import sys - -numberOfLevelsDeepInPackageHierarchy = 1 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/archive.py b/skeinforge/fabmetheus_utilities/archive.py deleted file mode 100644 index 97d9e84..0000000 --- a/skeinforge/fabmetheus_utilities/archive.py +++ /dev/null @@ -1,361 +0,0 @@ -""" -Boolean geometry utilities. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -import os -import sys -import traceback - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalTemporarySettingsPath = os.path.join(os.getcwd(), 'sfact_profiles') - -def addToNamePathDictionary(directoryPath, namePathDictionary): - """Add to the name path dictionary.""" - pluginFileNames = getPluginFileNamesFromDirectoryPath(directoryPath) - for pluginFileName in pluginFileNames: - namePathDictionary[pluginFileName.replace('_', '')] = os.path.join(directoryPath, pluginFileName) - -def getAbsoluteFolderPath(filePath, folderName=''): - """Get the absolute folder path.""" - absoluteFolderPath = os.path.dirname(os.path.abspath(filePath)) - if folderName == '': - return absoluteFolderPath - return os.path.join(absoluteFolderPath, folderName) - -def getAbsoluteFrozenFolderPath(filePath, folderName=''): - """Get the absolute frozen folder path.""" - if hasattr(sys, 'frozen'): - if '.py' in filePath: - filePath = ''.join(filePath.rpartition('\\')[: 2]) - filePath = os.path.join(filePath, 'skeinforge_application') - return getAbsoluteFolderPath(filePath, folderName) - -def getDocumentationPath(subName=''): - """Get the documentation file path.""" - return getJoinedPath(getFabmetheusPath('documentation'), subName) - -def getElementsPath(subName=''): - """Get the evaluate_elements directory path.""" - return getJoinedPath(getGeometryUtilitiesPath('evaluate_elements'), subName) - -def getEndsWithList(word, wordEndings): - """Determine if the word ends with a list.""" - for wordEnding in wordEndings: - if word.endswith(wordEnding): - return True - return False - -def getFabmetheusPath(subName=''): - """Get the fabmetheus directory path.""" - fabmetheusFile = None - if hasattr(sys, 'frozen'): - fabmetheusFile = unicode(sys.executable, sys.getfilesystemencoding()) - else: - fabmetheusFile = os.path.dirname(os.path.abspath(__file__)) - return getJoinedPath(os.path.dirname(fabmetheusFile), subName) - -def getFabmetheusUtilitiesPath(subName=''): - """Get the fabmetheus utilities directory path.""" - return getJoinedPath(getFabmetheusPath('fabmetheus_utilities'), subName) - -def getFileNamesByFilePaths(pluginFilePaths): - """Get the file names of the plugins by the file paths.""" - fileNames = [] - for pluginFilePath in pluginFilePaths: - pluginBasename = os.path.basename(pluginFilePath) - pluginBasename = getUntilDot(pluginBasename) - fileNames.append(pluginBasename) - return fileNames - -def getFilePaths(fileInDirectory=''): - """Get the file paths in the directory of the file in directory.""" - directoryName = os.getcwd() - if fileInDirectory != '': - directoryName = os.path.dirname(fileInDirectory) - return getFilePathsByDirectory(directoryName) - -def getFilePathsByDirectory(directoryName): - """Get the file paths in the directory of the file in directory.""" - absoluteDirectoryPath = os.path.abspath(directoryName) - directory = os.listdir(directoryName) - filePaths = [] - for fileName in directory: - filePaths.append(os.path.join(absoluteDirectoryPath, fileName)) - return filePaths - -def getFilePathsRecursively(fileInDirectory=''): - """Get the file paths in the directory of the file in directory.""" - filePaths = getFilePaths(fileInDirectory) - filePathsRecursively = filePaths[:] - for filePath in filePaths: - if os.path.isdir(filePath): - directory = os.listdir(filePath) - if len(directory) > 0: - filePathsRecursively += getFilePathsRecursively(os.path.join(filePath, directory[0])) - return filePathsRecursively - -def getFilePathWithUnderscoredBasename(fileName, suffix): - """Get the file path with all spaces in the basename replaced with underscores.""" - suffixFileName = getUntilDot(fileName) + suffix - suffixDirectoryName = os.path.dirname(suffixFileName) - suffixReplacedBaseName = os.path.basename(suffixFileName).replace(' ', '_') - return os.path.join(suffixDirectoryName, suffixReplacedBaseName) - -def getFileText(fileName, printWarning=True, readMode='r'): - """Get the entire text of a file.""" - try: - file = open(fileName, readMode) - fileText = file.read() - file.close() - return fileText - except IOError: - if printWarning: - print('The file ' + fileName + ' does not exist.') - return '' - -def getFileTextInFileDirectory(fileInDirectory, fileName, readMode='r'): - """Get the entire text of a file in the directory of the file in directory.""" - absoluteFilePathInFileDirectory = os.path.join(os.path.dirname(fileInDirectory), fileName) - return getFileText(absoluteFilePathInFileDirectory, True, readMode) - -def getFilesWithFileTypesWithoutWords(fileTypes, words = [], fileInDirectory=''): - """Get files which have a given file type, but with do not contain a word in a list.""" - filesWithFileTypes = [] - for filePath in getFilePaths(fileInDirectory): - for fileType in fileTypes: - if isFileWithFileTypeWithoutWords(fileType, filePath, words): - filesWithFileTypes.append(filePath) - filesWithFileTypes.sort() - return filesWithFileTypes - -def getFilesWithFileTypesWithoutWordsRecursively(fileTypes, words = [], fileInDirectory=''): - """Get files recursively which have a given file type, but with do not contain a word in a list.""" - filesWithFileTypesRecursively = [] - for filePath in getFilePathsRecursively(fileInDirectory): - for fileType in fileTypes: - if isFileWithFileTypeWithoutWords(fileType, filePath, words): - filesWithFileTypesRecursively.append(filePath) - filesWithFileTypesRecursively.sort() - return filesWithFileTypesRecursively - -def getFilesWithFileTypeWithoutWords(fileType, words = [], fileInDirectory=''): - """Get files which have a given file type, but with do not contain a word in a list.""" - filesWithFileType = [] - for filePath in getFilePaths(fileInDirectory): - if isFileWithFileTypeWithoutWords(fileType, filePath, words): - filesWithFileType.append(filePath) - filesWithFileType.sort() - return filesWithFileType - -def getFundamentalsPath(subName=''): - """Get the evaluate_fundamentals directory path.""" - return getJoinedPath(getGeometryUtilitiesPath('evaluate_fundamentals'), subName) - -def getGeometryDictionary(folderName): - """Get to the geometry name path dictionary.""" - geometryDictionary={} - geometryDirectory = getGeometryPath() - addToNamePathDictionary(os.path.join(geometryDirectory, folderName), geometryDictionary) - geometryPluginsDirectory = getFabmetheusUtilitiesPath('geometry_plugins') - addToNamePathDictionary(os.path.join(geometryPluginsDirectory, folderName), geometryDictionary) - return geometryDictionary - -def getGeometryPath(subName=''): - """Get the geometry directory path.""" - return getJoinedPath(getFabmetheusUtilitiesPath('geometry'), subName) - -def getGeometryToolsPath(subName=''): - """Get the geometry tools directory path.""" - return getJoinedPath(getGeometryPath('geometry_tools'), subName) - -def getGeometryUtilitiesPath(subName=''): - """Get the geometry_utilities directory path.""" - return getJoinedPath(getGeometryPath('geometry_utilities'), subName) - -def getJoinedPath(path, subName=''): - """Get the joined file path.""" - if subName == '': - return path - return os.path.join(path, subName) - -def getModuleWithDirectoryPath(directoryPath, fileName): - """Get the module from the fileName and folder name.""" - if fileName == '': - print('The file name in getModule in archive was empty.') - return None - originalSystemPath = sys.path[:] - try: - sys.path.insert(0, directoryPath) - folderPluginsModule = __import__(fileName) - sys.path = originalSystemPath - return folderPluginsModule - except: - sys.path = originalSystemPath - print('') - print('Exception traceback in getModuleWithDirectoryPath in archive:') - traceback.print_exc(file=sys.stdout) - print('') - print('That error means; could not import a module with the fileName ' + fileName) - print('and an absolute directory name of ' + directoryPath) - print('') - return None - -def getModuleWithPath(path): - """Get the module from the path.""" - return getModuleWithDirectoryPath(os.path.dirname(path), os.path.basename(path)) - -def getPluginFileNamesFromDirectoryPath(directoryPath): - """Get the file names of the python plugins in the directory path.""" - fileInDirectory = os.path.join(directoryPath, '__init__.py') - return getFileNamesByFilePaths(getPythonFileNamesExceptInit(fileInDirectory)) - -def getProfilesPath(subName=''): - """Get the profiles directory path, which is the settings directory joined with profiles.""" - return getJoinedPath(getSettingsPath('profiles'), subName) - -def getPythonDirectoryNames(directoryName): - """Get the python directories.""" - pythonDirectoryNames = [] - directory = os.listdir(directoryName) - for fileName in directory: - subdirectoryName = os.path.join(directoryName, fileName) - if os.path.isdir(subdirectoryName): - if os.path.isfile(os.path.join(subdirectoryName, '__init__.py')): - pythonDirectoryNames.append(subdirectoryName) - return pythonDirectoryNames - -def getPythonDirectoryNamesRecursively(directoryName=''): - """Get the python directories recursively.""" - recursivePythonDirectoryNames = [] - if directoryName == '': - directoryName = os.getcwd() - if os.path.isfile(os.path.join(directoryName, '__init__.py')): - recursivePythonDirectoryNames.append(directoryName) - pythonDirectoryNames = getPythonDirectoryNames(directoryName) - for pythonDirectoryName in pythonDirectoryNames: - recursivePythonDirectoryNames += getPythonDirectoryNamesRecursively(pythonDirectoryName) - else: - return [] - return recursivePythonDirectoryNames - -def getPythonFileNamesExceptInit(fileInDirectory=''): - """Get the python fileNames of the directory which the fileInDirectory is in, except for the __init__.py file.""" - pythonFileNamesExceptInit = getFilesWithFileTypeWithoutWords('py', ['__init__.py'], fileInDirectory) - pythonFileNamesExceptInit.sort() - return pythonFileNamesExceptInit - -def getPythonFileNamesExceptInitRecursively(directoryName=''): - """Get the python fileNames of the directory recursively, except for the __init__.py files.""" - pythonDirectoryNames = getPythonDirectoryNamesRecursively(directoryName) - pythonFileNamesExceptInitRecursively = [] - for pythonDirectoryName in pythonDirectoryNames: - pythonFileNamesExceptInitRecursively += getPythonFileNamesExceptInit(os.path.join(pythonDirectoryName, '__init__.py')) - pythonFileNamesExceptInitRecursively.sort() - return pythonFileNamesExceptInitRecursively - -def getSettingsPath(subName=''): - """Get the settings directory path, which is the home directory joined with .skeinforge.""" - global globalTemporarySettingsPath - return getJoinedPath(globalTemporarySettingsPath, subName) - -def getSkeinforgePath(subName=''): - """Get the skeinforge directory path.""" - return getJoinedPath(getFabmetheusPath('skeinforge_application'), subName) - -def getSkeinforgePluginsPath(subName=''): - """Get the skeinforge plugins directory path.""" - return getJoinedPath(getSkeinforgePath('skeinforge_plugins'), subName) - -def getSummarizedFileName(fileName): - """Get the fileName basename if the file is in the current working directory, otherwise return the original full name.""" - if os.getcwd() == os.path.dirname(fileName): - return os.path.basename(fileName) - return fileName - -def getTemplatesPath(subName=''): - """Get the templates directory path.""" - return getJoinedPath(getFabmetheusUtilitiesPath('templates'), subName) - -def getTextIfEmpty(fileName, text): - """Get the text from a file if it the text is empty.""" - if text != '': - return text - return getFileText(fileName) - -def getTextLines(text): - """Get the all the lines of text of a text.""" - textLines = text.replace('\r', '\n').replace('\n\n', '\n').split('\n') - if len(textLines) == 1: - if textLines[0] == '': - return [] - return textLines - -def getUntilDot(text): - """Get the text until the last dot, if any.""" - dotIndex = text.rfind('.') - if dotIndex < 0: - return text - return text[: dotIndex] - -def getVersionFileName(): - """Get the file name of the version date.getFabmetheusUtilitiesPath(subName='')""" - return getFabmetheusUtilitiesPath('version.txt') - -def isFileWithFileTypeWithoutWords(fileType, fileName, words): - """Determine if file has a given file type, but with does not contain a word in a list.""" - fileName = os.path.basename(fileName) - fileTypeDot = '.' + fileType - if not fileName.endswith(fileTypeDot): - return False - for word in words: - if fileName.find(word) >= 0: - return False - return True - -def makeDirectory(directory): - """Make a directory if it does not already exist.""" - if os.path.isdir(directory): - return - try: - print('The following directory was made:') - print(os.path.abspath(directory)) - os.makedirs(directory) - except OSError: - print('Skeinforge can not make the directory %s so give it read/write permission for that directory and the containing directory.' % directory) - -def removeBackupFilesByType(fileType): - """Remove backup files by type.""" - backupFilePaths = getFilesWithFileTypesWithoutWordsRecursively([fileType + '~']) - for backupFilePath in backupFilePaths: - os.remove(backupFilePath) - -def removeBackupFilesByTypes(fileTypes): - """Remove backup files by types.""" - for fileType in fileTypes: - removeBackupFilesByType(fileType) - -def writeFileMessageEnd(end, fileName, fileText, message): - """Write to a fileName with a suffix and print a message.""" - suffixFileName = getUntilDot(fileName) + end - writeFileText(suffixFileName, fileText) - print( message + getSummarizedFileName(suffixFileName) ) - -def writeFileText(fileName, fileText, writeMode='w+'): - """Write a text to a file.""" - try: - file = open(fileName, writeMode) - file.write(fileText) - file.close() - except IOError: - print('The file ' + fileName + ' can not be written to.') diff --git a/skeinforge/fabmetheus_utilities/euclidean.py b/skeinforge/fabmetheus_utilities/euclidean.py deleted file mode 100644 index 1cbfefc..0000000 --- a/skeinforge/fabmetheus_utilities/euclidean.py +++ /dev/null @@ -1,2568 +0,0 @@ -""" -Euclidean is a collection of python utilities for complex numbers, paths, polygons & Vector3s. - -To use euclidean, install python 2.x on your machine, which is avaliable from http://www.python.org/download/ - -Then in the folder which euclidean is in, type 'python' in a shell to run the python interpreter. Finally type 'import euclidean' to import these utilities and 'from vector3 import Vector3' to import the Vector3 class. - - -Below are examples of euclidean use. - ->>> from euclidean import * ->>> origin=complex() ->>> right=complex(1.0,0.0) ->>> back=complex(0.0,1.0) ->>> getMaximum(right,back) -1.0, 1.0 ->>> polygon=[origin, right, back] ->>> getLoopLength(polygon) -3.4142135623730949 ->>> getAreaLoop(polygon) -0.5 -""" - -from __future__ import absolute_import -try: - import psyco - psyco.full() -except: - pass -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import xml_simple_writer -import cStringIO -import math -import random - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalGoldenAngle = 3.8832220774509332 # (math.sqrt(5.0) - 1.0) * math.pi -globalGoldenRatio = 1.6180339887498948482045868 # math.sqrt(1.25) - .5 -globalTau = math.pi + math.pi # http://tauday.com/ - - -def addElementToListDictionary(element, key, listDictionary): - """Add an element to the list table.""" - if key in listDictionary: - listDictionary[key].append(element) - else: - listDictionary[key] = [element] - -def addElementToListDictionaryIfNotThere(element, key, listDictionary): - """Add the value to the lists.""" - if key in listDictionary: - elements = listDictionary[key] - if element not in elements: - elements.append(element) - else: - listDictionary[key] = [element] - -def addElementToPixelList( element, pixelDictionary, x, y ): - """Add an element to the pixel list.""" - stepKey = getStepKey(x, y) - addElementToListDictionary( element, stepKey, pixelDictionary ) - -def addElementToPixelListFromPoint( element, pixelDictionary, point ): - """Add an element to the pixel list.""" - addElementToPixelList( element, pixelDictionary, int( round( point.real ) ), int( round( point.imag ) ) ) - -def addHorizontallyBoundedPoint(begin, center, end, horizontalBegin, horizontalEnd, path): - """Add point if it is within the horizontal bounds.""" - if center.real >= horizontalEnd and center.real <= horizontalBegin: - path.append(center) - return - if end is not None: - if center.real > horizontalBegin and end.real <= horizontalBegin: - centerMinusEnd = center - end - along = (center.real - horizontalBegin) / centerMinusEnd.real - path.append(center - along * centerMinusEnd) - return - if begin is not None: - if center.real < horizontalEnd and begin.real >= horizontalEnd: - centerMinusBegin = center - begin - along = (center.real - horizontalEnd) / centerMinusBegin.real - path.append(center - along * centerMinusBegin) - -def addListToListTable( elementList, key, listDictionary ): - """Add a list to the list table.""" - if key in listDictionary: - listDictionary[key] += elementList - else: - listDictionary[key] = elementList - -def addLoopToPixelTable( loop, pixelDictionary, width ): - """Add loop to the pixel table.""" - for pointIndex in xrange(len(loop)): - pointBegin = loop[pointIndex] - pointEnd = loop[(pointIndex + 1) % len(loop)] - addValueSegmentToPixelTable( pointBegin, pointEnd, pixelDictionary, None, width ) - -def addPathToPixelTable( path, pixelDictionary, value, width ): - """Add path to the pixel table.""" - for pointIndex in xrange( len(path) - 1 ): - pointBegin = path[pointIndex] - pointEnd = path[pointIndex + 1] - addValueSegmentToPixelTable( pointBegin, pointEnd, pixelDictionary, value, width ) - -def addPixelTableToPixelTable( fromPixelTable, intoPixelTable ): - """Add from pixel table to the into pixel table.""" - for fromPixelTableKey in fromPixelTable.keys(): - intoPixelTable[ fromPixelTableKey ] = fromPixelTable[ fromPixelTableKey ] - -def addPixelToPixelTable( pixelDictionary, value, x, y ): - """Add pixel to the pixel table.""" - pixelDictionary[getStepKey(x, y)] = value - -def addPixelToPixelTableWithSteepness( isSteep, pixelDictionary, value, x, y ): - """Add pixels to the pixel table with steepness.""" - if isSteep: - addPixelToPixelTable( pixelDictionary, value, y, x ) - else: - addPixelToPixelTable( pixelDictionary, value, x, y ) - -def addPointToPath( path, pixelDictionary, point, value, width ): - """Add a point to a path and the pixel table.""" - path.append(point) - if len(path) < 2: - return - begin = path[-2] - addValueSegmentToPixelTable( begin, point, pixelDictionary, value, width ) - -def addSegmentToPixelTable( beginComplex, endComplex, pixelDictionary, shortenDistanceBegin, shortenDistanceEnd, width ): - """Add line segment to the pixel table.""" - if abs( beginComplex - endComplex ) <= 0.0: - return - beginComplex /= width - endComplex /= width - if shortenDistanceBegin > 0.0: - endMinusBeginComplex = endComplex - beginComplex - endMinusBeginComplexLength = abs( endMinusBeginComplex ) - if endMinusBeginComplexLength < shortenDistanceBegin: - return - beginComplex = beginComplex + endMinusBeginComplex * shortenDistanceBegin / endMinusBeginComplexLength - if shortenDistanceEnd > 0.0: - beginMinusEndComplex = beginComplex - endComplex - beginMinusEndComplexLength = abs( beginMinusEndComplex ) - if beginMinusEndComplexLength < 0.0: - return - endComplex = endComplex + beginMinusEndComplex * shortenDistanceEnd / beginMinusEndComplexLength - deltaX = endComplex.real - beginComplex.real - deltaY = endComplex.imag - beginComplex.imag - isSteep = abs( deltaY ) > abs( deltaX ) - if isSteep: - beginComplex = complex( beginComplex.imag, beginComplex.real ) - endComplex = complex( endComplex.imag, endComplex.real ) - if beginComplex.real > endComplex.real: - endComplex, beginComplex = beginComplex, endComplex - deltaX = endComplex.real - beginComplex.real - deltaY = endComplex.imag - beginComplex.imag - if deltaX > 0.0: - gradient = deltaY / deltaX - else: - gradient = 0.0 - print('This should never happen, deltaX in addSegmentToPixelTable in euclidean is 0.') - print( beginComplex ) - print( endComplex ) - print( shortenDistanceBegin ) - print( shortenDistanceEnd ) - print( width ) - xBegin = int(round(beginComplex.real)) - xEnd = int(round(endComplex.real)) - yIntersection = beginComplex.imag - beginComplex.real * gradient - addPixelToPixelTableWithSteepness( isSteep, pixelDictionary, None, xBegin, int( round( beginComplex.imag ) ) ) - addPixelToPixelTableWithSteepness( isSteep, pixelDictionary, None, xEnd, int( round( endComplex.imag ) ) ) - for x in xrange( xBegin + 1, xEnd ): - y = int( math.floor( yIntersection + x * gradient ) ) - addPixelToPixelTableWithSteepness( isSteep, pixelDictionary, None, x, y ) - addPixelToPixelTableWithSteepness( isSteep, pixelDictionary, None, x, y + 1 ) - -def addSquareTwoToPixelDictionary(pixelDictionary, point, value, width): - """Add square with two pixels around the center to pixel dictionary.""" - point /= width - x = int(round(point.real)) - y = int(round(point.imag)) - for xStep in xrange(x - 2, x + 3): - for yStep in xrange(y - 2, y + 3): - pixelDictionary[getStepKey(xStep, yStep)] = value - -def addSurroundingLoopBeginning( distanceFeedRate, loop, z ): - """Add surrounding loop beginning to gcode output.""" - distanceFeedRate.addLine('()') - distanceFeedRate.addLine('()') - for point in loop: - pointVector3 = Vector3(point.real, point.imag, z) - distanceFeedRate.addLine( distanceFeedRate.getBoundaryLine( pointVector3 ) ) - -def addToThreadsFromLoop(extrusionHalfWidth, gcodeType, loop, oldOrderedLocation, skein): - """Add to threads from the last location from loop.""" - loop = getLoopStartingNearest(extrusionHalfWidth, oldOrderedLocation.dropAxis(), loop) - oldOrderedLocation.x = loop[0].real - oldOrderedLocation.y = loop[0].imag - gcodeTypeStart = gcodeType - if isWiddershins(loop): - skein.distanceFeedRate.addLine('(<%s> outer )' % gcodeType) - else: - skein.distanceFeedRate.addLine('(<%s> inner )' % gcodeType) - skein.addGcodeFromThreadZ(loop + [loop[0]], oldOrderedLocation.z) - skein.distanceFeedRate.addLine('()' % gcodeType) - -def addToThreadsRemove(extrusionHalfWidth, nestedRings, oldOrderedLocation, skein, threadSequence): - """Add to threads from the last location from surrounding loops.""" - while len(nestedRings) > 0: - getTransferClosestSurroundingLoop(extrusionHalfWidth, nestedRings, oldOrderedLocation, skein, threadSequence) - -def addValueSegmentToPixelTable( beginComplex, endComplex, pixelDictionary, value, width ): - """Add line segment to the pixel table.""" - if abs( beginComplex - endComplex ) <= 0.0: - return - beginComplex /= width - endComplex /= width - deltaX = endComplex.real - beginComplex.real - deltaY = endComplex.imag - beginComplex.imag - isSteep = abs( deltaY ) > abs( deltaX ) - if isSteep: - beginComplex = complex( beginComplex.imag, beginComplex.real ) - endComplex = complex( endComplex.imag, endComplex.real ) - if beginComplex.real > endComplex.real: - endComplex, beginComplex = beginComplex, endComplex - deltaX = endComplex.real - beginComplex.real - deltaY = endComplex.imag - beginComplex.imag - if deltaX > 0.0: - gradient = deltaY / deltaX - else: - gradient = 0.0 - print('This should never happen, deltaX in addValueSegmentToPixelTable in euclidean is 0.') - print( beginComplex ) - print(value) - print( endComplex ) - print( width ) - xBegin = int(round(beginComplex.real)) - xEnd = int(round(endComplex.real)) - yIntersection = beginComplex.imag - beginComplex.real * gradient - addPixelToPixelTableWithSteepness( isSteep, pixelDictionary, value, xBegin, int( round( beginComplex.imag ) ) ) - addPixelToPixelTableWithSteepness( isSteep, pixelDictionary, value, xEnd, int( round( endComplex.imag ) ) ) - for x in xrange( xBegin + 1, xEnd ): - y = int( math.floor( yIntersection + x * gradient ) ) - addPixelToPixelTableWithSteepness( isSteep, pixelDictionary, value, x, y ) - addPixelToPixelTableWithSteepness( isSteep, pixelDictionary, value, x, y + 1 ) - -def addValueToOutput(depth, keyInput, output, value): - """Add value to the output.""" - depthStart = ' ' * depth - output.write('%s%s:' % (depthStart, keyInput)) - if value.__class__ == dict: - output.write('\n') - keys = value.keys() - keys.sort() - for key in keys: - addValueToOutput(depth + 1, key, output, value[key]) - return - if value.__class__ == list: - output.write('\n') - for elementIndex, element in enumerate(value): - addValueToOutput(depth + 1, elementIndex, output, element) - return - output.write(' %s\n' % value) - -def addXIntersectionIndexesFromLoop( frontOverWidth, loop, solidIndex, xIntersectionIndexLists, width, yList ): - """Add the x intersection indexes for a loop.""" - for pointIndex in xrange(len(loop)): - pointBegin = loop[pointIndex] - pointEnd = loop[(pointIndex + 1) % len(loop)] - if pointBegin.imag > pointEnd.imag: - pointOriginal = pointBegin - pointBegin = pointEnd - pointEnd = pointOriginal - fillBegin = int( math.ceil( pointBegin.imag / width - frontOverWidth ) ) - fillBegin = max( 0, fillBegin ) - fillEnd = int( math.ceil( pointEnd.imag / width - frontOverWidth ) ) - fillEnd = min( len( xIntersectionIndexLists ), fillEnd ) - if fillEnd > fillBegin: - secondMinusFirstComplex = pointEnd - pointBegin - secondMinusFirstImaginaryOverReal = secondMinusFirstComplex.real / secondMinusFirstComplex.imag - beginRealMinusImaginary = pointBegin.real - pointBegin.imag * secondMinusFirstImaginaryOverReal - for fillLine in xrange( fillBegin, fillEnd ): - xIntersection = yList[fillLine] * secondMinusFirstImaginaryOverReal + beginRealMinusImaginary - xIntersectionIndexList = xIntersectionIndexLists[fillLine] - xIntersectionIndexList.append( XIntersectionIndex( solidIndex, xIntersection ) ) - -def addXIntersectionIndexesFromLoops( frontOverWidth, loops, solidIndex, xIntersectionIndexLists, width, yList ): - """Add the x intersection indexes for a loop.""" - for loop in loops: - addXIntersectionIndexesFromLoop( frontOverWidth, loop, solidIndex, xIntersectionIndexLists, width, yList ) - -def addXIntersectionIndexesFromLoopY( loop, solidIndex, xIntersectionIndexList, y ): - """Add the x intersection indexes for a loop.""" - for pointIndex in xrange(len(loop)): - pointFirst = loop[pointIndex] - pointSecond = loop[(pointIndex + 1) % len(loop)] - xIntersection = getXIntersectionIfExists( pointFirst, pointSecond, y ) - if xIntersection is not None: - xIntersectionIndexList.append( XIntersectionIndex( solidIndex, xIntersection ) ) - -def addXIntersectionIndexesFromLoopListsY( loopLists, xIntersectionIndexList, y ): - """Add the x intersection indexes for the loop lists.""" - for loopListIndex in xrange( len(loopLists) ): - loopList = loopLists[ loopListIndex ] - addXIntersectionIndexesFromLoopsY( loopList, loopListIndex, xIntersectionIndexList, y ) - -def addXIntersectionIndexesFromLoopsY( loops, solidIndex, xIntersectionIndexList, y ): - """Add the x intersection indexes for the loops.""" - for loop in loops: - addXIntersectionIndexesFromLoopY( loop, solidIndex, xIntersectionIndexList, y ) - -def addXIntersectionIndexesFromSegment( index, segment, xIntersectionIndexList ): - """Add the x intersection indexes from the segment.""" - for endpoint in segment: - xIntersectionIndexList.append( XIntersectionIndex( index, endpoint.point.real ) ) - -def addXIntersectionIndexesFromSegments( index, segments, xIntersectionIndexList ): - """Add the x intersection indexes from the segments.""" - for segment in segments: - addXIntersectionIndexesFromSegment( index, segment, xIntersectionIndexList ) - -def addXIntersectionIndexesFromXIntersections( index, xIntersectionIndexList, xIntersections ): - """Add the x intersection indexes from the XIntersections.""" - for xIntersection in xIntersections: - xIntersectionIndexList.append( XIntersectionIndex( index, xIntersection ) ) - -def addXIntersections( loop, xIntersections, y ): - """Add the x intersections for a loop.""" - for pointIndex in xrange(len(loop)): - pointFirst = loop[pointIndex] - pointSecond = loop[(pointIndex + 1) % len(loop)] - xIntersection = getXIntersectionIfExists( pointFirst, pointSecond, y ) - if xIntersection is not None: - xIntersections.append( xIntersection ) - -def addXIntersectionsFromLoopForTable( loop, xIntersectionsTable, width ): - """Add the x intersections for a loop into a table.""" - for pointIndex in xrange(len(loop)): - pointBegin = loop[pointIndex] - pointEnd = loop[(pointIndex + 1) % len(loop)] - if pointBegin.imag > pointEnd.imag: - pointOriginal = pointBegin - pointBegin = pointEnd - pointEnd = pointOriginal - fillBegin = int( math.ceil( pointBegin.imag / width ) ) - fillEnd = int( math.ceil( pointEnd.imag / width ) ) - if fillEnd > fillBegin: - secondMinusFirstComplex = pointEnd - pointBegin - secondMinusFirstImaginaryOverReal = secondMinusFirstComplex.real / secondMinusFirstComplex.imag - beginRealMinusImaginary = pointBegin.real - pointBegin.imag * secondMinusFirstImaginaryOverReal - for fillLine in xrange( fillBegin, fillEnd ): - y = fillLine * width - xIntersection = y * secondMinusFirstImaginaryOverReal + beginRealMinusImaginary - addElementToListDictionary( xIntersection, fillLine, xIntersectionsTable ) - -def addXIntersectionsFromLoops( loops, xIntersections, y ): - """Add the x intersections for the loops.""" - for loop in loops: - addXIntersections( loop, xIntersections, y ) - -def addXIntersectionsFromLoopsForTable( loops, xIntersectionsTable, width ): - """Add the x intersections for a loop into a table.""" - for loop in loops: - addXIntersectionsFromLoopForTable( loop, xIntersectionsTable, width ) - -def compareSegmentLength( endpoint, otherEndpoint ): - """Get comparison in order to sort endpoints in ascending order of segment length.""" - if endpoint.segmentLength > otherEndpoint.segmentLength: - return 1 - if endpoint.segmentLength < otherEndpoint.segmentLength: - return - 1 - return 0 - -def concatenateRemovePath( connectedPaths, pathIndex, paths, pixelDictionary, segments, width ): - """Get connected paths from paths.""" - bottomSegment = segments[ pathIndex ] - path = paths[ pathIndex ] - if bottomSegment is None: - connectedPaths.append(path) - return - endpoints = getEndpointsFromSegments( segments[ pathIndex + 1 : ] ) - bottomSegmentEndpoint = bottomSegment[0] - nextEndpoint = bottomSegmentEndpoint.getNearestMissCheckEndpointPath( endpoints, bottomSegmentEndpoint.path, pixelDictionary, width ) - if nextEndpoint is None: - bottomSegmentEndpoint = bottomSegment[1] - nextEndpoint = bottomSegmentEndpoint.getNearestMissCheckEndpointPath( endpoints, bottomSegmentEndpoint.path, pixelDictionary, width ) - if nextEndpoint is None: - connectedPaths.append(path) - return - if len( bottomSegmentEndpoint.path ) > 0 and len( nextEndpoint.path ) > 0: - bottomEnd = bottomSegmentEndpoint.path[-1] - nextBegin = nextEndpoint.path[-1] - nextMinusBottomNormalized = getNormalized( nextBegin - bottomEnd ) - if len( bottomSegmentEndpoint.path ) > 1: - bottomPenultimate = bottomSegmentEndpoint.path[-2] - if getDotProduct( getNormalized( bottomPenultimate - bottomEnd ), nextMinusBottomNormalized ) > 0.9: - connectedPaths.append(path) - return - if len( nextEndpoint.path ) > 1: - nextPenultimate = nextEndpoint.path[-2] - if getDotProduct( getNormalized( nextPenultimate - nextBegin ), - nextMinusBottomNormalized ) > 0.9: - connectedPaths.append(path) - return - nextEndpoint.path.reverse() - concatenatedPath = bottomSegmentEndpoint.path + nextEndpoint.path - paths[ nextEndpoint.pathIndex ] = concatenatedPath - segments[ nextEndpoint.pathIndex ] = getSegmentFromPath( concatenatedPath, nextEndpoint.pathIndex ) - addValueSegmentToPixelTable( bottomSegmentEndpoint.point, nextEndpoint.point, pixelDictionary, None, width ) - -def getAngleAroundZAxisDifference( subtractFromVec3, subtractVec3 ): - """Get the angle around the Z axis difference between a pair of Vector3s.""" - subtractVectorMirror = complex( subtractVec3.x , - subtractVec3.y ) - differenceVector = getRoundZAxisByPlaneAngle( subtractVectorMirror, subtractFromVec3 ) - return math.atan2( differenceVector.y, differenceVector.x ) - -def getAngleDifferenceByComplex( subtractFromComplex, subtractComplex ): - """Get the angle between a pair of normalized complexes.""" - subtractComplexMirror = complex( subtractComplex.real , - subtractComplex.imag ) - differenceComplex = subtractComplexMirror * subtractFromComplex - return math.atan2( differenceComplex.imag, differenceComplex.real ) - -def getAreaLoop(loop): - """Get the area of a complex polygon.""" - areaLoopDouble = 0.0 - for pointIndex, point in enumerate(loop): - pointEnd = loop[(pointIndex + 1) % len(loop)] - areaLoopDouble += point.real * pointEnd.imag - pointEnd.real * point.imag - return 0.5 * areaLoopDouble - -def getAreaLoopAbsolute(loop): - """Get the absolute area of a complex polygon.""" - return abs(getAreaLoop(loop)) - -def getAreaLoops(loops): - """Get the area of a list of complex polygons.""" - areaLoops = 0.0 - for loop in loops: - areaLoops += getAreaLoop(loop) - return areaLoops - -def getAreaRadiusMultiplier(sides): - """Get the area radius multiplier for the polygon.""" - return math.sqrt(globalTau / sides / math.sin(globalTau / sides)) - -def getAreaVector3LoopAbsolute(loop): - """Get the absolute area of a vector3 polygon.""" - return getAreaLoopAbsolute(getComplexPath(loop)) - -def getAroundLoop(begin, end, loop): - """Get an arc around a loop.""" - aroundLoop = [] - if end <= begin: - end += len(loop) - for pointIndex in xrange(begin, end): - aroundLoop.append(loop[pointIndex % len(loop)]) - return aroundLoop - -def getAwayPoints(points, radius): - """Get a path with only the points that are far enough away from each other.""" - away = [] - oneOverOverlapDistance = 1000.0 / radius - pixelDictionary = {} - for point in points: - x = int(point.real * oneOverOverlapDistance) - y = int(point.imag * oneOverOverlapDistance) - if not getSquareIsOccupied(pixelDictionary, x, y): - away.append(point) - stepKey = getStepKey(x, y) - pixelDictionary[stepKey] = None - return away - -def getBackOfLoops(loops): - """Get the back of the loops.""" - negativeFloat = - 987654321.75342341 - back = negativeFloat - for loop in loops: - for point in loop: - back = max( back, point.imag ) - if back == negativeFloat: - print('This should never happen, there are no loops for getBackOfLoops in euclidean') - return back - -def getBooleanFromDictionary(defaultBoolean, dictionary, key): - """Get boolean from the dictionary and key.""" - if key not in dictionary: - return defaultBoolean - return getBooleanFromValue(dictionary[key]) - -def getBooleanFromValue(value): - """Get boolean from the word.""" - firstCharacter = str(value).lower().lstrip()[: 1] - return firstCharacter == 't' or firstCharacter == '1' - -def getBottomByPath(path): - """Get the bottom of the path.""" - bottom = 987654321.0 - for point in path: - bottom = min(bottom, point.z) - return bottom - -def getBottomByPaths(paths): - """Get the bottom of the paths.""" - bottom = 987654321.0 - for path in paths: - for point in path: - bottom = min(bottom, point.z) - return bottom - -def getClippedAtEndLoopPath( clip, loopPath ): - """Get a clipped loop path.""" - if clip <= 0.0: - return loopPath - loopPathLength = getPathLength(loopPath) - clip = min( clip, 0.3 * loopPathLength ) - 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 += abs(firstPoint - secondPoint) - remainingLength = clippedLength - lastLength - clippedLoopPath = loopPath[ : pointIndex ] - ultimateClippedPoint = loopPath[pointIndex] - penultimateClippedPoint = clippedLoopPath[-1] - segment = ultimateClippedPoint - penultimateClippedPoint - segmentLength = abs(segment) - if segmentLength <= 0.0: - return clippedLoopPath - newUltimatePoint = penultimateClippedPoint + segment * remainingLength / segmentLength - return clippedLoopPath + [newUltimatePoint] - -def getClippedLoopPath(clip, loopPath): - """Get a clipped loop path.""" - if clip <= 0.0: - return loopPath - loopPathLength = getPathLength(loopPath) - clip = min(clip, 0.3 * loopPathLength) - lastLength = 0.0 - pointIndex = 0 - totalLength = 0.0 - while totalLength < clip and pointIndex < len(loopPath) - 1: - firstPoint = loopPath[pointIndex] - secondPoint = loopPath[pointIndex + 1] - pointIndex += 1 - lastLength = totalLength - totalLength += abs(firstPoint - secondPoint) - remainingLength = clip - lastLength - clippedLoopPath = loopPath[pointIndex :] - ultimateClippedPoint = clippedLoopPath[0] - penultimateClippedPoint = loopPath[pointIndex - 1] - segment = ultimateClippedPoint - penultimateClippedPoint - segmentLength = abs(segment) - loopPath = clippedLoopPath - if segmentLength > 0.0: - newUltimatePoint = penultimateClippedPoint + segment * remainingLength / segmentLength - loopPath = [newUltimatePoint] + loopPath - return getClippedAtEndLoopPath(clip, loopPath) - -def getClippedSimplifiedLoopPath(clip, loopPath, radius): - """Get a clipped and simplified loop path.""" - return getSimplifiedPath(getClippedLoopPath(clip, loopPath), radius) - -def getComplexByCommaString( valueCommaString ): - """Get the commaString as a complex.""" - try: - splitLine = valueCommaString.replace(',', ' ').split() - return complex( float( splitLine[0] ), float(splitLine[1]) ) - except: - pass - return None - -def getComplexDefaultByDictionary( defaultComplex, dictionary, key ): - """Get the value as a complex.""" - if key in dictionary: - return complex( dictionary[key].strip().replace('(', '').replace(')', '') ) - return defaultComplex - -def getComplexDefaultByDictionaryKeys( defaultComplex, dictionary, keyX, keyY ): - """Get the value as a complex.""" - x = getFloatDefaultByDictionary( defaultComplex.real, dictionary, keyX ) - y = getFloatDefaultByDictionary( defaultComplex.real, dictionary, keyY ) - return complex(x, y) - -def getComplexByWords(words, wordIndex=0): - """Get the complex by the first two words.""" - try: - return complex(float(words[wordIndex]), float(words[wordIndex + 1])) - except: - pass - return None - -def getComplexPath(vector3Path): - """Get the complex path from the vector3 path.""" - complexPath = [] - for point in vector3Path: - complexPath.append(point.dropAxis()) - return complexPath - -def getComplexPathByMultiplier(multiplier, path): - """Get the multiplied complex path.""" - complexPath = [] - for point in path: - complexPath.append(multiplier * point) - return complexPath - -def getComplexPaths(vector3Paths): - """Get the complex paths from the vector3 paths.""" - complexPaths = [] - for vector3Path in vector3Paths: - complexPaths.append(getComplexPath(vector3Path)) - return complexPaths - -def getComplexPolygon(center, radius, sides, startAngle=0.0): - """Get the complex polygon.""" - complexPolygon = [] - sideAngle = 2.0 * math.pi / float(sides) - for side in xrange(abs(sides)): - unitPolar = getWiddershinsUnitPolar(startAngle) - complexPolygon.append(unitPolar * radius + center) - startAngle += sideAngle - return complexPolygon - -def getComplexPolygonByComplexRadius(radius, sides, startAngle=0.0): - """Get the complex polygon.""" - complexPolygon = [] - sideAngle = 2.0 * math.pi / float(sides) - for side in xrange(abs(sides)): - unitPolar = getWiddershinsUnitPolar(startAngle) - complexPolygon.append(complex(unitPolar.real * radius.real, unitPolar.imag * radius.imag)) - startAngle += sideAngle - return complexPolygon - -def getComplexPolygonByStartEnd(endAngle, radius, sides, startAngle=0.0): - """Get the complex polygon by start and end angle.""" - angleExtent = endAngle - startAngle - sideAngle = 2.0 * math.pi / float(sides) - sides = int(math.ceil(abs(angleExtent / sideAngle))) - sideAngle = angleExtent / float(sides) - complexPolygon = [] - for side in xrange(abs(sides) + 1): - unitPolar = getWiddershinsUnitPolar(startAngle) - complexPolygon.append(unitPolar * radius) - startAngle += sideAngle - return getLoopWithoutCloseEnds(0.000001 * radius, complexPolygon) - -def getConcatenatedList(originalLists): - """Get the lists as one concatenated list.""" - concatenatedList = [] - for originalList in originalLists: - concatenatedList += originalList - return concatenatedList - -def getConnectedPaths( paths, pixelDictionary, width ): - """Get connected paths from paths.""" - if len(paths) < 2: - return paths - connectedPaths = [] - segments = [] - for pathIndex in xrange( len(paths) ): - path = paths[ pathIndex ] - segments.append( getSegmentFromPath( path, pathIndex ) ) - for pathIndex in xrange( 0, len(paths) - 1 ): - concatenateRemovePath( connectedPaths, pathIndex, paths, pixelDictionary, segments, width ) - connectedPaths.append( paths[-1] ) - return connectedPaths - -def getCrossProduct( firstComplex, secondComplex ): - """Get z component cross product of a pair of complexes.""" - return firstComplex.real * secondComplex.imag - firstComplex.imag * secondComplex.real - -def getDecimalPlacesCarried(extraDecimalPlaces, value): - """Get decimal places carried by the decimal places of the value plus the extraDecimalPlaces.""" - return max(0, 1 + int(math.ceil(extraDecimalPlaces - math.log10(value)))) - -def getDiagonalFlippedLoop(loop): - """Get loop flipped over the dialogonal, in other words with the x and y swapped.""" - diagonalFlippedLoop = [] - for point in loop: - diagonalFlippedLoop.append( complex( point.imag, point.real ) ) - return diagonalFlippedLoop - -def getDiagonalFlippedLoops(loops): - """Get loops flipped over the dialogonal, in other words with the x and y swapped.""" - diagonalFlippedLoops = [] - for loop in loops: - diagonalFlippedLoops.append( getDiagonalFlippedLoop(loop) ) - return diagonalFlippedLoops - -def getDictionaryString(dictionary): - """Get the dictionary string.""" - output = cStringIO.StringIO() - keys = dictionary.keys() - keys.sort() - for key in keys: - addValueToOutput(0, key, output, dictionary[key]) - return output.getvalue() - -def getDistanceToLine(begin, end, point): - """Get the distance from a vector3 point to an infinite line.""" - pointMinusBegin = point - begin - if begin == end: - return abs(pointMinusBegin) - endMinusBegin = end - begin - return abs(endMinusBegin.cross(pointMinusBegin)) / abs(endMinusBegin) - -def getDistanceToLineByPath(begin, end, path): - """Get the maximum distance from a path to an infinite line.""" - distanceToLine = -987654321.0 - for point in path: - distanceToLine = max(getDistanceToLine(begin, end, point), distanceToLine) - return distanceToLine - -def getDistanceToLineByPaths(begin, end, paths): - """Get the maximum distance from paths to an infinite line.""" - distanceToLine = -987654321.0 - for path in paths: - distanceToLine = max(getDistanceToLineByPath(begin, end, path), distanceToLine) - return distanceToLine - -def getDistanceToPlaneSegment( segmentBegin, segmentEnd, point ): - """Get the distance squared from a point to the x & y components of a segment.""" - segmentDifference = segmentEnd - segmentBegin - pointMinusSegmentBegin = point - segmentBegin - beginPlaneDot = getDotProduct( pointMinusSegmentBegin, segmentDifference ) - if beginPlaneDot <= 0.0: - return abs( point - segmentBegin ) * abs( point - segmentBegin ) - differencePlaneDot = getDotProduct( segmentDifference, segmentDifference ) - if differencePlaneDot <= beginPlaneDot: - return abs( point - segmentEnd ) * abs( point - segmentEnd ) - intercept = beginPlaneDot / differencePlaneDot - interceptPerpendicular = segmentBegin + segmentDifference * intercept - return abs( point - interceptPerpendicular ) * abs( point - interceptPerpendicular ) - -def getDotProduct( firstComplex, secondComplex ): - """Get the dot product of a pair of complexes.""" - return firstComplex.real * secondComplex.real + firstComplex.imag * secondComplex.imag - -def getDotProductPlusOne( firstComplex, secondComplex ): - """Get the dot product plus one of the x and y components of a pair of Vector3s.""" - return 1.0 + getDotProduct( firstComplex, secondComplex ) - -def getDurationString( seconds ): - """Get the duration string.""" - secondsRounded = int( round( seconds ) ) - durationString = getPluralString( secondsRounded % 60, 'second') - if seconds < 60: - return durationString - durationString = '%s %s' % ( getPluralString( ( secondsRounded / 60 ) % 60, 'minute'), durationString ) - if seconds < 3600: - return durationString - return '%s %s' % ( getPluralString( secondsRounded / 3600, 'hour'), durationString ) - -def getEndpointFromPath( path, pathIndex ): - """Get endpoint segment from a path.""" - begin = path[-1] - end = path[-2] - endpointBegin = Endpoint() - endpointEnd = Endpoint().getFromOtherPoint( endpointBegin, end ) - endpointBegin.getFromOtherPoint( endpointEnd, begin ) - endpointBegin.path = path - endpointBegin.pathIndex = pathIndex - return endpointBegin - -def getEndpointsFromSegments( segments ): - """Get endpoints from segments.""" - endpoints = [] - for segment in segments: - for endpoint in segment: - endpoints.append( endpoint ) - return endpoints - -def getEndpointsFromSegmentTable( segmentTable ): - """Get the endpoints from the segment table.""" - endpoints = [] - segmentTableKeys = segmentTable.keys() - segmentTableKeys.sort() - for segmentTableKey in segmentTableKeys: - for segment in segmentTable[ segmentTableKey ]: - for endpoint in segment: - endpoints.append( endpoint ) - return endpoints - -def getEnumeratorKeys(enumerator, keys): - """Get enumerator keys.""" - if len(keys) == 1: - return keys[0] - return getEnumeratorKeysExceptForOneArgument(enumerator, keys) - -def getEnumeratorKeysAlwaysList(enumerator, keys): - """Get enumerator keys.""" - if keys.__class__ != list: - return [keys] - if len(keys) == 1: - return keys - return getEnumeratorKeysExceptForOneArgument(enumerator, keys) - -def getEnumeratorKeysExceptForOneArgument(enumerator, keys): - """Get enumerator keys, except when there is one argument.""" - if not len(keys): - return range(0, len(enumerator)) - beginIndex = keys[0] - endIndex = keys[1] - if len(keys) == 2: - if beginIndex is None: - beginIndex = 0 - if endIndex is None: - endIndex = len(enumerator) - return range(beginIndex, endIndex) - step = keys[2] - beginIndexDefault = 0 - endIndexDefault = len(enumerator) - if step < 0: - beginIndexDefault = endIndexDefault - 1 - endIndexDefault = -1 - if beginIndex is None: - beginIndex = beginIndexDefault - if endIndex is None: - endIndex = endIndexDefault - return range(beginIndex, endIndex, step) - -def getFillOfSurroundings(nestedRings, penultimateFillLoops): - """Get extra fill loops of surrounding loops.""" - fillOfSurroundings = [] - for nestedRing in nestedRings: - fillOfSurroundings += nestedRing.getFillLoops(penultimateFillLoops) - return fillOfSurroundings - -def getFloatDefaultByDictionary( defaultFloat, dictionary, key ): - """Get the value as a float.""" - evaluatedFloat = None - if key in dictionary: - evaluatedFloat = getFloatFromValue(dictionary[key]) - if evaluatedFloat is None: - return defaultFloat - return evaluatedFloat - -def getFloatFromValue(value): - """Get the value as a float.""" - try: - return float(value) - except: - pass - return None - -def getFourSignificantFigures(number): - """Get number rounded to four significant figures as a string.""" - if number is None: - return None - absoluteNumber = abs(number) - if absoluteNumber >= 100.0: - return getRoundedToPlacesString( 2, number ) - if absoluteNumber < 0.000000001: - return getRoundedToPlacesString( 13, number ) - return getRoundedToPlacesString( 3 - math.floor( math.log10( absoluteNumber ) ), number ) - -def getFrontOfLoops(loops): - """Get the front of the loops.""" - bigFloat = 987654321.196854654 - front = bigFloat - for loop in loops: - for point in loop: - front = min( front, point.imag ) - if front == bigFloat: - print('This should never happen, there are no loops for getFrontOfLoops in euclidean') - return front - -def getFrontOverWidthAddXListYList( front, loopLists, numberOfLines, xIntersectionIndexLists, width, yList ): - """Get the front over width and add the x intersection index lists and ylist.""" - frontOverWidth = getFrontOverWidthAddYList( front, numberOfLines, xIntersectionIndexLists, width, yList ) - for loopListIndex in xrange( len(loopLists) ): - loopList = loopLists[ loopListIndex ] - addXIntersectionIndexesFromLoops( frontOverWidth, loopList, loopListIndex, xIntersectionIndexLists, width, yList ) - return frontOverWidth - -def getFrontOverWidthAddYList( front, numberOfLines, xIntersectionIndexLists, width, yList ): - """Get the front over width and add the x intersection index lists and ylist.""" - frontOverWidth = front / width - for fillLine in xrange( numberOfLines ): - yList.append( front + float( fillLine ) * width ) - xIntersectionIndexLists.append([]) - return frontOverWidth - -def getHalfSimplifiedLoop( loop, radius, remainder ): - """Get the loop with half of the points inside the channel removed.""" - if len(loop) < 2: - return loop - channelRadius = radius * .01 - simplified = [] - addIndex = 0 - if remainder == 1: - addIndex = len(loop) - 1 - for pointIndex in xrange(len(loop)): - point = loop[pointIndex] - if pointIndex % 2 == remainder or pointIndex == addIndex: - simplified.append(point) - elif not isWithinChannel( channelRadius, pointIndex, loop ): - simplified.append(point) - return simplified - -def getHalfSimplifiedPath(path, radius, remainder): - """Get the path with half of the points inside the channel removed.""" - if len(path) < 2: - return path - channelRadius = radius * .01 - simplified = [path[0]] - for pointIndex in xrange(1, len(path) - 1): - point = path[pointIndex] - if pointIndex % 2 == remainder: - simplified.append(point) - elif not isWithinChannel(channelRadius, pointIndex, path): - simplified.append(point) - simplified.append(path[-1]) - return simplified - -def getHorizontallyBoundedPath(horizontalBegin, horizontalEnd, path): - """Get horizontally bounded path.""" - horizontallyBoundedPath = [] - for pointIndex, point in enumerate(path): - begin = None - previousIndex = pointIndex - 1 - if previousIndex >= 0: - begin = path[previousIndex] - end = None - nextIndex = pointIndex + 1 - if nextIndex < len(path): - end = path[nextIndex] - addHorizontallyBoundedPoint(begin, point, end, horizontalBegin, horizontalEnd, horizontallyBoundedPath) - return horizontallyBoundedPath - -def getHorizontalSegmentListsFromLoopLists( alreadyFilledArounds, front, numberOfLines, rotatedFillLoops, width ): - """Get horizontal segment lists inside loops.""" - xIntersectionIndexLists = [] - yList = [] - frontOverWidth = getFrontOverWidthAddXListYList( front, alreadyFilledArounds, numberOfLines, xIntersectionIndexLists, width, yList ) - addXIntersectionIndexesFromLoops( frontOverWidth, rotatedFillLoops, - 1, xIntersectionIndexLists, width, yList ) - horizontalSegmentLists = [] - for xIntersectionIndexListIndex in xrange( len( xIntersectionIndexLists ) ): - xIntersectionIndexList = xIntersectionIndexLists[ xIntersectionIndexListIndex ] - lineSegments = getSegmentsFromXIntersectionIndexes( xIntersectionIndexList, yList[ xIntersectionIndexListIndex ] ) - horizontalSegmentLists.append( lineSegments ) - return horizontalSegmentLists - -def getIncrementFromRank( rank ): - """Get the increment from the rank which is 0 at 1 and increases by three every power of ten.""" - rankZone = int( math.floor( rank / 3 ) ) - rankModulo = rank % 3 - powerOfTen = pow( 10, rankZone ) - moduloMultipliers = ( 1, 2, 5 ) - return float( powerOfTen * moduloMultipliers[ rankModulo ] ) - -def getInsidesAddToOutsides( loops, outsides ): - """Add loops to either the insides or outsides.""" - insides = [] - for loopIndex in xrange( len(loops) ): - loop = loops[loopIndex] - if isInsideOtherLoops( loopIndex, loops ): - insides.append(loop) - else: - outsides.append(loop) - return insides - -def getIntermediateLocation( alongWay, begin, end ): - """Get the intermediate location between begin and end.""" - return begin * ( 1.0 - alongWay ) + end * alongWay - -def getIntersectionOfXIntersectionIndexes( totalSolidSurfaceThickness, xIntersectionIndexList ): - """Get x intersections from surrounding layers.""" - xIntersectionList = [] - solidTable = {} - solid = False - xIntersectionIndexList.sort() - for xIntersectionIndex in xIntersectionIndexList: - toggleHashtable(solidTable, xIntersectionIndex.index, '') - oldSolid = solid - solid = len(solidTable) >= totalSolidSurfaceThickness - if oldSolid != solid: - xIntersectionList.append(xIntersectionIndex.x) - return xIntersectionList - -def getIntersectionOfXIntersectionsTables( xIntersectionsTables ): - """Get the intersection of both XIntersections tables.""" - intersectionOfXIntersectionsTables = {} - firstIntersectionTable = xIntersectionsTables[0] - for firstIntersectionTableKey in firstIntersectionTable.keys(): - xIntersectionIndexList = [] - for xIntersectionsTableIndex in xrange( len( xIntersectionsTables ) ): - xIntersectionsTable = xIntersectionsTables[ xIntersectionsTableIndex ] - addXIntersectionIndexesFromXIntersections( xIntersectionsTableIndex, xIntersectionIndexList, xIntersectionsTable[ firstIntersectionTableKey ] ) - xIntersections = getIntersectionOfXIntersectionIndexes( len( xIntersectionsTables ), xIntersectionIndexList ) - if len( xIntersections ) > 0: - intersectionOfXIntersectionsTables[ firstIntersectionTableKey ] = xIntersections - return intersectionOfXIntersectionsTables - -def getIntFromValue(value): - """Get the value as an int.""" - try: - return int(value) - except: - pass - return None - -def getIsInFilledRegion(loops, point): - """Determine if the point is in the filled region of the loops.""" - return getNumberOfIntersectionsToLeftOfLoops(loops, point) % 2 == 1 - -def getIsInFilledRegionByPaths(loops, paths): - """Determine if the point of any path is in the filled region of the loops.""" - for path in paths: - if len(path) > 0: - if getIsInFilledRegion(loops, path[0]): - return True - return False - -def getIsRadianClose(firstRadian, secondRadian): - """Determine if the firstRadian is close to the secondRadian.""" - return abs(math.pi - abs(math.pi - ((firstRadian - secondRadian) % (math.pi + math.pi) ))) < 0.000001 - -def getIsWiddershinsByVector3( polygon ): - """Determine if the polygon goes round in the widdershins direction.""" - return isWiddershins( getComplexPath( polygon ) ) - -def getJoinOfXIntersectionIndexes( xIntersectionIndexList ): - """Get joined x intersections from surrounding layers.""" - xIntersections = [] - solidTable = {} - solid = False - xIntersectionIndexList.sort() - for xIntersectionIndex in xIntersectionIndexList: - toggleHashtable(solidTable, xIntersectionIndex.index, '') - oldSolid = solid - solid = len(solidTable) > 0 - if oldSolid != solid: - xIntersections.append(xIntersectionIndex.x) - return xIntersections - -def getLargestLoop(loops): - """Get largest loop from loops.""" - if len(loops) == 1: - return loops[0] - largestArea = - 987654321.0 - largestLoop = [] - for loop in loops: - loopArea = abs( getAreaLoop(loop) ) - if loopArea > largestArea: - largestArea = loopArea - largestLoop = loop - return largestLoop - -def getLeftPoint(points): - """Get the leftmost complex point in the points.""" - leftmost = 987654321.0 - leftPointComplex = None - for pointComplex in points: - if pointComplex.real < leftmost: - leftmost = pointComplex.real - leftPointComplex = pointComplex - return leftPointComplex - -def getLeftPointIndex(points): - """Get the index of the leftmost complex point in the points.""" - if len(points) < 1: - return None - leftPointIndex = 0 - for pointIndex in xrange( len(points) ): - if points[pointIndex].real < points[ leftPointIndex ].real: - leftPointIndex = pointIndex - return leftPointIndex - -def getListTableElements( listDictionary ): - """Get all the element in a list table.""" - listDictionaryElements = [] - for listDictionaryValue in listDictionary.values(): - listDictionaryElements += listDictionaryValue - return listDictionaryElements - -def getLoopCentroid(polygonComplex): - """Get the area of a complex polygon using http://en.wikipedia.org/wiki/Centroid.""" - polygonDoubleArea = 0.0 - polygonTorque = 0.0 - for pointIndex in xrange( len(polygonComplex) ): - pointBegin = polygonComplex[pointIndex] - pointEnd = polygonComplex[ (pointIndex + 1) % len(polygonComplex) ] - doubleArea = pointBegin.real * pointEnd.imag - pointEnd.real * pointBegin.imag - doubleCenter = complex( pointBegin.real + pointEnd.real, pointBegin.imag + pointEnd.imag ) - polygonDoubleArea += doubleArea - polygonTorque += doubleArea * doubleCenter - torqueMultiplier = 0.333333333333333333333333 / polygonDoubleArea - return polygonTorque * torqueMultiplier - -def getLoopConvex(points): - """Get convex hull of points using gift wrap algorithm.""" - loopConvex = [] - pointSet = set() - for point in points: - if point not in pointSet: - pointSet.add(point) - loopConvex.append(point) - if len(loopConvex) < 4: - return loopConvex - leftPoint = getLeftPoint(loopConvex) - lastPoint = leftPoint - pointSet.remove(leftPoint) - loopConvex = [leftPoint] - lastSegment = complex(0.0, 1.0) - while True: - greatestDotProduct = -9.9 - greatestPoint = None - greatestSegment = None - if len(loopConvex) > 2: - nextSegment = getNormalized(leftPoint - lastPoint) - if abs(nextSegment) > 0.0: - greatestDotProduct = getDotProduct(nextSegment, lastSegment) - for point in pointSet: - nextSegment = getNormalized(point - lastPoint) - if abs(nextSegment) > 0.0: - dotProduct = getDotProduct(nextSegment, lastSegment) - if dotProduct >= greatestDotProduct: - greatestDotProduct = dotProduct - greatestPoint = point - greatestSegment = nextSegment - if greatestPoint is None: - return loopConvex - lastPoint = greatestPoint - loopConvex.append(greatestPoint) - pointSet.remove(greatestPoint) - lastSegment = greatestSegment - return loopConvex - -def getLoopConvexCentroid(polygonComplex): - """Get centroid of the convex hull of a complex polygon.""" - return getLoopCentroid( getLoopConvex(polygonComplex) ) - -def getLoopInsideContainingLoop( containingLoop, loops ): - """Get a loop that is inside the containing loop.""" - for loop in loops: - if loop != containingLoop: - if isPathInsideLoop( containingLoop, loop ): - return loop - return None - -def getLoopLength( polygon ): - """Get the length of a polygon perimeter.""" - polygonLength = 0.0 - for pointIndex in xrange( len( polygon ) ): - point = polygon[pointIndex] - secondPoint = polygon[ (pointIndex + 1) % len( polygon ) ] - polygonLength += abs( point - secondPoint ) - return polygonLength - -def getLoopStartingNearest(extrusionHalfWidth, location, loop): - """Add to threads from the last location from loop.""" - nearestIndex = getNearestDistanceIndex(location, loop).index - loop = getAroundLoop(nearestIndex, nearestIndex, loop) - nearestPoint = getNearestPointOnSegment(loop[0], loop[1], location) - if abs(nearestPoint - loop[0]) > extrusionHalfWidth and abs(nearestPoint - loop[1]) > extrusionHalfWidth: - loop = [nearestPoint] + loop[1 :] + [loop[0]] - elif abs(nearestPoint - loop[0]) > abs(nearestPoint - loop[1]): - loop = loop[1 :] + [loop[0]] - return loop - -def getLoopWithoutCloseEnds(close, loop): - """Get loop without close ends.""" - if len(loop) < 2: - return loop - if abs(loop[0] - loop[-1]) > close: - return loop - return loop[: -1] - -def getLoopWithoutCloseSequentialPoints(close, loop): - """Get loop without close sequential points.""" - if len(loop) < 2: - return loop - lastPoint = loop[-1] - loopWithoutCloseSequentialPoints = [] - for point in loop: - if abs(point - lastPoint) > close: - loopWithoutCloseSequentialPoints.append(point) - lastPoint = point - return loopWithoutCloseSequentialPoints - -def getMaximum(firstComplex, secondComplex): - """Get a complex with each component the maximum of the respective components of a pair of complexes.""" - return complex(max(firstComplex.real, secondComplex.real), max(firstComplex.imag, secondComplex.imag)) - -def getMaximumByComplexPath(path): - """Get a complex with each component the maximum of the respective components of a complex path.""" - maximum = complex(-987654321.0, -987654321.0) - for point in path: - maximum = getMaximum(maximum, point) - return maximum - -def getMaximumByComplexPaths(paths): - """Get a complex with each component the maximum of the respective components of complex paths.""" - maximum = complex(-987654321.0, -987654321.0) - for path in paths: - for point in path: - maximum = getMaximum(maximum, point) - return maximum - -def getMaximumByVector3Path(path): - """Get a vector3 with each component the maximum of the respective components of a vector3 path.""" - maximum = Vector3(-987654321.0, -987654321.0, -987654321.0) - for point in path: - maximum.maximize(point) - return maximum - -def getMaximumByVector3Paths(paths): - """Get a complex with each component the maximum of the respective components of a complex path.""" - maximum = Vector3(-987654321.0, -987654321.0, -987654321.0) - for path in paths: - for point in path: - maximum.maximize(point) - return maximum - -def getMaximumSpan(loop): - """Get the maximum span of the loop.""" - extent = getMaximumByComplexPath(loop) - getMinimumByComplexPath(loop) - return max(extent.real, extent.imag) - -def getMinimum(firstComplex, secondComplex): - """Get a complex with each component the minimum of the respective components of a pair of complexes.""" - return complex(min(firstComplex.real, secondComplex.real), min(firstComplex.imag, secondComplex.imag)) - -def getMinimumByComplexPath(path): - """Get a complex with each component the minimum of the respective components of a complex path.""" - minimum = complex(987654321.0, 987654321.0) - for point in path: - minimum = getMinimum(minimum, point) - return minimum - -def getMinimumByComplexPaths(paths): - """Get a complex with each component the minimum of the respective components of complex paths.""" - minimum = complex(987654321.0, 987654321.0) - for path in paths: - for point in path: - minimum = getMinimum(minimum, point) - return minimum - -def getMinimumByVector3Path(path): - """Get a vector3 with each component the minimum of the respective components of a vector3 path.""" - minimum = Vector3(987654321.0, 987654321.0, 987654321.0) - for point in path: - minimum.minimize(point) - return minimum - -def getMinimumByVector3Paths(paths): - """Get a complex with each component the minimum of the respective components of a complex path.""" - minimum = Vector3(987654321.0, 987654321.0, 987654321.0) - for path in paths: - for point in path: - minimum.minimize(point) - return minimum - -def getMirrorPath(path): - """Get mirror path.""" - close = 0.001 * getPathLength(path) - for pointIndex in xrange(len(path) - 1, -1, -1): - point = path[pointIndex] - flipPoint = complex(-point.real, point.imag) - if abs(flipPoint - path[-1]) > close: - path.append(flipPoint) - return path - -def getNearestDistanceIndex( point, loop ): - """Get the distance squared to the nearest segment of the loop and index of that segment.""" - smallestDistance = 987654321987654321.0 - nearestDistanceIndex = None - for pointIndex in xrange(len(loop)): - segmentBegin = loop[pointIndex] - segmentEnd = loop[(pointIndex + 1) % len(loop)] - distance = getDistanceToPlaneSegment( segmentBegin, segmentEnd, point ) - if distance < smallestDistance: - smallestDistance = distance - nearestDistanceIndex = DistanceIndex( distance, pointIndex ) - return nearestDistanceIndex - -def getNearestPointOnSegment( segmentBegin, segmentEnd, point ): - """Get the nearest point on the segment.""" - segmentDifference = segmentEnd - segmentBegin - if abs(segmentDifference) <= 0.0: - return segmentBegin - pointMinusSegmentBegin = point - segmentBegin - beginPlaneDot = getDotProduct(pointMinusSegmentBegin, segmentDifference) - differencePlaneDot = getDotProduct(segmentDifference, segmentDifference) - intercept = beginPlaneDot / differencePlaneDot - intercept = max(intercept, 0.0) - intercept = min(intercept, 1.0) - return segmentBegin + segmentDifference * intercept - -def getNormal(begin, center, end): - """Get normal.""" - centerMinusBegin = (center - begin).getNormalized() - endMinusCenter = (end - center).getNormalized() - return centerMinusBegin.cross(endMinusCenter) - -def getNormalByPath(path): - """Get normal by path.""" - totalNormal = Vector3() - for pointIndex, point in enumerate(path): - center = path[(pointIndex + 1) % len(path)] - end = path[(pointIndex + 2) % len(path)] - totalNormal += getNormalWeighted(point, center, end) - return totalNormal.getNormalized() - -def getNormalized( complexNumber ): - """Get the normalized complex.""" - complexNumberLength = abs( complexNumber ) - if complexNumberLength > 0.0: - return complexNumber / complexNumberLength - return complexNumber - -def getNormalWeighted(begin, center, end): - """Get weighted normal.""" - return (center - begin).cross(end - center) - -def getNumberOfIntersectionsToLeft(loop, point): - """Get the number of intersections through the loop for the line going left.""" - numberOfIntersectionsToLeft = 0 - for pointIndex in xrange(len(loop)): - firstPointComplex = loop[pointIndex] - secondPointComplex = loop[(pointIndex + 1) % len(loop)] - xIntersection = getXIntersectionIfExists(firstPointComplex, secondPointComplex, point.imag) - if xIntersection is not None: - if xIntersection < point.real: - numberOfIntersectionsToLeft += 1 - return numberOfIntersectionsToLeft - -def getNumberOfIntersectionsToLeftOfLoops(loops, point): - """Get the number of intersections through the loop for the line starting from the left point and going left.""" - totalNumberOfIntersectionsToLeft = 0 - for loop in loops: - totalNumberOfIntersectionsToLeft += getNumberOfIntersectionsToLeft(loop, point) - return totalNumberOfIntersectionsToLeft - -def getOrderedNestedRings(nestedRings): - """Get ordered nestedRings from nestedRings.""" - insides = [] - orderedNestedRings = [] - for loopIndex in xrange(len(nestedRings)): - nestedRing = nestedRings[loopIndex] - otherLoops = [] - for beforeIndex in xrange(loopIndex): - otherLoops.append(nestedRings[beforeIndex].boundary) - for afterIndex in xrange(loopIndex + 1, len(nestedRings)): - otherLoops.append(nestedRings[afterIndex].boundary) - if isPathEntirelyInsideLoops(otherLoops, nestedRing.boundary): - insides.append(nestedRing) - else: - orderedNestedRings.append(nestedRing) - for outside in orderedNestedRings: - outside.getFromInsideSurroundings(insides) - return orderedNestedRings - -def getPathCopy(path): - """Get path copy.""" - pathCopy = [] - for point in path: - pathCopy.append(point.copy()) - return pathCopy - -def getPathLength(path): - """Get the length of a path ( an open polyline ).""" - pathLength = 0.0 - for pointIndex in xrange( len(path) - 1 ): - firstPoint = path[pointIndex] - secondPoint = path[pointIndex + 1] - pathLength += abs(firstPoint - secondPoint) - return pathLength - -def getPathsFromEndpoints(endpoints, maximumConnectionLength, pixelDictionary, width): - """Get paths from endpoints.""" - if len(endpoints) < 2: - return [[]] - for beginningEndpoint in endpoints[: : 2]: - beginningPoint = beginningEndpoint.point - addSegmentToPixelTable(beginningPoint, beginningEndpoint.otherEndpoint.point, pixelDictionary, 0, 0, width) - endpointFirst = endpoints[0] - endpoints.remove(endpointFirst) - otherEndpoint = endpointFirst.otherEndpoint - endpoints.remove(otherEndpoint) - nextEndpoint = None - path = [] - paths = [path] - if len(endpoints) > 1: - nextEndpoint = otherEndpoint.getNearestMiss(endpoints, path, pixelDictionary, width) - if nextEndpoint is not None: - if abs(nextEndpoint.point - endpointFirst.point) < abs(nextEndpoint.point - otherEndpoint.point): - endpointFirst = endpointFirst.otherEndpoint - otherEndpoint = endpointFirst.otherEndpoint - addPointToPath(path, pixelDictionary, endpointFirst.point, None, width) - addPointToPath(path, pixelDictionary, otherEndpoint.point, len(paths) - 1, width) - oneOverEndpointWidth = 1.0 / maximumConnectionLength - endpointTable = {} - for endpoint in endpoints: - addElementToPixelListFromPoint(endpoint, endpointTable, endpoint.point * oneOverEndpointWidth) - while len(endpointTable) > 0: - if len(endpointTable) == 1: - if len(endpointTable.values()[0]) < 2: - return - endpoints = getSquareValuesFromPoint(endpointTable, otherEndpoint.point * oneOverEndpointWidth) - nextEndpoint = otherEndpoint.getNearestMiss(endpoints, path, pixelDictionary, width) - if nextEndpoint is None: - path = [] - paths.append(path) - endpoints = getListTableElements(endpointTable) - nextEndpoint = otherEndpoint.getNearestEndpoint(endpoints) -# this commented code should be faster than the getListTableElements code, but it isn't, someday a spiral algorithim could be tried -# endpoints = getSquareValuesFromPoint( endpointTable, otherEndpoint.point * oneOverEndpointWidth ) -# nextEndpoint = otherEndpoint.getNearestEndpoint(endpoints) -# if nextEndpoint == None: -# endpoints = [] -# for endpointTableValue in endpointTable.values(): -# endpoints.append( endpointTableValue[0] ) -# nextEndpoint = otherEndpoint.getNearestEndpoint(endpoints) -# endpoints = getSquareValuesFromPoint( endpointTable, nextEndpoint.point * oneOverEndpointWidth ) -# nextEndpoint = otherEndpoint.getNearestEndpoint(endpoints) - addPointToPath(path, pixelDictionary, nextEndpoint.point, len(paths) - 1, width) - removeElementFromPixelListFromPoint(nextEndpoint, endpointTable, nextEndpoint.point * oneOverEndpointWidth) - otherEndpoint = nextEndpoint.otherEndpoint - addPointToPath(path, pixelDictionary, otherEndpoint.point, len(paths) - 1, width) - removeElementFromPixelListFromPoint(otherEndpoint, endpointTable, otherEndpoint.point * oneOverEndpointWidth) - return paths - -def getPlaneDot( vec3First, vec3Second ): - """Get the dot product of the x and y components of a pair of Vector3s.""" - return vec3First.x * vec3Second.x + vec3First.y * vec3Second.y - -def getPluralString( number, suffix ): - """Get the plural string.""" - if number == 1: - return '1 %s' % suffix - return '%s %ss' % ( number, suffix ) - -def getPointsByHorizontalDictionary(width, xIntersectionsDictionary): - """Get points from the horizontalXIntersectionsDictionary.""" - points = [] - xIntersectionsDictionaryKeys = xIntersectionsDictionary.keys() - xIntersectionsDictionaryKeys.sort() - for xIntersectionsDictionaryKey in xIntersectionsDictionaryKeys: - for xIntersection in xIntersectionsDictionary[xIntersectionsDictionaryKey]: - points.append(complex(xIntersection, xIntersectionsDictionaryKey * width)) - return points - -def getPointsByVerticalDictionary(width, xIntersectionsDictionary): - """Get points from the verticalXIntersectionsDictionary.""" - points = [] - xIntersectionsDictionaryKeys = xIntersectionsDictionary.keys() - xIntersectionsDictionaryKeys.sort() - for xIntersectionsDictionaryKey in xIntersectionsDictionaryKeys: - for xIntersection in xIntersectionsDictionary[xIntersectionsDictionaryKey]: - points.append(complex(xIntersectionsDictionaryKey * width, xIntersection)) - return points - -def getPointsRoundZAxis( planeAngle, points ): - """Get points rotated by the plane angle""" - planeArray = [] - for point in points: - planeArray.append( planeAngle * point ) - return planeArray - -def getPointPlusSegmentWithLength( length, point, segment ): - """Get point plus a segment scaled to a given length.""" - return segment * length / abs(segment) + point - -def getRandomComplex(begin, end): - """Get random complex.""" - endMinusBegin = end - begin - return begin + complex(random.random() * endMinusBegin.real, random.random() * endMinusBegin.imag) - -def getRank(width): - """Get the rank which is 0 at 1 and increases by three every power of ten.""" - return int(math.floor(3.0 * math.log10(width))) - -def getRotatedWiddershinsQuarterAroundZAxis(vector3): - """Get Vector3 rotated a quarter widdershins turn around Z axis.""" - return Vector3(-vector3.y, vector3.x, vector3.z) - -def getRoundedPoint(point): - """Get point with each component rounded.""" - return Vector3(round(point.x), round( point.y ), round(point.z)) - -def getRoundedToPlaces(decimalPlaces, number): - """Get number rounded to a number of decimal places.""" - decimalPlacesRounded = max(1, int(round(decimalPlaces))) - return round(number, decimalPlacesRounded ) - -def getRoundedToPlacesString(decimalPlaces, number): - """Get number rounded to a number of decimal places as a string.""" - return str(getRoundedToPlaces(decimalPlaces, number)) - -def getRoundedToThreePlaces(number): - """Get number rounded to three places as a string.""" - return str(round(number, 3)) - -def getRoundZAxisByPlaneAngle( planeAngle, vector3 ): - """Get Vector3 rotated by a plane angle.""" - return Vector3( vector3.x * planeAngle.real - vector3.y * planeAngle.imag, vector3.x * planeAngle.imag + vector3.y * planeAngle.real, vector3.z ) - -def getSegmentFromPath( path, pathIndex ): - """Get endpoint segment from a path.""" - if len(path) < 2: - return None - begin = path[-1] - end = path[-2] - forwardEndpoint = getEndpointFromPath( path, pathIndex ) - reversePath = path[:] - reversePath.reverse() - reverseEndpoint = getEndpointFromPath( reversePath, pathIndex ) - return forwardEndpoint, reverseEndpoint - -def getSegmentFromPoints( begin, end ): - """Get endpoint segment from a pair of points.""" - endpointFirst = Endpoint() - endpointSecond = Endpoint().getFromOtherPoint( endpointFirst, end ) - endpointFirst.getFromOtherPoint( endpointSecond, begin ) - return endpointFirst, endpointSecond - -def getSegmentsFromXIntersections( xIntersections, y ): - """Get endpoint segments from the x intersections.""" - segments = [] - end = len( xIntersections ) - if len( xIntersections ) % 2 == 1: - end -= 1 - for xIntersectionIndex in xrange( 0, end, 2 ): - firstX = xIntersections[ xIntersectionIndex ] - secondX = xIntersections[ xIntersectionIndex + 1 ] - if firstX != secondX: - segments.append( getSegmentFromPoints( complex( firstX, y ), complex( secondX, y ) ) ) - return segments - -def getSegmentsFromXIntersectionIndexes( xIntersectionIndexList, y ): - """Get endpoint segments from the x intersection indexes.""" - xIntersections = getXIntersectionsFromIntersections( xIntersectionIndexList ) - return getSegmentsFromXIntersections( xIntersections, y ) - -def getSimplifiedLoop( loop, radius ): - """Get loop with points inside the channel removed.""" - if len(loop) < 2: - return loop - simplificationMultiplication = 256 - simplificationRadius = radius / float( simplificationMultiplication ) - maximumIndex = len(loop) * simplificationMultiplication - pointIndex = 1 - while pointIndex < maximumIndex: - oldLoopLength = len(loop) - loop = getHalfSimplifiedLoop( loop, simplificationRadius, 0 ) - loop = getHalfSimplifiedLoop( loop, simplificationRadius, 1 ) - simplificationRadius += simplificationRadius - if oldLoopLength == len(loop): - if simplificationRadius > radius: - return getAwayPoints( loop, radius ) - else: - simplificationRadius *= 1.5 - simplificationRadius = min( simplificationRadius, radius ) - pointIndex += pointIndex - return getAwayPoints( loop, radius ) - -def getSimplifiedLoops( loops, radius ): - """Get the simplified loops.""" - simplifiedLoops = [] - for loop in loops: - simplifiedLoops.append( getSimplifiedLoop( loop, radius ) ) - return simplifiedLoops - -def getSimplifiedPath( path, radius ): - """Get path with points inside the channel removed.""" - if len(path) < 2: - return path - simplificationMultiplication = 256 - simplificationRadius = radius / float( simplificationMultiplication ) - maximumIndex = len(path) * simplificationMultiplication - pointIndex = 1 - while pointIndex < maximumIndex: - oldPathLength = len(path) - path = getHalfSimplifiedPath( path, simplificationRadius, 0 ) - path = getHalfSimplifiedPath( path, simplificationRadius, 1 ) - simplificationRadius += simplificationRadius - if oldPathLength == len(path): - if simplificationRadius > radius: - return getAwayPoints( path, radius ) - else: - simplificationRadius *= 1.5 - simplificationRadius = min( simplificationRadius, radius ) - pointIndex += pointIndex - return getAwayPoints( path, radius ) - -def getSquareIsOccupied( pixelDictionary, x, y ): - """Determine if a square around the x and y pixel coordinates is occupied.""" - squareValues = [] - for xStep in xrange(x - 1, x + 2): - for yStep in xrange(y - 1, y + 2): - stepKey = getStepKey(xStep, yStep) - if stepKey in pixelDictionary: - return True - return False - -def getSquareLoopWiddershins(beginComplex, endComplex): - """Get a square loop from the beginning to the end and back.""" - loop = [beginComplex, complex(endComplex.real, beginComplex.imag), endComplex, - complex(beginComplex.real, endComplex.imag)] - return loop - -def getSquareValues( pixelDictionary, x, y ): - """Get a list of the values in a square around the x and y pixel coordinates.""" - squareValues = [] - for xStep in xrange(x - 1, x + 2): - for yStep in xrange(y - 1, y + 2): - stepKey = getStepKey(xStep, yStep) - if stepKey in pixelDictionary: - squareValues += pixelDictionary[ stepKey ] - return squareValues - -def getSquareValuesFromPoint( pixelDictionary, point ): - """Get a list of the values in a square around the point.""" - return getSquareValues(pixelDictionary, int(round(point.real)), int(round(point.imag))) - -def getStepKey(x, y): - """Get step key for x and y.""" - return x, y - -def getStepKeyFromPoint(point): - """Get step key for the point.""" - return int(round(point.real)), int(round(point.imag)) - -def getThreeSignificantFigures(number): - """Get number rounded to three significant figures as a string.""" - absoluteNumber = abs(number) - if absoluteNumber >= 10.0: - return getRoundedToPlacesString( 1, number ) - if absoluteNumber < 0.000000001: - return getRoundedToPlacesString( 12, number ) - return getRoundedToPlacesString( 1 - math.floor( math.log10( absoluteNumber ) ), number ) - -def getTopPath(path): - """Get the top of the path.""" - top = -987654321.0 - for point in path: - top = max(top, point.z) - return top - -def getTopPaths(paths): - """Get the top of the paths.""" - top = -987654321.0 - for path in paths: - for point in path: - top = max(top, point.z) - return top - -def getTransferClosestSurroundingLoop(extrusionHalfWidth, nestedRings, oldOrderedLocation, skein, threadSequence): - """Get and transfer the closest remaining surrounding loop.""" - if len(nestedRings) > 0: - oldOrderedLocation.z = nestedRings[0].z - closestDistance = 987654321987654321.0 - closestSurroundingLoop = None - for remainingSurroundingLoop in nestedRings: - distance = getNearestDistanceIndex(oldOrderedLocation.dropAxis(), remainingSurroundingLoop.boundary).distance - if distance < closestDistance: - closestDistance = distance - closestSurroundingLoop = remainingSurroundingLoop - nestedRings.remove(closestSurroundingLoop) - closestSurroundingLoop.addToThreads(extrusionHalfWidth, oldOrderedLocation, skein, threadSequence) - return closestSurroundingLoop - -def getTransferredPaths( insides, loop ): - """Get transferred paths from inside paths.""" - transferredPaths = [] - for insideIndex in xrange( len( insides ) - 1, - 1, - 1 ): - inside = insides[ insideIndex ] - if isPathInsideLoop( loop, inside ): - transferredPaths.append( inside ) - del insides[ insideIndex ] - return transferredPaths - -def getTransferredSurroundingLoops( insides, loop ): - """Get transferred paths from inside surrounding loops.""" - transferredSurroundings = [] - for insideIndex in xrange( len( insides ) - 1, - 1, - 1 ): - insideSurrounding = insides[ insideIndex ] - if isPathInsideLoop( loop, insideSurrounding.boundary ): - transferredSurroundings.append( insideSurrounding ) - del insides[ insideIndex ] - return transferredSurroundings - -def getTranslatedComplexPath(path, translateComplex): - """Get the translated complex path.""" - translatedComplexPath = [] - for point in path: - translatedComplexPath.append(point + translateComplex) - return translatedComplexPath - -def getVector3Path(complexPath, z=0.0): - """Get the vector3 path from the complex path.""" - vector3Path = [] - for complexPoint in complexPath: - vector3Path.append(Vector3(complexPoint.real, complexPoint.imag, z)) - return vector3Path - -def getVector3Paths(complexPaths, z=0.0): - """Get the vector3 paths from the complex paths.""" - vector3Paths = [] - for complexPath in complexPaths: - vector3Paths.append(getVector3Path(complexPath, z)) - return vector3Paths - -def getWiddershinsUnitPolar(angle): - """Get polar complex from counterclockwise angle from 1, 0.""" - return complex(math.cos(angle), math.sin(angle)) - -def getXIntersectionIfExists( beginComplex, endComplex, y ): - """Get the x intersection if it exists.""" - if ( y > beginComplex.imag ) == ( y > endComplex.imag ): - return None - endMinusBeginComplex = endComplex - beginComplex - return ( y - beginComplex.imag ) / endMinusBeginComplex.imag * endMinusBeginComplex.real + beginComplex.real - -def getXIntersectionsFromIntersections( xIntersectionIndexList ): - """Get x intersections from the x intersection index list, in other words subtract non negative intersections from negatives.""" - xIntersections = [] - fill = False - solid = False - solidTable = {} - xIntersectionIndexList.sort() - for solidX in xIntersectionIndexList: - if solidX.index >= 0: - toggleHashtable( solidTable, solidX.index, '' ) - else: - fill = not fill - oldSolid = solid - solid = ( len( solidTable ) == 0 and fill ) - if oldSolid != solid: - xIntersections.append( solidX.x ) - return xIntersections - -def getXYComplexFromVector3(vector3): - """Get an xy complex from a vector3 if it exists, otherwise return None.""" - if vector3 is None: - return None - return vector3.dropAxis() - -def getYIntersectionIfExists( beginComplex, endComplex, x ): - """Get the y intersection if it exists.""" - if ( x > beginComplex.real ) == ( x > endComplex.real ): - return None - endMinusBeginComplex = endComplex - beginComplex - return ( x - beginComplex.real ) / endMinusBeginComplex.real * endMinusBeginComplex.imag + beginComplex.imag - -def getZComponentCrossProduct( vec3First, vec3Second ): - """Get z component cross product of a pair of Vector3s.""" - return vec3First.x * vec3Second.y - vec3First.y * vec3Second.x - -def isInsideOtherLoops( loopIndex, loops ): - """Determine if a loop in a list is inside another loop in that list.""" - return isPathInsideLoops( loops[ : loopIndex ] + loops[loopIndex + 1 :], loops[loopIndex] ) - -def isLineIntersectingInsideXSegment( beginComplex, endComplex, segmentFirstX, segmentSecondX, y ): - """Determine if the line is crossing inside the x segment.""" - xIntersection = getXIntersectionIfExists( beginComplex, endComplex, y ) - if xIntersection is None: - return False - if xIntersection < min( segmentFirstX, segmentSecondX ): - return False - return xIntersection <= max( segmentFirstX, segmentSecondX ) - -def isLineIntersectingLoop( loop, pointBegin, pointEnd ): - """Determine if the line is intersecting loops.""" - normalizedSegment = pointEnd - pointBegin - normalizedSegmentLength = abs( normalizedSegment ) - if normalizedSegmentLength > 0.0: - normalizedSegment /= normalizedSegmentLength - segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) - pointBeginRotated = segmentYMirror * pointBegin - pointEndRotated = segmentYMirror * pointEnd - if isLoopIntersectingInsideXSegment( loop, pointBeginRotated.real, pointEndRotated.real, segmentYMirror, pointBeginRotated.imag ): - return True - return False - -def isLineIntersectingLoops( loops, pointBegin, pointEnd ): - """Determine if the line is intersecting loops.""" - normalizedSegment = pointEnd - pointBegin - normalizedSegmentLength = abs( normalizedSegment ) - if normalizedSegmentLength > 0.0: - normalizedSegment /= normalizedSegmentLength - segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) - pointBeginRotated = segmentYMirror * pointBegin - pointEndRotated = segmentYMirror * pointEnd - if isLoopListIntersectingInsideXSegment( loops, pointBeginRotated.real, pointEndRotated.real, segmentYMirror, pointBeginRotated.imag ): - return True - return False - -def isLoopIntersectingInsideXSegment( loop, segmentFirstX, segmentSecondX, segmentYMirror, y ): - """Determine if the loop is intersecting inside the x segment.""" - rotatedLoop = getPointsRoundZAxis( segmentYMirror, loop ) - for pointIndex in xrange( len( rotatedLoop ) ): - pointFirst = rotatedLoop[pointIndex] - pointSecond = rotatedLoop[ (pointIndex + 1) % len( rotatedLoop ) ] - if isLineIntersectingInsideXSegment( pointFirst, pointSecond, segmentFirstX, segmentSecondX, y ): - return True - return False - -def isLoopIntersectingLoop( loop, otherLoop ): - """Determine if the loop is intersecting the other loop.""" - for pointIndex in xrange(len(loop)): - pointBegin = loop[pointIndex] - pointEnd = loop[(pointIndex + 1) % len(loop)] - if isLineIntersectingLoop( otherLoop, pointBegin, pointEnd ): - return True - return False - -def isLoopIntersectingLoops( loop, otherLoops ): - """Determine if the loop is intersecting other loops.""" - for pointIndex in xrange(len(loop)): - pointBegin = loop[pointIndex] - pointEnd = loop[(pointIndex + 1) % len(loop)] - if isLineIntersectingLoops( otherLoops, pointBegin, pointEnd ): - return True - return False - -def isLoopListIntersectingInsideXSegment( loopList, segmentFirstX, segmentSecondX, segmentYMirror, y ): - """Determine if the loop list is crossing inside the x segment.""" - for alreadyFilledLoop in loopList: - if isLoopIntersectingInsideXSegment( alreadyFilledLoop, segmentFirstX, segmentSecondX, segmentYMirror, y ): - return True - return False - -def isLoopListIntersecting(loops): - """Determine if a loop in the list is intersecting the other loops.""" - for loopIndex in xrange(len(loops) - 1): - loop = loops[loopIndex] - if isLoopIntersectingLoops(loop, loops[loopIndex + 1 :]): - return True - return False - -def isPathEntirelyInsideLoop(loop, path): - """Determine if a path is entirely inside another loop.""" - for point in path: - if not isPointInsideLoop(loop, point): - return False - return True - -def isPathEntirelyInsideLoops(loops, path): - """Determine if a path is entirely inside another loop in a list.""" - for loop in loops: - if isPathEntirelyInsideLoop(loop, path): - return True - return False - -def isPathInsideLoop(loop, path): - """Determine if a path is inside another loop.""" - return isPointInsideLoop(loop, getLeftPoint(path)) - -def isPathInsideLoops(loops, path): - """Determine if a path is inside another loop in a list.""" - for loop in loops: - if isPathInsideLoop(loop, path): - return True - return False - -def isPixelTableIntersecting( bigTable, littleTable, maskTable = {} ): - """Add path to the pixel table.""" - littleTableKeys = littleTable.keys() - for littleTableKey in littleTableKeys: - if littleTableKey not in maskTable: - if littleTableKey in bigTable: - return True - return False - -def isPointInsideLoop(loop, point): - """Determine if a point is inside another loop.""" - return getNumberOfIntersectionsToLeft(loop, point) % 2 == 1 - -def isSegmentCompletelyInX( segment, xFirst, xSecond ): - """Determine if the segment overlaps within x.""" - segmentFirstX = segment[0].point.real - segmentSecondX = segment[1].point.real - if max( segmentFirstX, segmentSecondX ) > max( xFirst, xSecond ): - return False - return min( segmentFirstX, segmentSecondX ) >= min( xFirst, xSecond ) - -def isWiddershins(polygonComplex): - """Determine if the complex polygon goes round in the widdershins direction.""" - return getAreaLoop(polygonComplex) > 0.0 - -def isWithinChannel( channelRadius, pointIndex, loop ): - """Determine if the the point is within the channel between two adjacent points.""" - point = loop[pointIndex] - behindSegmentComplex = loop[(pointIndex + len(loop) - 1) % len(loop)] - point - behindSegmentComplexLength = abs( behindSegmentComplex ) - if behindSegmentComplexLength < channelRadius: - return True - aheadSegmentComplex = loop[(pointIndex + 1) % len(loop)] - point - aheadSegmentComplexLength = abs( aheadSegmentComplex ) - if aheadSegmentComplexLength < channelRadius: - return True - behindSegmentComplex /= behindSegmentComplexLength - aheadSegmentComplex /= aheadSegmentComplexLength - absoluteZ = getDotProductPlusOne( aheadSegmentComplex, behindSegmentComplex ) - if behindSegmentComplexLength * absoluteZ < channelRadius: - return True - return aheadSegmentComplexLength * absoluteZ < channelRadius - -def isXSegmentIntersectingPath( path, segmentFirstX, segmentSecondX, segmentYMirror, y ): - """Determine if a path is crossing inside the x segment.""" - rotatedPath = getPointsRoundZAxis( segmentYMirror, path ) - for pointIndex in xrange( len( rotatedPath ) - 1 ): - pointFirst = rotatedPath[pointIndex] - pointSecond = rotatedPath[pointIndex + 1] - if isLineIntersectingInsideXSegment( pointFirst, pointSecond, segmentFirstX, segmentSecondX, y ): - return True - return False - -def isXSegmentIntersectingPaths( paths, segmentFirstX, segmentSecondX, segmentYMirror, y ): - """Determine if a path list is crossing inside the x segment.""" - for path in paths: - if isXSegmentIntersectingPath( path, segmentFirstX, segmentSecondX, segmentYMirror, y ): - return True - return False - -def joinSegmentTables( fromTable, intoTable ): - """Join both segment tables and put the join into the intoTable.""" - intoTableKeys = intoTable.keys() - fromTableKeys = fromTable.keys() - joinedKeyTable = {} - concatenatedTableKeys = intoTableKeys + fromTableKeys - for concatenatedTableKey in concatenatedTableKeys: - joinedKeyTable[ concatenatedTableKey ] = None - joinedKeys = joinedKeyTable.keys() - joinedKeys.sort() - for joinedKey in joinedKeys: - xIntersectionIndexList = [] - if joinedKey in intoTable: - addXIntersectionIndexesFromSegments( 0, intoTable[ joinedKey ], xIntersectionIndexList ) - if joinedKey in fromTable: - addXIntersectionIndexesFromSegments( 1, fromTable[ joinedKey ], xIntersectionIndexList ) - xIntersections = getJoinOfXIntersectionIndexes( xIntersectionIndexList ) - lineSegments = getSegmentsFromXIntersections( xIntersections, joinedKey ) - if len( lineSegments ) > 0: - intoTable[ joinedKey ] = lineSegments - else: - print('This should never happen, there are no line segments in joinSegments in euclidean') - -def joinXIntersectionsTables( fromTable, intoTable ): - """Join both XIntersections tables and put the join into the intoTable.""" - joinedKeyTable = {} - concatenatedTableKeys = fromTable.keys() + intoTable.keys() - for concatenatedTableKey in concatenatedTableKeys: - joinedKeyTable[ concatenatedTableKey ] = None - for joinedKey in joinedKeyTable.keys(): - xIntersectionIndexList = [] - if joinedKey in intoTable: - addXIntersectionIndexesFromXIntersections( 0, xIntersectionIndexList, intoTable[ joinedKey ] ) - if joinedKey in fromTable: - addXIntersectionIndexesFromXIntersections( 1, xIntersectionIndexList, fromTable[ joinedKey ] ) - xIntersections = getJoinOfXIntersectionIndexes( xIntersectionIndexList ) - if len( xIntersections ) > 0: - intoTable[ joinedKey ] = xIntersections - else: - print('This should never happen, there are no line segments in joinSegments in euclidean') - -def overwriteDictionary(fromDictionary, keys, toDictionary): - """Overwrite the dictionary.""" - for key in keys: - if key in fromDictionary: - toDictionary[key] = fromDictionary[key] - -def removeElementFromDictionary(dictionary, key): - """Remove element from the dictionary.""" - if key in dictionary: - del dictionary[key] - -def removeElementFromListTable(element, key, listDictionary): - """Remove an element from the list table.""" - if key not in listDictionary: - return - elementList = listDictionary[key] - if len( elementList ) < 2: - del listDictionary[key] - return - if element in elementList: - elementList.remove(element) - -def removeElementFromPixelListFromPoint( element, pixelDictionary, point ): - """Remove an element from the pixel list.""" - stepKey = getStepKeyFromPoint(point) - removeElementFromListTable( element, stepKey, pixelDictionary ) - -def removeElementsFromDictionary(dictionary, keys): - """Remove list from the dictionary.""" - for key in keys: - removeElementFromDictionary(dictionary, key) - -def removePrefixFromDictionary( dictionary, prefix ): - """Remove the attributes starting with the prefix from the dictionary.""" - for key in dictionary.keys(): - if key.startswith( prefix ): - del dictionary[key] - -def removePixelTableFromPixelTable( pixelDictionaryToBeRemoved, pixelDictionaryToBeRemovedFrom ): - """Remove pixel from the pixel table.""" - removeElementsFromDictionary( pixelDictionaryToBeRemovedFrom, pixelDictionaryToBeRemoved.keys() ) - -def removeTrueFromDictionary(dictionary, key): - """Remove key from the dictionary in the value is true.""" - if key in dictionary: - if getBooleanFromValue(dictionary[key]): - del dictionary[key] - -def removeTrueListFromDictionary( dictionary, keys ): - """Remove list from the dictionary in the value is true.""" - for key in keys: - removeTrueFromDictionary( dictionary, key ) - -def subtractXIntersectionsTable( subtractFromTable, subtractTable ): - """Subtract the subtractTable from the subtractFromTable.""" - subtractFromTableKeys = subtractFromTable.keys() - subtractFromTableKeys.sort() - for subtractFromTableKey in subtractFromTableKeys: - xIntersectionIndexList = [] - addXIntersectionIndexesFromXIntersections( - 1, xIntersectionIndexList, subtractFromTable[ subtractFromTableKey ] ) - if subtractFromTableKey in subtractTable: - addXIntersectionIndexesFromXIntersections( 0, xIntersectionIndexList, subtractTable[ subtractFromTableKey ] ) - xIntersections = getXIntersectionsFromIntersections( xIntersectionIndexList ) - if len( xIntersections ) > 0: - subtractFromTable[ subtractFromTableKey ] = xIntersections - else: - del subtractFromTable[ subtractFromTableKey ] - -def swapList( elements, indexBegin, indexEnd ): - """Swap the list elements.""" - elements[ indexBegin ], elements[ indexEnd ] = elements[ indexEnd ], elements[ indexBegin ] - -def toggleHashtable( hashtable, key, value ): - """Toggle a hashtable between having and not having a key.""" - if key in hashtable: - del hashtable[key] - else: - hashtable[key] = value - -def transferClosestFillLoop(extrusionHalfWidth, oldOrderedLocation, remainingFillLoops, skein): - """Transfer the closest remaining fill loop.""" - closestDistance = 987654321987654321.0 - closestFillLoop = None - for remainingFillLoop in remainingFillLoops: - distance = getNearestDistanceIndex(oldOrderedLocation.dropAxis(), remainingFillLoop).distance - if distance < closestDistance: - closestDistance = distance - closestFillLoop = remainingFillLoop - newClosestFillLoop = getLoopInsideContainingLoop(closestFillLoop, remainingFillLoops) - while newClosestFillLoop is not None: - closestFillLoop = newClosestFillLoop - newClosestFillLoop = getLoopInsideContainingLoop(closestFillLoop, remainingFillLoops) - remainingFillLoops.remove(closestFillLoop) - addToThreadsFromLoop(extrusionHalfWidth, 'loop', closestFillLoop[:], oldOrderedLocation, skein) - -def transferClosestPath( oldOrderedLocation, remainingPaths, skein ): - """Transfer the closest remaining path.""" - closestDistance = 987654321987654321.0 - closestPath = None - oldOrderedLocationComplex = oldOrderedLocation.dropAxis() - for remainingPath in remainingPaths: - distance = min( abs( oldOrderedLocationComplex - remainingPath[0] ), abs( oldOrderedLocationComplex - remainingPath[-1] ) ) - if distance < closestDistance: - closestDistance = distance - closestPath = remainingPath - remainingPaths.remove( closestPath ) - skein.addGcodeFromThreadZ( closestPath, oldOrderedLocation.z ) - oldOrderedLocation.x = closestPath[-1].real - oldOrderedLocation.y = closestPath[-1].imag - -def transferClosestPaths(oldOrderedLocation, remainingPaths, skein): - """Transfer the closest remaining paths.""" - while len(remainingPaths) > 0: - transferClosestPath(oldOrderedLocation, remainingPaths, skein) - -def transferPathsToSurroundingLoops(nestedRings, paths): - """Transfer paths to surrounding loops.""" - for nestedRing in nestedRings: - nestedRing.transferPaths(paths) - -def translateVector3Path(path, translateVector3): - """Translate the vector3 path.""" - for point in path: - point.setToVector3(point + translateVector3) - -def translateVector3Paths(paths, translateVector3): - """Translate the vector3 paths.""" - for path in paths: - translateVector3Path(path, translateVector3) - -def unbuckleBasis( basis, maximumUnbuckling, normal ): - """Unbuckle space.""" - normalDot = basis.dot( normal ) - dotComplement = math.sqrt( 1.0 - normalDot * normalDot ) - unbuckling = maximumUnbuckling - if dotComplement > 0.0: - unbuckling = min( 1.0 / dotComplement, maximumUnbuckling ) - basis.setToVector3( basis * unbuckling ) - - -class DistanceIndex: - """A class to hold the distance and the index of the loop.""" - def __init__( self, distance, index ): - self.distance = distance - self.index = index - - def __repr__(self): - """Get the string representation of this distance index.""" - return '%s, %s' % ( self.distance, self.index ) - - -class Endpoint: - """The endpoint of a segment.""" - def __repr__(self): - """Get the string representation of this Endpoint.""" - return 'Endpoint %s, %s' % ( self.point, self.otherEndpoint.point ) - - def getFromOtherPoint( self, otherEndpoint, point ): - """Initialize from other endpoint.""" - self.otherEndpoint = otherEndpoint - self.point = point - return self - - def getNearestEndpoint( self, endpoints ): - """Get nearest endpoint.""" - smallestDistance = 987654321987654321.0 - nearestEndpoint = None - for endpoint in endpoints: - distance = abs( self.point - endpoint.point ) - if distance < smallestDistance: - smallestDistance = distance - nearestEndpoint = endpoint - return nearestEndpoint - - def getNearestMiss(self, endpoints, path, pixelDictionary, width): - """Get the nearest endpoint which the segment to that endpoint misses the other extrusions.""" - pathMaskTable = {} - smallestDistance = 987654321.0 - penultimateMinusPoint = complex(0.0, 0.0) - if len(path) > 1: - penultimatePoint = path[-2] - addSegmentToPixelTable(penultimatePoint, self.point, pathMaskTable, 0, 0, width) - penultimateMinusPoint = penultimatePoint - self.point - if abs(penultimateMinusPoint) > 0.0: - penultimateMinusPoint /= abs(penultimateMinusPoint) - for endpoint in endpoints: - endpoint.segment = endpoint.point - self.point - endpoint.segmentLength = abs(endpoint.segment) - if endpoint.segmentLength <= 0.0: -# print('This should never happen, the endpoints are touching') -# print( endpoint ) -# print(path) - return endpoint - endpoints.sort(compareSegmentLength) - for endpoint in endpoints[: 15]: # increasing the number of searched endpoints increases the search time, with 20 fill took 600 seconds for cilinder.gts, with 10 fill took 533 seconds - normalizedSegment = endpoint.segment / endpoint.segmentLength - isOverlappingSelf = getDotProduct(penultimateMinusPoint, normalizedSegment) > 0.9 - if not isOverlappingSelf: - if len(path) > 2: - segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) - pointRotated = segmentYMirror * self.point - endpointPointRotated = segmentYMirror * endpoint.point - if isXSegmentIntersectingPath(path[max(0, len(path) - 21) : -1], pointRotated.real, endpointPointRotated.real, segmentYMirror, pointRotated.imag): - isOverlappingSelf = True - if not isOverlappingSelf: - totalMaskTable = pathMaskTable.copy() - addSegmentToPixelTable(endpoint.point, endpoint.otherEndpoint.point, totalMaskTable, 0, 0, width) - segmentTable = {} - addSegmentToPixelTable(self.point, endpoint.point, segmentTable, 0, 0, width) - if not isPixelTableIntersecting(pixelDictionary, segmentTable, totalMaskTable): - return endpoint - return None - - def getNearestMissCheckEndpointPath( self, endpoints, path, pixelDictionary, width ): - """Get the nearest endpoint which the segment to that endpoint misses the other extrusions, also checking the path of the endpoint.""" - pathMaskTable = {} - smallestDistance = 987654321.0 - penultimateMinusPoint = complex(0.0, 0.0) - if len(path) > 1: - penultimatePoint = path[-2] - addSegmentToPixelTable( penultimatePoint, self.point, pathMaskTable, 0, 0, width ) - penultimateMinusPoint = penultimatePoint - self.point - if abs(penultimateMinusPoint) > 0.0: - penultimateMinusPoint /= abs(penultimateMinusPoint) - for endpoint in endpoints: - endpoint.segment = endpoint.point - self.point - endpoint.segmentLength = abs(endpoint.segment) - if endpoint.segmentLength <= 0.0: -# print('This should never happen, the endpoints are touching') -# print( endpoint ) -# print(path) - return endpoint - endpoints.sort( compareSegmentLength ) - for endpoint in endpoints[ : 15 ]: # increasing the number of searched endpoints increases the search time, with 20 fill took 600 seconds for cilinder.gts, with 10 fill took 533 seconds - normalizedSegment = endpoint.segment / endpoint.segmentLength - isOverlappingSelf = getDotProduct( penultimateMinusPoint, normalizedSegment ) > 0.9 - if not isOverlappingSelf: - if len(path) > 2: - segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) - pointRotated = segmentYMirror * self.point - endpointPointRotated = segmentYMirror * endpoint.point - if isXSegmentIntersectingPath( path[ max( 0, len(path) - 21 ) : - 1 ], pointRotated.real, endpointPointRotated.real, segmentYMirror, pointRotated.imag ): - isOverlappingSelf = True - endpointPath = endpoint.path - if len( endpointPath ) > 2: - segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) - pointRotated = segmentYMirror * self.point - endpointPointRotated = segmentYMirror * endpoint.point - if isXSegmentIntersectingPath( endpointPath, pointRotated.real, endpointPointRotated.real, segmentYMirror, pointRotated.imag ): - isOverlappingSelf = True - if not isOverlappingSelf: - totalMaskTable = pathMaskTable.copy() - addSegmentToPixelTable( endpoint.point, endpoint.otherEndpoint.point, totalMaskTable, 0, 0, width ) - segmentTable = {} - addSegmentToPixelTable( self.point, endpoint.point, segmentTable, 0, 0, width ) - if not isPixelTableIntersecting( pixelDictionary, segmentTable, totalMaskTable ): - return endpoint - return None - - -class LoopLayer: - """Loops with a z.""" - def __init__(self, z): - self.loops = [] - self.z = z - - def __repr__(self): - """Get the string representation of this loop layer.""" - return '%s, %s' % ( self.z, self.loops ) - - -class NestedRing: - """A nested ring.""" - def __init__(self): - """Initialize.""" - self.boundary = [] - self.innerNestedRings = None - - def __repr__(self): - """Get the string representation of this surrounding loop.""" - return str(self.__dict__) - - def addFlattenedNestedRings(self, flattenedNestedRings): - """Add flattened nested rings.""" - flattenedNestedRings.append(self) - for innerNestedRing in self.innerNestedRings: - flattenedNestedRings += getFlattenedNestedRings(innerNestedRing.innerNestedRings) - - def getFromInsideSurroundings(self, inputSurroundingInsides): - """Initialize from inside surrounding loops.""" - transferredSurroundings = getTransferredSurroundingLoops(inputSurroundingInsides, self.boundary) - self.innerNestedRings = getOrderedNestedRings(transferredSurroundings) - return self - - -class NestedBand(NestedRing): - """A loop that surrounds paths.""" - def __init__(self): - """Initialize.""" - NestedRing.__init__(self) - self.extraLoops = [] - self.infillPaths = [] -# self.lastExistingFillLoops = None - self.lastFillLoops = None - self.loop = None - self.penultimateFillLoops = [] - self.perimeterPaths = [] - self.z = None - - def __repr__(self): - """Get the string representation of this surrounding loop.""" - stringRepresentation = 'boundary\n%s\n' % self.boundary - stringRepresentation += 'loop\n%s\n' % self.loop - stringRepresentation += 'inner nested rings\n%s\n' % self.innerNestedRings - stringRepresentation += 'infillPaths\n' - for infillPath in self.infillPaths: - stringRepresentation += 'infillPath\n%s\n' % infillPath - stringRepresentation += 'perimeterPaths\n' - for perimeterPath in self.perimeterPaths: - stringRepresentation += 'perimeterPath\n%s\n' % perimeterPath - return stringRepresentation + '\n' - - def addToBoundary(self, vector3): - """Add vector3 to boundary.""" - self.boundary.append(vector3.dropAxis()) - self.z = vector3.z - - def addToLoop(self, vector3): - """Add vector3 to loop.""" - if self.loop is None: - self.loop = [] - self.loop.append(vector3.dropAxis()) - self.z = vector3.z - - def addPerimeterInner(self, extrusionHalfWidth, oldOrderedLocation, skein, threadSequence): - """Add to the perimeter and the inner island.""" - if self.loop is None: - skein.distanceFeedRate.addLine('()') - transferClosestPaths(oldOrderedLocation, self.perimeterPaths[:], skein) - skein.distanceFeedRate.addLine('()') - else: - addToThreadsFromLoop(extrusionHalfWidth, 'perimeter', self.loop[:], oldOrderedLocation, skein) - skein.distanceFeedRate.addLine('()') - addToThreadsRemove(extrusionHalfWidth, self.innerNestedRings[:], oldOrderedLocation, skein, threadSequence) - - def addToThreads(self, extrusionHalfWidth, oldOrderedLocation, skein, threadSequence): - """Add to paths from the last location. perimeter>inner >fill>paths or fill> perimeter>inner >paths""" - addSurroundingLoopBeginning(skein.distanceFeedRate, self.boundary, self.z) - threadFunctionDictionary = { - 'infill' : self.transferInfillPaths, 'loops' : self.transferClosestFillLoops, 'perimeter' : self.addPerimeterInner} - for threadType in threadSequence: - threadFunctionDictionary[threadType](extrusionHalfWidth, oldOrderedLocation, skein, threadSequence) - skein.distanceFeedRate.addLine('()') - - def getFillLoops(self, penultimateFillLoops): - """Get last fill loops from the outside loop and the loops inside the inside loops.""" - fillLoops = self.getLoopsToBeFilled()[:] - surroundingBoundaries = self.getSurroundingBoundaries() - withinLoops = [] - if penultimateFillLoops is None: - penultimateFillLoops = self.penultimateFillLoops - for penultimateFillLoop in penultimateFillLoops: - if len(penultimateFillLoop) > 2: - if getIsInFilledRegion(surroundingBoundaries, penultimateFillLoop[0]): - withinLoops.append(penultimateFillLoop) - if not getIsInFilledRegionByPaths(self.penultimateFillLoops, fillLoops): - fillLoops += self.penultimateFillLoops - for nestedRing in self.innerNestedRings: - fillLoops += getFillOfSurroundings(nestedRing.innerNestedRings, penultimateFillLoops) - return fillLoops -# -# def getLastExistingFillLoops(self): -# 'Get last existing fill loops.' -# lastExistingFillLoops = self.lastExistingFillLoops[:] -# for nestedRing in self.innerNestedRings: -# lastExistingFillLoops += nestedRing.getLastExistingFillLoops() -# return lastExistingFillLoops - - def getLoopsToBeFilled(self): - """Get last fill loops from the outside loop and the loops inside the inside loops.""" - if self.lastFillLoops is None: - return self.getSurroundingBoundaries() - return self.lastFillLoops - - def getSurroundingBoundaries(self): - """Get the boundary of the surronding loop plus any boundaries of the innerNestedRings.""" - surroundingBoundaries = [self.boundary] - for nestedRing in self.innerNestedRings: - surroundingBoundaries.append(nestedRing.boundary) - return surroundingBoundaries - - def transferClosestFillLoops(self, extrusionHalfWidth, oldOrderedLocation, skein, threadSequence): - """Transfer closest fill loops.""" - if len( self.extraLoops ) < 1: - return - remainingFillLoops = self.extraLoops[:] - while len( remainingFillLoops ) > 0: - transferClosestFillLoop(extrusionHalfWidth, oldOrderedLocation, remainingFillLoops, skein) - - def transferInfillPaths(self, extrusionHalfWidth, oldOrderedLocation, skein, threadSequence): - """Transfer the infill paths.""" - transferClosestPaths(oldOrderedLocation, self.infillPaths[:], skein) - - def transferPaths(self, paths): - """Transfer paths.""" - for nestedRing in self.innerNestedRings: - transferPathsToSurroundingLoops(nestedRing.innerNestedRings, paths) - self.infillPaths = getTransferredPaths(paths, self.boundary) - - -class PathZ: - """Complex path with a z.""" - def __init__( self, z ): - self.path = [] - self.z = z - - def __repr__(self): - """Get the string representation of this path z.""" - return '%s, %s' % ( self.z, self.path ) - - -class ProjectiveSpace: - """Class to define a projective space.""" - def __init__( self, basisX = Vector3(1.0, 0.0, 0.0), basisY = Vector3( 0.0, 1.0, 0.0 ), basisZ = Vector3(0.0, 0.0, 1.0) ): - """Initialize the basis vectors.""" - self.basisX = basisX - self.basisY = basisY - self.basisZ = basisZ - - def __repr__(self): - """Get the string representation of this ProjectivePlane.""" - return '%s, %s, %s' % ( self.basisX, self.basisY, self.basisZ ) - - def getByBasisXZ( self, basisX, basisZ ): - """Get by x basis x and y basis.""" - self.basisX = basisX - self.basisZ = basisZ - self.basisX.normalize() - self.basisY = basisZ.cross(self.basisX) - self.basisY.normalize() - return self - - def getByBasisZFirst(self, basisZ, firstVector3): - """Get by basisZ and first.""" - self.basisZ = basisZ - self.basisY = basisZ.cross(firstVector3) - self.basisY.normalize() - self.basisX = self.basisY.cross(self.basisZ) - self.basisX.normalize() - return self - - def getByBasisZTop(self, basisZ, top): - """Get by basisZ and top.""" - return self.getByBasisXZ(top.cross(basisZ), basisZ) - - def getByLatitudeLongitude( self, viewpointLatitude, viewpointLongitude ): - """Get by latitude and longitude.""" - longitudeComplex = getWiddershinsUnitPolar( math.radians( 90.0 - viewpointLongitude ) ) - viewpointLatitudeRatio = getWiddershinsUnitPolar( math.radians( viewpointLatitude ) ) - basisZ = Vector3( viewpointLatitudeRatio.imag * longitudeComplex.real, viewpointLatitudeRatio.imag * longitudeComplex.imag, viewpointLatitudeRatio.real ) - return self.getByBasisXZ( Vector3( - longitudeComplex.imag, longitudeComplex.real, 0.0 ), basisZ ) - - def getByTilt( self, tilt ): - """Get by latitude and longitude.""" - xPlaneAngle = getWiddershinsUnitPolar( tilt.real ) - self.basisX = Vector3( xPlaneAngle.real, 0.0, xPlaneAngle.imag ) - yPlaneAngle = getWiddershinsUnitPolar( tilt.imag ) - self.basisY = Vector3( 0.0, yPlaneAngle.real, yPlaneAngle.imag ) - self.basisZ = self.basisX.cross(self.basisY) - return self - - def getComplexByComplex( self, pointComplex ): - """Get complex by complex point.""" - return self.basisX.dropAxis() * pointComplex.real + self.basisY.dropAxis() * pointComplex.imag - - def getCopy(self): - """Get copy.""" - return ProjectiveSpace( self.basisX, self.basisY, self.basisZ ) - - def getDotComplex(self, point): - """Get the dot complex.""" - return complex( point.dot(self.basisX), point.dot(self.basisY) ) - - def getDotVector3(self, point): - """Get the dot vector3.""" - return Vector3(point.dot(self.basisX), point.dot(self.basisY), point.dot(self.basisZ)) - - def getNextSpace( self, nextNormal ): - """Get next space by next normal.""" - nextSpace = self.getCopy() - nextSpace.normalize() - dotNext = nextSpace.basisZ.dot( nextNormal ) - if dotNext > 0.999999: - return nextSpace - if dotNext < - 0.999999: - nextSpace.basisX = - nextSpace.basisX - return nextSpace - crossNext = nextSpace.basisZ.cross( nextNormal ) - oldBasis = ProjectiveSpace().getByBasisZTop( nextSpace.basisZ, crossNext ) - newBasis = ProjectiveSpace().getByBasisZTop( nextNormal, crossNext ) - nextSpace.basisX = newBasis.getVector3ByPoint( oldBasis.getDotVector3( nextSpace.basisX ) ) - nextSpace.basisY = newBasis.getVector3ByPoint( oldBasis.getDotVector3( nextSpace.basisY ) ) - nextSpace.basisZ = newBasis.getVector3ByPoint( oldBasis.getDotVector3( nextSpace.basisZ ) ) - nextSpace.normalize() - return nextSpace - - def getSpaceByXYScaleAngle( self, angle, scale ): - """Get space by angle and scale.""" - spaceByXYScaleRotation = ProjectiveSpace() - planeAngle = getWiddershinsUnitPolar(angle) - spaceByXYScaleRotation.basisX = self.basisX * scale.real * planeAngle.real + self.basisY * scale.imag * planeAngle.imag - spaceByXYScaleRotation.basisY = - self.basisX * scale.real * planeAngle.imag + self.basisY * scale.imag * planeAngle.real - spaceByXYScaleRotation.basisZ = self.basisZ - return spaceByXYScaleRotation - - def getVector3ByPoint(self, point): - """Get vector3 by point.""" - return self.basisX * point.x + self.basisY * point.y + self.basisZ * point.z - - def normalize(self): - """Normalize.""" - self.basisX.normalize() - self.basisY.normalize() - self.basisZ.normalize() - - def unbuckle( self, maximumUnbuckling, normal ): - """Unbuckle space.""" - unbuckleBasis( self.basisX, maximumUnbuckling, normal ) - unbuckleBasis( self.basisY, maximumUnbuckling, normal ) - - -class RotatedLoopLayer: - """A rotated layer.""" - def __init__( self, z ): - self.loops = [] - self.rotation = None - self.z = z - - def __repr__(self): - """Get the string representation of this rotated loop layer.""" - return '%s, %s, %s' % ( self.z, self.rotation, self.loops ) - - def addXML(self, depth, output): - """Add the xml for this object.""" - if len( self.loops ) < 1: - return - if len( self.loops ) == 1: - xml_simple_writer.addXMLFromLoopComplexZ( {}, depth, self.loops[0], output, self.z ) - return - xml_simple_writer.addBeginXMLTag( {}, 'group', depth, output ) - for loop in self.loops: - xml_simple_writer.addXMLFromLoopComplexZ( {}, depth + 1, loop, output, self.z ) - xml_simple_writer.addEndXMLTag('group', depth, output ) - - def getCopyAtZ( self, z ): - """Get a raised copy.""" - raisedRotatedLoopLayer = RotatedLoopLayer(z) - for loop in self.loops: - raisedRotatedLoopLayer.loops.append( loop[:] ) - raisedRotatedLoopLayer.rotation = self.rotation - return raisedRotatedLoopLayer - -def getFlattenedNestedRings(nestedRings): - """Get flattened nested rings.""" - flattenedNestedRings = [] - for nestedRing in nestedRings: - nestedRing.addFlattenedNestedRings(flattenedNestedRings) - return flattenedNestedRings - - -class XIntersectionIndex: - """A class to hold the x intersection position and the index of the loop which intersected.""" - def __init__( self, index, x ): - """Initialize.""" - self.index = index - self.x = x - - def __cmp__(self, other): - """Get comparison in order to sort x intersections in ascending order of x.""" - if self.x < other.x: - return - 1 - return int( self.x > other.x ) - - def __eq__(self, other): - """Determine whether this XIntersectionIndex is identical to other one.""" - if other is None: - return False - if other.__class__ != self.__class__: - return False - return self.index == other.index and self.x == other.x - - def __ne__(self, other): - """Determine whether this XIntersectionIndex is not identical to other one.""" - return not self.__eq__(other) - - def __repr__(self): - """Get the string representation of this x intersection.""" - return 'XIntersectionIndex index %s; x %s ' % ( self.index, self.x ) diff --git a/skeinforge/fabmetheus_utilities/fabmetheus_tools/__init__.py b/skeinforge/fabmetheus_utilities/fabmetheus_tools/__init__.py deleted file mode 100644 index 2dc8ddc..0000000 --- a/skeinforge/fabmetheus_utilities/fabmetheus_tools/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 2 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/fabmetheus_tools/fabmetheus_interpret.py b/skeinforge/fabmetheus_utilities/fabmetheus_tools/fabmetheus_interpret.py deleted file mode 100644 index bb1b070..0000000 --- a/skeinforge/fabmetheus_utilities/fabmetheus_tools/fabmetheus_interpret.py +++ /dev/null @@ -1,146 +0,0 @@ -""" -Interpret is a collection of utilities to list the import plugins. - -An import plugin is a script in the interpret_plugins folder which has the function getCarving. - -The following examples shows functions of fabmetheus_interpret. The examples are run in a terminal in the folder which contains fabmetheus_interpret.py. - - -> python -Python 2.5.1 (r251:54863, Sep 22 2007, 01:43:31) -[GCC 4.2.1 (SUSE Linux)] on linux2 -Type "help", "copyright", "credits" or "license" for more information. ->>> import interpret ->>> fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples() -[('GTS files', '*.gts'), ('Gcode text files', '*.gcode'), ('STL files', '*.stl'), ('SVG files', '*.svg')] - ->>> fabmetheus_interpret.getImportPluginFileNames() -['gts', 'stl', 'svg'] - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import os -import time - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCarving(fileName): - """Get carving.""" - pluginModule = getInterpretPlugin(fileName) - if pluginModule is None: - return None - return pluginModule.getCarving(fileName) - -def getGNUTranslatorGcodeFileTypeTuples(): - """Get the file type tuples from the translators in the import plugins folder plus gcode.""" - fileTypeTuples = getTranslatorFileTypeTuples() - fileTypeTuples.append( ('Gcode text files', '*.gcode') ) - fileTypeTuples.sort() - return fileTypeTuples - -def getGNUTranslatorFilesUnmodified(): - """Get the file types from the translators in the import plugins folder.""" - return archive.getFilesWithFileTypesWithoutWords(getImportPluginFileNames()) - -def getImportPluginFileNames(): - """Get interpret plugin fileNames.""" - return archive.getPluginFileNamesFromDirectoryPath( getPluginsDirectoryPath() ) - -def getInterpretPlugin(fileName): - """Get the interpret plugin for the file.""" - importPluginFileNames = getImportPluginFileNames() - for importPluginFileName in importPluginFileNames: - fileTypeDot = '.' + importPluginFileName - if fileName[ - len(fileTypeDot) : ].lower() == fileTypeDot: - importPluginsDirectoryPath = getPluginsDirectoryPath() - pluginModule = archive.getModuleWithDirectoryPath( importPluginsDirectoryPath, importPluginFileName ) - if pluginModule is not None: - return pluginModule - print('Could not find plugin to handle ' + fileName ) - return None - -def getNewRepository(): - """Get new repository.""" - return InterpretRepository() - -def getPluginsDirectoryPath(): - """Get the plugins directory path.""" - return archive.getAbsoluteFrozenFolderPath( __file__, 'interpret_plugins') - -def getTranslatorFileTypeTuples(): - """Get the file types from the translators in the import plugins folder.""" - importPluginFileNames = getImportPluginFileNames() - fileTypeTuples = [] - for importPluginFileName in importPluginFileNames: - fileTypeTitle = importPluginFileName.upper() + ' files' - fileType = ( fileTypeTitle, '*.' + importPluginFileName ) - fileTypeTuples.append( fileType ) - fileTypeTuples.sort() - return fileTypeTuples - -def getWindowAnalyzeFile(fileName): - """Get file interpretion.""" - startTime = time.time() - carving = getCarving(fileName) - if carving is None: - return None - interpretGcode = str( carving ) - if interpretGcode == '': - return None - repository = settings.getReadRepository( InterpretRepository() ) - if repository.printInterpretion.value: - print( interpretGcode ) - suffixFileName = fileName[ : fileName.rfind('.') ] + '_interpret.' + carving.getInterpretationSuffix() - suffixDirectoryName = os.path.dirname(suffixFileName) - suffixReplacedBaseName = os.path.basename(suffixFileName).replace(' ', '_') - suffixFileName = os.path.join( suffixDirectoryName, suffixReplacedBaseName ) - archive.writeFileText( suffixFileName, interpretGcode ) - print('The interpret file is saved as ' + archive.getSummarizedFileName(suffixFileName) ) - print('It took %s to interpret the file.' % euclidean.getDurationString( time.time() - startTime ) ) - textProgram = repository.textProgram.value - if textProgram == '': - return None - if textProgram == 'webbrowser': - settings.openWebPage(suffixFileName) - return None - textFilePath = '"' + os.path.normpath(suffixFileName) + '"' # " to send in file name with spaces - shellCommand = textProgram + ' ' + textFilePath - print('Sending the shell command:') - print(shellCommand) - commandResult = os.system(shellCommand) - if commandResult: - print('It may be that the system could not find the %s program.' % textProgram ) - print('If so, try installing the %s program or look for another one, like Open Office which can be found at:' % textProgram ) - print('http://www.openoffice.org/') - print('Open office writer can then be started from the command line with the command "soffice -writer".') - - -class InterpretRepository: - """A class to handle the interpret settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.analyze_plugins.interpret.html', self) - self.fileNameInput = settings.FileNameInput().getFromFileName( getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Interpret', self, '') - self.activateInterpret = settings.BooleanSetting().getFromValue('Activate Interpret', self, False ) - self.printInterpretion = settings.BooleanSetting().getFromValue('Print Interpretion', self, False ) - self.textProgram = settings.StringSetting().getFromValue('Text Program:', self, 'webbrowser') - self.executeTitle = 'Interpret' - - def execute(self): - """Write button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrGcodeDirectory( self.fileNameInput.value, self.fileNameInput.wasCancelled ) - for fileName in fileNames: - getWindowAnalyzeFile(fileName) diff --git a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/__init__.py b/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/__init__.py deleted file mode 100644 index cefa3e7..0000000 --- a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -This page is in the table of contents. -This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -""" -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/csv.py b/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/csv.py deleted file mode 100644 index 9834f63..0000000 --- a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/csv.py +++ /dev/null @@ -1,159 +0,0 @@ -""" -This page is in the table of contents. -The csv.py script is an import translator plugin to get a carving from an csv file. - -An import plugin is a script in the interpret_plugins folder which has the function getCarving. It is meant to be run from the interpret tool. To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name. - -The getCarving function takes the file name of an csv file and returns the carving. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import xml_simple_reader -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCarving(fileName=''): - """Get the carving for the csv file.""" - csvText = archive.getFileText(fileName) - if csvText == '': - return None - csvParser = CSVSimpleParser( fileName, None, csvText ) - lowerClassName = csvParser.getRoot().className.lower() - pluginModule = archive.getModuleWithDirectoryPath( getPluginsDirectoryPath(), lowerClassName ) - if pluginModule is None: - return None - return pluginModule.getCarvingFromParser( csvParser ) - -def getLineDictionary(line): - """Get the line dictionary.""" - lineDictionary = {} - splitLine = line.split('\t') - for splitLineIndex in xrange( len(splitLine) ): - word = splitLine[ splitLineIndex ] - if word != '': - lineDictionary[ splitLineIndex ] = word - return lineDictionary - -def getPluginsDirectoryPath(): - """Get the plugins directory path.""" - return archive.getAbsoluteFrozenFolderPath( __file__, 'xml_plugins') - - -class CSVElement( xml_simple_reader.XMLElement ): - """A csv element.""" - def continueParsingObject( self, line, lineStripped ): - """Parse replaced line.""" - splitLineStripped = lineStripped.split('\t') - key = splitLineStripped[0] - value = splitLineStripped[1] - self.attributeDictionary[key] = value - self.addToIdentifierDictionaryIFIdentifierExists() - - def continueParsingTable( self, line, lineStripped ): - """Parse replaced line.""" - if self.headingDictionary is None: - self.headingDictionary = getLineDictionary(line) - return - csvElement = self - oldAttributeDictionaryLength = len( self.attributeDictionary ) - if oldAttributeDictionaryLength > 0: - csvElement = CSVElement() - csvElement.parent = self.parent - csvElement.className = self.className - lineDictionary = getLineDictionary(line) - for columnIndex in lineDictionary.keys(): - if columnIndex in self.headingDictionary: - key = self.headingDictionary[ columnIndex ] - value = lineDictionary[ columnIndex ] - csvElement.attributeDictionary[key] = value - csvElement.addToIdentifierDictionaryIFIdentifierExists() - if len( csvElement.attributeDictionary ) == 0 or oldAttributeDictionaryLength == 0 or self.parent is None: - return - self.parent.children.append( csvElement ) - - def getElementFromObject( self, leadingTabCount, lineStripped, oldElement ): - """Parse replaced line.""" - splitLine = lineStripped.split('\t') - self.className = splitLine[1] - if leadingTabCount == 0: - return self - self.parent = oldElement - while leadingTabCount <= self.parent.getNumberOfParents(): - self.parent = self.parent.parent - self.parent.children.append(self) - return self - - def getElementFromTable( self, leadingTabCount, lineStripped, oldElement ): - """Parse replaced line.""" - self.headingDictionary = None - return self.getElementFromObject( leadingTabCount, lineStripped, oldElement ) - - def getNumberOfParents(self): - """Get the number of parents.""" - if self.parent is None: - return 0 - return self.parent.getNumberOfParents() + 1 - - -class CSVSimpleParser( xml_simple_reader.XMLSimpleReader ): - """A simple csv parser.""" - def __init__( self, parent, csvText ): - """Add empty lists.""" - self.continueFunction = None - self.extraLeadingTabCount = None - self.lines = archive.getTextLines( csvText ) - self.oldCSVElement = None - self.root = None - for line in self.lines: - self.parseLine(line) - - def getNewCSVElement( self, leadingTabCount, lineStripped ): - """Get a new csv element.""" - if self.root is not None and self.extraLeadingTabCount is None: - self.extraLeadingTabCount = 1 - leadingTabCount - if self.extraLeadingTabCount is not None: - leadingTabCount += self.extraLeadingTabCount - if lineStripped[ : len('_table') ] == '_table' or lineStripped[ : len('_t') ] == '_t': - self.oldCSVElement = CSVElement().getElementFromTable( leadingTabCount, lineStripped, self.oldCSVElement ) - self.continueFunction = self.oldCSVElement.continueParsingTable - return - self.oldCSVElement = CSVElement().getElementFromObject( leadingTabCount, lineStripped, self.oldCSVElement ) - self.continueFunction = self.oldCSVElement.continueParsingObject - - def parseLine(self, line): - """Parse a gcode line and add it to the inset skein.""" - lineStripped = line.lstrip() - if len( lineStripped ) < 1: - return - leadingPart = line[ : line.find( lineStripped ) ] - leadingTabCount = leadingPart.count('\t') - if lineStripped[ : len('_') ] == '_': - self.getNewCSVElement( leadingTabCount, lineStripped ) - if self.root is None: - self.root = self.oldCSVElement - self.root.parser = self - return - if self.continueFunction is not None: - self.continueFunction( line, lineStripped ) - - -def main(): - """Display the inset dialog.""" - if len(sys.argv) > 1: - getCarving(' '.join(sys.argv[1 :])) - -if __name__ == "__main__": - main() diff --git a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/gts.py b/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/gts.py deleted file mode 100644 index 4f05ba6..0000000 --- a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/gts.py +++ /dev/null @@ -1,80 +0,0 @@ -""" -This page is in the table of contents. -The gts.py script is an import translator plugin to get a carving from an gts file. - -An import plugin is a script in the interpret_plugins folder which has the function getCarving. It is meant to be run from the interpret tool. To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name. - -The getCarving function takes the file name of an gts file and returns the carving. - -The GNU Triangulated Surface (.gts) format is described at: -http://gts.sourceforge.net/reference/gts-surfaces.html#GTS-SURFACE-WRITE - -Quoted from http://gts.sourceforge.net/reference/gts-surfaces.html#GTS-SURFACE-WRITE -"All the lines beginning with GTS_COMMENTS (#!) are ignored. The first line contains three unsigned integers separated by spaces. The first integer is the number of vertexes, nv, the second is the number of edges, ne and the third is the number of faces, nf. - -Follows nv lines containing the x, y and z coordinates of the vertexes. Follows ne lines containing the two indices (starting from one) of the vertexes of each edge. Follows nf lines containing the three ordered indices (also starting from one) of the edges of each face. - -The format described above is the least common denominator to all GTS files. Consistent with an object-oriented approach, the GTS file format is extensible. Each of the lines of the file can be extended with user-specific attributes accessible through the read() and write() virtual methods of each of the objects written (surface, vertexes, edges or faces). When read with different object classes, these extra attributes are just ignored." - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_tools import face -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getFromGNUTriangulatedSurfaceText( gnuTriangulatedSurfaceText, triangleMesh ): - """Initialize from a GNU Triangulated Surface Text.""" - if gnuTriangulatedSurfaceText == '': - return None - lines = archive.getTextLines( gnuTriangulatedSurfaceText ) - linesWithoutComments = [] - for line in lines: - if len(line) > 0: - firstCharacter = line[0] - if firstCharacter != '#' and firstCharacter != '!': - linesWithoutComments.append(line) - splitLine = linesWithoutComments[0].split() - numberOfVertexes = int( splitLine[0] ) - numberOfEdges = int(splitLine[1]) - numberOfFaces = int( splitLine[2] ) - faceTriples = [] - for vertexIndex in xrange( numberOfVertexes ): - line = linesWithoutComments[ vertexIndex + 1 ] - splitLine = line.split() - vertex = Vector3( float( splitLine[0] ), float(splitLine[1]), float( splitLine[2] ) ) - triangleMesh.vertexes.append(vertex) - edgeStart = numberOfVertexes + 1 - for edgeIndex in xrange( numberOfEdges ): - line = linesWithoutComments[ edgeIndex + edgeStart ] - splitLine = line.split() - vertexIndexes = [] - for word in splitLine[ : 2 ]: - vertexIndexes.append( int(word) - 1 ) - edge = face.Edge().getFromVertexIndexes( edgeIndex, vertexIndexes ) - triangleMesh.edges.append( edge ) - faceStart = edgeStart + numberOfEdges - for faceIndex in xrange( numberOfFaces ): - line = linesWithoutComments[ faceIndex + faceStart ] - splitLine = line.split() - edgeIndexes = [] - for word in splitLine[ : 3 ]: - edgeIndexes.append( int(word) - 1 ) - triangleMesh.faces.append( face.Face().getFromEdgeIndexes( edgeIndexes, triangleMesh.edges, faceIndex ) ) - return triangleMesh - -def getCarving(fileName): - """Get the carving for the gts file.""" - return getFromGNUTriangulatedSurfaceText( archive.getFileText(fileName), triangle_mesh.TriangleMesh() ) diff --git a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/obj.py b/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/obj.py deleted file mode 100644 index b73d6ef..0000000 --- a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/obj.py +++ /dev/null @@ -1,78 +0,0 @@ -""" -This page is in the table of contents. -The obj.py script is an import translator plugin to get a carving from an obj file. - -An example obj file is box.obj in the models folder. - -An import plugin is a script in the interpret_plugins folder which has the function getCarving. It is meant to be run from the interpret tool. To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name. - -The getCarving function takes the file name of an obj file and returns the carving. - -From wikipedia, OBJ (or .OBJ) is a geometry definition file format first developed by Wavefront Technologies for its Advanced Visualizer animation package: -http://en.wikipedia.org/wiki/Obj - -The Object File specification is at: -http://local.wasp.uwa.edu.au/~pbourke/dataformats/obj/ - -An excellent link page about obj files is at: -http://people.sc.fsu.edu/~burkardt/data/obj/obj.html - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_tools import face -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec -from struct import unpack - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addFacesGivenText( objText, triangleMesh ): - """Add faces given obj text.""" - lines = archive.getTextLines( objText ) - for line in lines: - splitLine = line.split() - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'v': - triangleMesh.vertexes.append( getVertexGivenLine(line) ) - elif firstWord == 'f': - triangleMesh.faces.append( getFaceGivenLine( line, triangleMesh ) ) - -def getFaceGivenLine( line, triangleMesh ): - """Add face given line index and lines.""" - faceGivenLine = face.Face() - faceGivenLine.index = len( triangleMesh.faces ) - splitLine = line.split() - for vertexStringIndex in xrange( 1, 4 ): - vertexString = splitLine[ vertexStringIndex ] - vertexStringWithSpaces = vertexString.replace('/', ' ') - vertexStringSplit = vertexStringWithSpaces.split() - vertexIndex = int( vertexStringSplit[0] ) - 1 - faceGivenLine.vertexIndexes.append(vertexIndex) - return faceGivenLine - -def getCarving(fileName=''): - """Get the triangle mesh for the obj file.""" - if fileName == '': - return None - objText = archive.getFileText(fileName, True, 'rb') - if objText == '': - return None - triangleMesh = triangle_mesh.TriangleMesh() - addFacesGivenText(objText, triangleMesh) - return triangleMesh - -def getVertexGivenLine(line): - """Get vertex given obj vertex line.""" - splitLine = line.split() - return Vector3( float(splitLine[1]), float( splitLine[2] ), float( splitLine[3] ) ) diff --git a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/slc.py b/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/slc.py deleted file mode 100644 index becca7e..0000000 --- a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/slc.py +++ /dev/null @@ -1,195 +0,0 @@ -""" -This page is in the table of contents. -The slc.py script is an import translator plugin to get a carving from an slc file. - -An import plugin is a script in the interpret_plugins folder which has the function getCarving. It is meant to be run from the interpret tool. To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name. - -The getCarving function takes the file name of an slc file and returns the carving. - -An explanation of the SLC format can be found at: -http://rapid.lpt.fi/archives/rp-ml-1999/0713.html - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import svg_writer -from struct import unpack -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCarving(fileName=''): - """Get the triangle mesh for the slc file.""" - carving = SLCCarving() - carving.readFile(fileName) - return carving - -def getLittleEndianFloatGivenFile( file ): - """Get little endian float given a file.""" - return unpack(' 2: - rotatedLoopLayer.loops.append( getPointsFromFile( numPoints, file ) ) - - def readFile( self, fileName ): - """Read SLC and store the layers.""" - self.fileName = fileName - pslcfile = open( fileName, 'rb') - readHeader( pslcfile ) - pslcfile.read( 256 ) #Go past the 256 byte 3D Reserved Section. - self.readTableEntry( pslcfile ) - self.processContourLayers( pslcfile ) - pslcfile.close() - self.cornerMaximum = Vector3(-987654321.0, -987654321.0, self.maximumZ) - self.cornerMinimum = Vector3(987654321.0, 987654321.0, self.minimumZ) - for rotatedLoopLayer in self.rotatedLoopLayers: - for loop in rotatedLoopLayer.loops: - for point in loop: - pointVector3 = Vector3(point.real, point.imag, rotatedLoopLayer.z) - self.cornerMaximum.maximize(pointVector3) - self.cornerMinimum.minimize(pointVector3) - halfLayerThickness = 0.5 * self.layerThickness - self.cornerMaximum.z += halfLayerThickness - self.cornerMinimum.z -= halfLayerThickness - - def readTableEntry( self, file ): - """Read in the sampling table section. It contains a table length (byte) and the table entries.""" - tableEntrySize = ord( file.read( 1 ) ) - if tableEntrySize == 0: - print( "Sampling table size is zero!" ) - exit() - for index in xrange( tableEntrySize ): - sampleTableEntry = SampleTableEntry( file ) - self.layerThickness = sampleTableEntry.layer_thickness - - def setCarveInfillInDirectionOfBridge( self, infillInDirectionOfBridge ): - """Set the infill in direction of bridge.""" - pass - - def setCarveLayerThickness( self, layerThickness ): - """Set the layer thickness.""" - pass - - def setCarveImportRadius( self, importRadius ): - """Set the import radius.""" - pass - - def setCarveIsCorrectMesh( self, isCorrectMesh ): - """Set the is correct mesh flag.""" - pass - - -def main(): - """Display the inset dialog.""" - if len(sys.argv) > 1: - getCarving(' '.join(sys.argv[1 :])) - -if __name__ == "__main__": - main() diff --git a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/stl.py b/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/stl.py deleted file mode 100644 index 08e141e..0000000 --- a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/stl.py +++ /dev/null @@ -1,111 +0,0 @@ -""" -This page is in the table of contents. -The stl.py script is an import translator plugin to get a carving from an stl file. - -An import plugin is a script in the interpret_plugins folder which has the function getCarving. It is meant to be run from the interpret tool. To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name. - -The getCarving function takes the file name of an stl file and returns the carving. - -STL is an inferior triangle surface format, described at: -http://en.wikipedia.org/wiki/STL_(file_format) - -A good triangle surface format is the GNU Triangulated Surface format which is described at: -http://gts.sourceforge.net/reference/gts-surfaces.html#GTS-SURFACE-WRITE - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_tools import face -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec -from struct import unpack - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addFacesGivenBinary( stlData, triangleMesh, vertexIndexTable ): - """Add faces given stl binary.""" - numberOfVertexes = ( len( stlData ) - 84 ) / 50 - vertexes = [] - for vertexIndex in xrange( numberOfVertexes ): - byteIndex = 84 + vertexIndex * 50 - vertexes.append( getVertexGivenBinary( byteIndex + 12, stlData ) ) - vertexes.append( getVertexGivenBinary( byteIndex + 24, stlData ) ) - vertexes.append( getVertexGivenBinary( byteIndex + 36, stlData ) ) - addFacesGivenVertexes( triangleMesh, vertexIndexTable, vertexes ) - -def addFacesGivenText( stlText, triangleMesh, vertexIndexTable ): - """Add faces given stl text.""" - lines = archive.getTextLines( stlText ) - vertexes = [] - for line in lines: - if line.find('vertex') != - 1: - vertexes.append( getVertexGivenLine(line) ) - addFacesGivenVertexes( triangleMesh, vertexIndexTable, vertexes ) - -def addFacesGivenVertexes( triangleMesh, vertexIndexTable, vertexes ): - """Add faces given stl text.""" - for vertexIndex in xrange( 0, len(vertexes), 3 ): - triangleMesh.faces.append( getFaceGivenLines( triangleMesh, vertexIndex, vertexIndexTable, vertexes ) ) - -def getCarving(fileName=''): - """Get the triangle mesh for the stl file.""" - if fileName == '': - return None - stlData = archive.getFileText(fileName, True, 'rb') - if stlData == '': - return None - triangleMesh = triangle_mesh.TriangleMesh() - vertexIndexTable = {} - numberOfVertexStrings = stlData.count('vertex') - requiredVertexStringsForText = max( 2, len( stlData ) / 8000 ) - if numberOfVertexStrings > requiredVertexStringsForText: - addFacesGivenText( stlData, triangleMesh, vertexIndexTable ) - else: -# A binary stl should never start with the word "solid". Because this error is common the file is been parsed as binary regardless. - addFacesGivenBinary( stlData, triangleMesh, vertexIndexTable ) - return triangleMesh - -def getFaceGivenLines( triangleMesh, vertexStartIndex, vertexIndexTable, vertexes ): - """Add face given line index and lines.""" - faceGivenLines = face.Face() - faceGivenLines.index = len( triangleMesh.faces ) - for vertexIndex in xrange( vertexStartIndex, vertexStartIndex + 3 ): - vertex = vertexes[vertexIndex] - vertexUniqueIndex = len( vertexIndexTable ) - if str(vertex) in vertexIndexTable: - vertexUniqueIndex = vertexIndexTable[ str(vertex) ] - else: - vertexIndexTable[ str(vertex) ] = vertexUniqueIndex - triangleMesh.vertexes.append(vertex) - faceGivenLines.vertexIndexes.append( vertexUniqueIndex ) - return faceGivenLines - -def getFloat(floatString): - """Get the float, replacing commas if necessary because an inferior program is using a comma instead of a point for the decimal point.""" - try: - return float(floatString) - except: - return float( floatString.replace(',', '.') ) - -def getFloatGivenBinary( byteIndex, stlData ): - """Get vertex given stl vertex line.""" - return unpack('f', stlData[ byteIndex : byteIndex + 4 ] )[0] - -def getVertexGivenBinary( byteIndex, stlData ): - """Get vertex given stl vertex line.""" - return Vector3( getFloatGivenBinary( byteIndex, stlData ), getFloatGivenBinary( byteIndex + 4, stlData ), getFloatGivenBinary( byteIndex + 8, stlData ) ) - -def getVertexGivenLine(line): - """Get vertex given stl vertex line.""" - splitLine = line.split() - return Vector3( getFloat(splitLine[1]), getFloat( splitLine[2] ), getFloat( splitLine[3] ) ) diff --git a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/svg.py b/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/svg.py deleted file mode 100644 index b889475..0000000 --- a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/svg.py +++ /dev/null @@ -1,113 +0,0 @@ -""" -This page is in the table of contents. -The svg.py script is an import translator plugin to get a carving from an svg file. This script will read an svg file made by skeinforge or by inkscape. - -An example inkscape svg file is inkscape_star.svg in the models folder. - -An import plugin is a script in the interpret_plugins folder which has the function getCarving. It is meant to be run from the interpret tool. To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name. - -The getCarving function takes the file name of an svg file and returns the carving. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.svg_reader import SVGReader -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import svg_writer -from fabmetheus_utilities import xml_simple_writer -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCarving(fileName=''): - """Get the triangle mesh for the gts file.""" - carving = SVGCarving() - carving.parseSVG(fileName, archive.getFileText(fileName)) - return carving - - -class SVGCarving: - """An svg carving.""" - def __init__(self): - """Add empty lists.""" - self.layerThickness = 1.0 - self.maximumZ = - 987654321.0 - self.minimumZ = 987654321.0 - self.svgReader = SVGReader() - - def __repr__(self): - """Get the string representation of this carving.""" - return self.getCarvedSVG() - - def addXML(self, depth, output): - """Add xml for this object.""" - xml_simple_writer.addXMLFromObjects(depth, self.svgReader.rotatedLoopLayers, output) - - def getCarveCornerMaximum(self): - """Get the corner maximum of the vertexes.""" - return self.cornerMaximum - - def getCarveCornerMinimum(self): - """Get the corner minimum of the vertexes.""" - return self.cornerMinimum - - def getCarvedSVG(self): - """Get the carved svg text.""" - return svg_writer.getSVGByLoopLayers(True, self, self.svgReader.rotatedLoopLayers) - - def getCarveLayerThickness(self): - """Get the layer thickness.""" - return self.layerThickness - - def getCarveRotatedBoundaryLayers(self): - """Get the rotated boundary layers.""" - return self.svgReader.rotatedLoopLayers - - def getFabmetheusXML(self): - """Return the fabmetheus XML.""" - return None - - def getInterpretationSuffix(self): - """Return the suffix for a carving.""" - return 'svg' - - def parseSVG(self, fileName, svgText): - """Parse SVG text and store the layers.""" - if svgText == '': - return - self.fileName = fileName - self.svgReader.parseSVG(fileName, svgText) - self.layerThickness = euclidean.getFloatDefaultByDictionary( - self.layerThickness, self.svgReader.sliceDictionary, 'layerThickness') - self.cornerMaximum = Vector3(-987654321.0, -987654321.0, self.maximumZ) - self.cornerMinimum = Vector3(987654321.0, 987654321.0, self.minimumZ) - svg_writer.setSVGCarvingCorners( - self.cornerMaximum, self.cornerMinimum, self.layerThickness, self.svgReader.rotatedLoopLayers) - - def setCarveInfillInDirectionOfBridge(self, infillInDirectionOfBridge): - """Set the infill in direction of bridge.""" - pass - - def setCarveLayerThickness(self, layerThickness): - """Set the layer thickness.""" - self.layerThickness = layerThickness - - def setCarveImportRadius(self, importRadius): - """Set the import radius.""" - pass - - def setCarveIsCorrectMesh(self, isCorrectMesh): - """Set the is correct mesh flag.""" - pass diff --git a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/xml.py b/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/xml.py deleted file mode 100644 index b82d892..0000000 --- a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/xml.py +++ /dev/null @@ -1,128 +0,0 @@ -""" -This page is in the table of contents. -The xml.py script is an import translator plugin to get a carving from an xml file. - -An import plugin is a script in the interpret_plugins folder which has the function getCarving. It is meant to be run from the interpret tool. To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name. - -The getCarving function takes the file name of an xml file and returns the carving. - -An example of an xml boolean geometry format file follows below. - - - - - - - - - - - - - -In the 'fabmetheus' format, all class names are lower case. The defined geometric objects are cube, cylinder, difference, group, sphere, trianglemesh and union. The id attribute is not necessary. The default matrix is a four by four identity matrix. The attributes of the cube, cylinder and sphere default to one. The attributes of the vertexes in the triangle mesh default to zero. The boolean solids are difference, intersection and union. The difference solid is the first solid minus the remaining solids. The combined_shape.xml example in the xml_models folder in the models folder is pasted below. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The 'fabmetheus' xml format is the preferred skeinforge format. When the Interpret button in the Interpret tool in Analyze is clicked, any xml format for which there is a plugin will be converted to the 'fabmetheus' format. - -There is a plugin for the 'Art of Illusion' xml format. An xml file can be exported from Art of Illusion by going to the "File" menu, then going into the "Export" menu item, then picking the XML choice. This will bring up the XML file chooser window, choose a place to save the file then click "OK". Leave the "compressFile" checkbox unchecked. All the objects from the scene will be exported, the artofillusion plugin will ignore the light and camera. If you want to fabricate more than one object at a time, you can have multiple objects in the Art of Illusion scene and they will all be carved, then fabricated together. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.xml_simple_reader import XMLSimpleReader -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec -import os -import sys - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCarving(fileName=''): - """Get the carving for the xml file.""" - xmlText = archive.getFileText(fileName) - if xmlText == '': - return None - xmlParser = XMLSimpleReader( fileName, None, xmlText ) - lowerClassName = xmlParser.getRoot().className.lower() - pluginModule = archive.getModuleWithDirectoryPath( getPluginsDirectoryPath(), lowerClassName ) - if pluginModule is None: - return None - return pluginModule.getCarvingFromParser( xmlParser ) - -def getPluginsDirectoryPath(): - """Get the plugins directory path.""" - return archive.getAbsoluteFrozenFolderPath( __file__, 'xml_plugins') - -def main(): - """Display the inset dialog.""" - if len(sys.argv) > 1: - getCarving(' '.join(sys.argv[1 :])) - -if __name__ == "__main__": - main() diff --git a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/xml_plugins/__init__.py b/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/xml_plugins/__init__.py deleted file mode 100644 index 58ec332..0000000 --- a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/xml_plugins/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 4 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/xml_plugins/artofillusion.py b/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/xml_plugins/artofillusion.py deleted file mode 100644 index a71575d..0000000 --- a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/xml_plugins/artofillusion.py +++ /dev/null @@ -1,191 +0,0 @@ -""" -This page is in the table of contents. -The xml.py script is an import translator plugin to get a carving from an Art of Illusion xml file. - -An import plugin is a script in the interpret_plugins folder which has the function getCarving. It is meant to be run from the interpret tool. To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name. - -The getCarving function takes the file name of an xml file and returns the carving. - -An xml file can be exported from Art of Illusion by going to the "File" menu, then going into the "Export" menu item, then picking the XML choice. This will bring up the XML file chooser window, choose a place to save the file then click "OK". Leave the "compressFile" checkbox unchecked. All the objects from the scene will be exported, this plugin will ignore the light and camera. If you want to fabricate more than one object at a time, you can have multiple objects in the Art of Illusion scene and they will all be carved, then fabricated together. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_tools import face -from fabmetheus_utilities.geometry.geometry_utilities import boolean_geometry -from fabmetheus_utilities.geometry.geometry_utilities import boolean_solid -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.geometry.solids import cube -from fabmetheus_utilities.geometry.solids import cylinder -from fabmetheus_utilities.geometry.solids import group -from fabmetheus_utilities.geometry.solids import sphere -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCarvingFromParser( xmlParser ): - """Get the carving for the parser.""" - booleanGeometry = boolean_geometry.BooleanGeometry() - artOfIllusionElement = xmlParser.getRoot() - artOfIllusionElement.xmlObject = booleanGeometry - euclidean.removeElementsFromDictionary( artOfIllusionElement.attributeDictionary, ['fileversion', 'xmlns:bf'] ) - sceneElement = artOfIllusionElement.getFirstChildWithClassName('Scene') - xmlElements = sceneElement.getFirstChildWithClassName('objects').getChildrenWithClassName('bf:Elem') - for xmlElement in xmlElements: - processXMLElement( booleanGeometry.archivableObjects, artOfIllusionElement, xmlElement ) - return booleanGeometry - -def getCarvableObject(globalObject, object, xmlElement): - """Get new carvable object info.""" - object.xmlObject = globalObject() - object.xmlObject.xmlElement = object - object.attributeDictionary['id'] = xmlElement.getFirstChildWithClassName('name').text - coords = xmlElement.getFirstChildWithClassName('coords') - transformXMLElement = getTransformXMLElement(coords, 'transformFrom') - if len(transformXMLElement.attributeDictionary) < 16: - transformXMLElement = getTransformXMLElement(coords, 'transformTo') - matrix.setXMLElementDictionaryMatrix(object.xmlObject.matrix4X4.getFromXMLElement('', transformXMLElement), object) - return object.xmlObject - -def getTransformXMLElement( coords, transformName ): - """Get the transform attributes.""" - transformXMLElement = coords.getFirstChildWithClassName( transformName ) - if len( transformXMLElement.attributeDictionary ) < 16: - if 'bf:ref' in transformXMLElement.attributeDictionary: - idReference = transformXMLElement.attributeDictionary['bf:ref'] - return coords.getRoot().getSubChildWithID( idReference ) - return transformXMLElement - -def processXMLElement( archivableObjects, parent, xmlElement ): - """Add the object info if it is carvable.""" - if xmlElement is None: - return - object = xmlElement.getFirstChildWithClassName('object') - if 'bf:type' not in object.attributeDictionary: - return - shapeType = object.attributeDictionary['bf:type'] - if shapeType not in globalCarvableClassObjectTable: - return - carvableClassObject = globalCarvableClassObjectTable[ shapeType ] - archivableObject = getCarvableObject( carvableClassObject, object, xmlElement ) - archivableObject.xmlElement.attributeDictionary['visible'] = xmlElement.attributeDictionary['visible'] - archivableObject.setToArtOfIllusionDictionary() - archivableObject.xmlElement.parent = parent - archivableObjects.append(archivableObject) - -def removeListArtOfIllusionFromDictionary( dictionary, scrubKeys ): - """Remove the list and art of illusion keys from the dictionary.""" - euclidean.removeElementsFromDictionary( dictionary, ['bf:id', 'bf:type'] ) - euclidean.removeElementsFromDictionary( dictionary, scrubKeys ) - - -class BooleanSolid( boolean_solid.BooleanSolid ): - """An Art of Illusion CSG object info.""" - def setToArtOfIllusionDictionary(self): - """Set the shape of this carvable object info.""" - processXMLElement( self.archivableObjects, self.xmlElement, self.xmlElement.getFirstChildWithClassName('obj1') ) - processXMLElement( self.archivableObjects, self.xmlElement, self.xmlElement.getFirstChildWithClassName('obj2') ) - operationString = self.xmlElement.attributeDictionary['operation'] - self.operationFunction = { '0': self.getUnion, '1': self.getIntersection, '2': self.getDifference, '3': self.getDifference }[ operationString ] - if operationString == '3': - self.archivableObjects.reverse() - removeListArtOfIllusionFromDictionary( self.xmlElement.attributeDictionary, ['operation'] ) - - -class Cube( cube.Cube ): - """An Art of Illusion Cube object.""" - def setToArtOfIllusionDictionary(self): - """Set the shape of this carvable object info.""" - self.inradius = Vector3( - float( self.xmlElement.attributeDictionary['halfx'] ), - float( self.xmlElement.attributeDictionary['halfy'] ), - float( self.xmlElement.attributeDictionary['halfz'] ) ) - self.xmlElement.attributeDictionary['inradius.x'] = self.xmlElement.attributeDictionary['halfx'] - self.xmlElement.attributeDictionary['inradius.y'] = self.xmlElement.attributeDictionary['halfy'] - self.xmlElement.attributeDictionary['inradius.z'] = self.xmlElement.attributeDictionary['halfz'] - removeListArtOfIllusionFromDictionary( self.xmlElement.attributeDictionary, ['halfx', 'halfy', 'halfz'] ) - self.createShape() - - -class Cylinder(cylinder.Cylinder): - """An Art of Illusion Cylinder object.""" - def setToArtOfIllusionDictionary(self): - """Set the shape of this carvable object info.""" - self.inradius = Vector3() - self.inradius.x = float(self.xmlElement.attributeDictionary['rx']) - self.inradius.y = float(self.xmlElement.attributeDictionary['rz']) - self.inradius.z = float(self.xmlElement.attributeDictionary['height']) - self.topOverBottom = float(self.xmlElement.attributeDictionary['ratio']) - self.xmlElement.attributeDictionary['radius.x'] = self.xmlElement.attributeDictionary['rx'] - self.xmlElement.attributeDictionary['radius.y'] = self.xmlElement.attributeDictionary['rz'] - self.xmlElement.attributeDictionary['topOverBottom'] = self.xmlElement.attributeDictionary['ratio'] - xmlObject = self.xmlElement.xmlObject - xmlObject.matrix4X4 = xmlObject.matrix4X4.getOtherTimesSelf(matrix.getDiagonalSwitchedTetragrid(90.0, [0, 2])) - removeListArtOfIllusionFromDictionary(self.xmlElement.attributeDictionary, ['rx', 'rz', 'ratio']) - self.createShape() - - -class Group( group.Group ): - """An Art of Illusion Group object.""" - def setToArtOfIllusionDictionary(self): - """Set the shape of this group.""" - childrenElement = self.xmlElement.parent.getFirstChildWithClassName('children') - children = childrenElement.getChildrenWithClassName('bf:Elem') - for child in children: - processXMLElement( self.archivableObjects, self.xmlElement, child ) - removeListArtOfIllusionFromDictionary( self.xmlElement.attributeDictionary, [] ) - - -class Sphere( sphere.Sphere ): - """An Art of Illusion Sphere object.""" - def setToArtOfIllusionDictionary(self): - """Set the shape of this carvable object.""" - self.radius = Vector3( - float( self.xmlElement.attributeDictionary['rx'] ), - float( self.xmlElement.attributeDictionary['ry'] ), - float( self.xmlElement.attributeDictionary['rz'] ) ) - self.xmlElement.attributeDictionary['radius.x'] = self.xmlElement.attributeDictionary['rx'] - self.xmlElement.attributeDictionary['radius.y'] = self.xmlElement.attributeDictionary['ry'] - self.xmlElement.attributeDictionary['radius.z'] = self.xmlElement.attributeDictionary['rz'] - removeListArtOfIllusionFromDictionary( self.xmlElement.attributeDictionary, ['rx', 'ry', 'rz'] ) - self.createShape() - - -class TriangleMesh(triangle_mesh.TriangleMesh): - """An Art of Illusion triangle mesh object.""" - def setToArtOfIllusionDictionary(self): - """Set the shape of this carvable object info.""" - vertexElement = self.xmlElement.getFirstChildWithClassName('vertex') - vertexPointElements = vertexElement.getChildrenWithClassName('bf:Elem') - for vertexPointElement in vertexPointElements: - coordinateElement = vertexPointElement.getFirstChildWithClassName('r') - vertex = Vector3( float( coordinateElement.attributeDictionary['x'] ), float( coordinateElement.attributeDictionary['y'] ), float( coordinateElement.attributeDictionary['z'] ) ) - self.vertexes.append(vertex) - edgeElement = self.xmlElement.getFirstChildWithClassName('edge') - edgeSubelements = edgeElement.getChildrenWithClassName('bf:Elem') - for edgeSubelementIndex in xrange( len( edgeSubelements ) ): - edgeSubelement = edgeSubelements[ edgeSubelementIndex ] - vertexIndexes = [ int( edgeSubelement.attributeDictionary['v1'] ), int( edgeSubelement.attributeDictionary['v2'] ) ] - edge = face.Edge().getFromVertexIndexes( edgeSubelementIndex, vertexIndexes ) - self.edges.append( edge ) - faceElement = self.xmlElement.getFirstChildWithClassName('face') - faceSubelements = faceElement.getChildrenWithClassName('bf:Elem') - for faceSubelementIndex in xrange( len( faceSubelements ) ): - faceSubelement = faceSubelements[ faceSubelementIndex ] - edgeIndexes = [ int( faceSubelement.attributeDictionary['e1'] ), int( faceSubelement.attributeDictionary['e2'] ), int( faceSubelement.attributeDictionary['e3'] ) ] - self.faces.append( face.Face().getFromEdgeIndexes( edgeIndexes, self.edges, faceSubelementIndex ) ) - removeListArtOfIllusionFromDictionary( self.xmlElement.attributeDictionary, ['closed', 'smoothingMethod'] ) - - -globalCarvableClassObjectTable = { 'CSGObject' : BooleanSolid, 'Cube' : Cube, 'Cylinder' : Cylinder, 'artofillusion.object.NullObject' : Group, 'Sphere' : Sphere, 'TriangleMesh' : TriangleMesh } diff --git a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/xml_plugins/fabmetheus.py b/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/xml_plugins/fabmetheus.py deleted file mode 100644 index 1918a58..0000000 --- a/skeinforge/fabmetheus_utilities/fabmetheus_tools/interpret_plugins/xml_plugins/fabmetheus.py +++ /dev/null @@ -1,109 +0,0 @@ -""" -This page is in the table of contents. -The xml.py script is an import translator plugin to get a carving from an Art of Illusion xml file. - -An import plugin is a script in the interpret_plugins folder which has the function getCarving. It is meant to be run from the interpret tool. To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name. - -The getCarving function takes the file name of an xml file and returns the carving. - -An xml file can be exported from Art of Illusion by going to the "File" menu, then going into the "Export" menu item, then picking the XML choice. This will bring up the XML file chooser window, choose a place to save the file then click "OK". Leave the "compressFile" checkbox unchecked. All the objects from the scene will be exported, this plugin will ignore the light and camera. If you want to fabricate more than one object at a time, you can have multiple objects in the Art of Illusion scene and they will all be carved, then fabricated together. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import boolean_geometry -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from fabmetheus_utilities import xml_simple_reader -import os -import sys -import traceback - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCarvingFromParser(xmlParser): - """Get the carving for the parser.""" - booleanGeometryElement = xmlParser.getRoot() - booleanGeometryElement.xmlObject = boolean_geometry.BooleanGeometry() - booleanGeometryElement.xmlProcessor = XMLBooleanGeometryProcessor() - booleanGeometryElement.xmlProcessor.processChildren(booleanGeometryElement) - return booleanGeometryElement.xmlObject - - -class XMLBooleanGeometryProcessor(): - """A class to process xml boolean geometry elements.""" - def __init__(self): - """Initialize processor.""" - self.functions = [] - self.manipulationMatrixDictionary = archive.getGeometryDictionary('manipulation_matrix') - self.manipulationPathDictionary = archive.getGeometryDictionary('manipulation_paths') - self.manipulationShapeDictionary = archive.getGeometryDictionary('manipulation_shapes') - self.namePathDictionary = {} - self.namePathDictionary.update(evaluate.globalCreationDictionary) - self.namePathDictionary.update(archive.getGeometryDictionary('manipulation_meta')) - self.namePathDictionary.update(self.manipulationMatrixDictionary) - self.namePathDictionary.update(self.manipulationPathDictionary) - self.namePathDictionary.update(self.manipulationShapeDictionary) - archive.addToNamePathDictionary(archive.getGeometryToolsPath(), self.namePathDictionary) - archive.addToNamePathDictionary(archive.getGeometryToolsPath('path_elements'), self.namePathDictionary) - archive.addToNamePathDictionary(archive.getGeometryPath('solids'), self.namePathDictionary) - archive.addToNamePathDictionary(archive.getGeometryPath('statements'), self.namePathDictionary) - - def __repr__(self): - """Get the string representation of this XMLBooleanGeometryProcessor.""" - return 'XMLBooleanGeometryProcessor with %s functions.' % len(self.functions) - - def convertXMLElement( self, geometryOutput, xmlElement ): - """Convert the xml element.""" - geometryOutputKeys = geometryOutput.keys() - if len( geometryOutputKeys ) < 1: - return None - firstKey = geometryOutputKeys[0] - lowerClassName = firstKey.lower() - if lowerClassName not in self.namePathDictionary: - return None - pluginModule = archive.getModuleWithPath( self.namePathDictionary[ lowerClassName ] ) - if pluginModule is None: - return None - xmlElement.className = lowerClassName - return pluginModule.convertXMLElement(geometryOutput[ firstKey ], xmlElement) - - def createChildren( self, geometryOutput, parent ): - """Create children for the parent.""" - for geometryOutputChild in geometryOutput: - child = xml_simple_reader.XMLElement() - child.setParentAddToChildren( parent ) - self.convertXMLElement(geometryOutputChild, child) - - def processChildren(self, xmlElement): - """Process the children of the xml element.""" - for child in xmlElement.children: - self.processXMLElement(child) - - def processXMLElement(self, xmlElement): - """Process the xml element.""" - lowerClassName = xmlElement.className.lower() - if lowerClassName not in self.namePathDictionary: - return None - pluginModule = archive.getModuleWithPath(self.namePathDictionary[lowerClassName]) - if pluginModule is None: - return None - try: - return pluginModule.processXMLElement(xmlElement) - except: - print('Warning, could not processXMLElement in fabmetheus for:') - print(pluginModule) - print(xmlElement) - traceback.print_exc(file=sys.stdout) - return None diff --git a/skeinforge/fabmetheus_utilities/fabmetheus_tools/prepare.py b/skeinforge/fabmetheus_utilities/fabmetheus_tools/prepare.py deleted file mode 100644 index f28807b..0000000 --- a/skeinforge/fabmetheus_utilities/fabmetheus_tools/prepare.py +++ /dev/null @@ -1,87 +0,0 @@ -""" -Prepare is a script to remove the generated files, run wikifier, and finally zip the package. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import archive -from fabmetheus_utilities.fabmetheus_tools import wikifier -import os - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def prepareWikify(): - """Remove generated files, then wikify the file comments.""" - removeGeneratedFiles() - wikifier.main() - removeZip() - -def removeCSVFile(csvFilePath): - """Remove csv file.""" - if 'alterations' in csvFilePath and 'example_' not in csvFilePath: - os.remove(csvFilePath) - print('removeGeneratedFiles deleted ' + csvFilePath) - -def removeGcodeFile(gcodeFilePath): - """Remove gcode file.""" - if 'alterations' not in gcodeFilePath: - os.remove(gcodeFilePath) - print('removeGeneratedFiles deleted ' + gcodeFilePath) - return - if 'example_' not in gcodeFilePath: - os.remove(gcodeFilePath) - print('removeGeneratedFiles deleted ' + gcodeFilePath) - -def removeGeneratedFiles(): - """Remove generated files.""" - csvFilePaths = archive.getFilesWithFileTypesWithoutWordsRecursively(['csv']) - for csvFilePath in csvFilePaths: - removeCSVFile(csvFilePath) - gcodeFilePaths = archive.getFilesWithFileTypesWithoutWordsRecursively(['gcode']) - for gcodeFilePath in gcodeFilePaths: - removeGcodeFile(gcodeFilePath) - svgFilePaths = archive.getFilesWithFileTypesWithoutWordsRecursively(['svg']) - for svgFilePath in svgFilePaths: - removeSVGFile(svgFilePath) - xmlFilePaths = archive.getFilesWithFileTypesWithoutWordsRecursively(['xml']) - for xmlFilePath in xmlFilePaths: - removeXMLFile(xmlFilePath) - archive.removeBackupFilesByTypes(['gcode', 'svg', 'xml']) - -def removeSVGFile(svgFilePath): - """Remove svg file.""" - if archive.getEndsWithList(svgFilePath, ['_bottom.svg', '_carve.svg', '_chop.svg', '_cleave.svg', '_scale.svg', '_vectorwrite.svg']): - os.remove(svgFilePath) - print('removeGeneratedFiles deleted ' + svgFilePath) - -def removeXMLFile(xmlFilePath): - """Remove xml file.""" - if archive.getEndsWithList(xmlFilePath, ['_interpret.xml']): - os.remove(xmlFilePath) - print('removeGeneratedFiles deleted ' + xmlFilePath) - -def removeZip(): - """Remove the zip file, then generate a new one.zip -r reprap_python_beanshell * -x \*.pyc \*~""" - zipName = 'reprap_python_beanshell' - zipNameExtension = zipName + '.zip' - if zipNameExtension in os.listdir(os.getcwd()): - os.remove(zipNameExtension) - shellCommand = 'zip -r %s * -x \*.pyc \*~' % zipName - commandResult = os.system(shellCommand) - if commandResult != 0: - print('Failed to execute the following command in removeZip in prepare.') - print(shellCommand) - -def main(): - """Run main function.""" - prepareWikify() - -if __name__ == "__main__": - main() diff --git a/skeinforge/fabmetheus_utilities/fabmetheus_tools/wikifier.py b/skeinforge/fabmetheus_utilities/fabmetheus_tools/wikifier.py deleted file mode 100644 index 58470a6..0000000 --- a/skeinforge/fabmetheus_utilities/fabmetheus_tools/wikifier.py +++ /dev/null @@ -1,199 +0,0 @@ -""" -Wikifier is a script to add spaces to the pydoc files and move them to the documentation folder. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -import cStringIO -import os - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -class Heading: - """A class to hold the heading and subheadings.""" - def __init__(self, depth=0): - """Initialize.""" - self.depth = depth - - def addToOutput(self, output): - """Add to the output.""" - line = '  ' * self.depth + '%s
\n' % (self.name, self.name) - output.write(line) - - def getFromLine(self, headingLineTable, line): - """Get the heading from a line.""" - heading = 'h%s' % (self.depth + 2) - nextLine = '\n
\n' - if self.depth > 0: - nextLine = '\n' - self.name = line.replace('=', '').replace('
', '') - name = self.name - headingLine = '<%s>%s%s' % (name, name, heading, name, heading, nextLine) - headingLineTable[line] = headingLine - return self - - -def addToHeadings(headingLineTable, headings, line): - """Add the line to the headings.""" - for depth in xrange(4, -1, -1): - equalSymbolLength = depth + 2 - if line[: equalSymbolLength] == '=' * equalSymbolLength: - headings.append(Heading(depth).getFromLine(headingLineTable, line)) - return - -def getNavigationHypertext(fileText, transferredFileNameIndex, transferredFileNames): - """Get the hypertext help with navigation lines.""" - helpTextEnd = fileText.find('

') - helpTextStart = fileText.find('

') - helpText = fileText[helpTextStart : helpTextEnd] - lines = archive.getTextLines(helpText) - headings = [] - headingLineTable = {} - for line in lines: - addToHeadings(headingLineTable, headings, line) - headingsToBeenAdded = True - output = cStringIO.StringIO() - for line in lines: - if line[: 2] == '==': - if headingsToBeenAdded: - output.write('
\n') - for heading in headings: - heading.addToOutput(output) - output.write('
\n') - headingsToBeenAdded = False - if line in headingLineTable: - line = headingLineTable[line] - if line.find('<a href=') > -1: - line = line.replace('<', '<').replace('>', '>') - output.write(line + '\n') - helpText = output.getvalue() - previousFileName = 'contents.html' - previousIndex = transferredFileNameIndex - 1 - if previousIndex >= 0: - previousFileName = transferredFileNames[previousIndex] - previousLinkText = 'Previous' % previousFileName - nextLinkText = getNextLinkText(transferredFileNames, transferredFileNameIndex + 1) - navigationLine = getNavigationLine('Contents', previousLinkText, nextLinkText) - helpText = navigationLine + helpText + '
\n
\n' + navigationLine + '


\n' - return fileText[: helpTextStart] + helpText + fileText[helpTextEnd :] - -def getNavigationLine(contentsLinkText, previousLinkText, nextLinkText): - """Get the wrapped pydoc hypertext help.""" - return '

\n%s / %s / %s\n

\n' % (previousLinkText, nextLinkText, contentsLinkText) - -def getNextLinkText(hypertextFiles, nextIndex): - """Get the next link text.""" - nextFileName = 'contents.html' - if nextIndex < len(hypertextFiles): - nextFileName = hypertextFiles[nextIndex] - return 'Next' % nextFileName - -def getWrappedHypertext(fileText, hypertextFileIndex, hypertextFiles): - """Get the wrapped pydoc hypertext help.""" - helpTextEnd = fileText.find('

') - if helpTextEnd < 0: - print('Failed to find the helpTextEnd in getWrappedHypertext in docwrap.') - helpTextStart = fileText.find('

') - if helpTextStart < 0: - print('Failed to find the helpTextStart in getWrappedHypertext in docwrap.') - helpText = fileText[helpTextStart : helpTextEnd] - helpText = helpText.replace(' ', ' ') - return fileText[: helpTextStart] + helpText + fileText[helpTextEnd :] - -def readWriteDeleteHypertextHelp(documentDirectoryPath, hypertextFileIndex, hypertextFiles, transferredFileNames): - """Read the pydoc hypertext help documents, write them in the documentation folder then delete the originals.""" - fileName = os.path.basename(hypertextFiles[hypertextFileIndex]) - print('readWriteDeleteHypertextHelp ' + fileName) - filePath = os.path.join(documentDirectoryPath, fileName) - fileText = archive.getFileText(fileName) - fileText = getWrappedHypertext(fileText, hypertextFileIndex, hypertextFiles) - if fileText.find('This page is in the table of contents.') > - 1: - fileText = fileText.replace('This page is in the table of contents.', '') - transferredFileNames.append(fileName) - archive.writeFileText(filePath, fileText) - os.remove(fileName) - -def readWriteNavigationHelp(documentDirectoryPath, transferredFileNameIndex, transferredFileNames): - """Read the hypertext help documents, and add the navigation lines to them.""" - fileName = os.path.basename(transferredFileNames[transferredFileNameIndex]) - print('readWriteNavigationHelp ' + fileName) - filePath = os.path.join(documentDirectoryPath, fileName) - fileText = archive.getFileText(filePath) - fileText = getNavigationHypertext(fileText, transferredFileNameIndex, transferredFileNames) - archive.writeFileText(filePath, fileText) - -def removeFilesInDirectory(directoryPath): - """Remove all the files in a directory.""" - fileNames = os.listdir(directoryPath) - for fileName in fileNames: - filePath = os.path.join(directoryPath, fileName) - os.remove(filePath) - -def writeContentsFile(documentDirectoryPath, hypertextFiles): - """Write the contents file.""" - output = cStringIO.StringIO() - output.write('\n \n Contents\n \n \n') - navigationLine = getNavigationLine('Contents', 'Previous', getNextLinkText(hypertextFiles, 0)) - output.write(navigationLine) - for hypertextFile in hypertextFiles: - writeContentsLine(hypertextFile, output) - output.write(navigationLine) - output.write(' \n\n') - filePath = os.path.join( documentDirectoryPath, 'contents.html') - archive.writeFileText(filePath, output.getvalue()) - -def writeContentsLine(hypertextFile, output): - """Write a line of the contents file.""" - summarizedFileName = hypertextFile[: hypertextFile.rfind('.')] - numberOfDots = summarizedFileName.count('.') - prefixSpaces = '  ' * numberOfDots - if numberOfDots > 0: - summarizedFileName = summarizedFileName[summarizedFileName.rfind('.') + 1 :] - capitalizedSummarizedFileName = settings.getEachWordCapitalized(summarizedFileName) - output.write('%s%s
\n' % (prefixSpaces, hypertextFile, capitalizedSummarizedFileName)) - -def writeHypertext(): - """Run pydoc, then read, write and delete each of the files.""" - shellCommand = 'pydoc -w ./' - commandResult = os.system(shellCommand) - if commandResult != 0: - print('Failed to execute the following command in writeHypertext in docwrap.') - print(shellCommand) - hypertextFiles = archive.getFilesWithFileTypeWithoutWords('html') - if len( hypertextFiles ) <= 0: - print('Failed to find any help files in writeHypertext in docwrap.') - return - documentDirectoryPath = archive.getAbsoluteFolderPath( hypertextFiles[0], 'documentation') - removeFilesInDirectory(documentDirectoryPath) - sortedReplaceFiles = [] - for hypertextFile in hypertextFiles: - sortedReplaceFiles.append(hypertextFile.replace('.html', '. html')) - sortedReplaceFiles.sort() - hypertextFiles = [] - for sortedReplaceFile in sortedReplaceFiles: - hypertextFiles.append(sortedReplaceFile.replace('. html', '.html')) - transferredFileNames = [] - for hypertextFileIndex in xrange(len(hypertextFiles)): - readWriteDeleteHypertextHelp(documentDirectoryPath, hypertextFileIndex, hypertextFiles, transferredFileNames) - for transferredFileNameIndex in xrange(len(transferredFileNames)): - readWriteNavigationHelp(documentDirectoryPath, transferredFileNameIndex, transferredFileNames) - writeContentsFile(documentDirectoryPath, transferredFileNames) - print('%s files were wrapped.' % len(transferredFileNames)) - - -def main(): - """Display the craft dialog.""" - writeHypertext() - -if __name__ == '__main__': - main() diff --git a/skeinforge/fabmetheus_utilities/fonts/gentium_basic_regular.svg b/skeinforge/fabmetheus_utilities/fonts/gentium_basic_regular.svg deleted file mode 100644 index 418f023..0000000 --- a/skeinforge/fabmetheus_utilities/fonts/gentium_basic_regular.svg +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/skeinforge/fabmetheus_utilities/gcodec.py b/skeinforge/fabmetheus_utilities/gcodec.py deleted file mode 100644 index 1eef589..0000000 --- a/skeinforge/fabmetheus_utilities/gcodec.py +++ /dev/null @@ -1,394 +0,0 @@ -""" -Gcodec is a collection of utilities to decode and encode gcode. - -To run gcodec, install python 2.x on your machine, which is avaliable from http://www.python.org/download/ - -Then in the folder which gcodec is in, type 'python' in a shell to run the python interpreter. Finally type 'from gcodec import *' to import this program. - -Below is an example of gcodec use. This example is run in a terminal in the folder which contains gcodec and Screw Holder Bottom_export.gcode. - ->>> from gcodec import * ->>> getFileText('Screw Holder Bottom_export.gcode') -'G90\nG21\nM103\nM105\nM106\nM110 S60.0\nM111 S30.0\nM108 S210.0\nM104 S235.0\nG1 X0.37 Y-4.07 Z1.9 F60.0\nM101\n -.. -many lines of text -.. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -import cStringIO -import math -import os -import sys -import traceback - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addLineAndNewlineIfNecessary(line, output): - """Add the line and if the line does not end with a newline add a newline.""" - output.write(line) - if len(line) < 1: - return - if not line.endswith('\n'): - output.write('\n') - -def addLinesToCString(cString, lines): - """Add lines which have something to cStringIO.""" - for line in lines: - if line != '': - cString.write(line + '\n') - -def getArcDistance(relativeLocation, splitLine): - """Get arc distance.""" - halfPlaneLineDistance = 0.5 * abs(relativeLocation.dropAxis()) - radius = getDoubleFromCharacterSplitLine('R', splitLine) - if radius is None: - iFloat = getDoubleFromCharacterSplitLine('I', splitLine) - jFloat = getDoubleFromCharacterSplitLine('J', splitLine) - radius = abs(complex(iFloat, jFloat)) - angle = 0.0 - if radius > 0.0: - halfPlaneLineDistanceOverRadius = halfPlaneLineDistance / radius - if halfPlaneLineDistance < radius: - angle = 2.0 * math.asin(halfPlaneLineDistanceOverRadius) - else: - angle = math.pi * halfPlaneLineDistanceOverRadius - return abs(complex(angle * radius, relativeLocation.z)) - -def getDoubleAfterFirstLetter(word): - """Get the double value of the word after the first letter.""" - return float(word[1 :]) - -def getDoubleForLetter(letter, splitLine): - """Get the double value of the word after the first occurence of the letter in the split line.""" - return getDoubleAfterFirstLetter(splitLine[getIndexOfStartingWithSecond(letter, splitLine)]) - -def getDoubleFromCharacterSplitLine(character, splitLine): - """Get the double value of the string after the first occurence of the character in the split line.""" - indexOfCharacter = getIndexOfStartingWithSecond(character, splitLine) - if indexOfCharacter < 0: - return None - floatString = splitLine[indexOfCharacter][1 :] - try: - return float(floatString) - except ValueError: - return None - -def getDoubleFromCharacterSplitLineValue(character, splitLine, value): - """Get the double value of the string after the first occurence of the character in the split line, if it does not exist return the value.""" - splitLineFloat = getDoubleFromCharacterSplitLine(character, splitLine) - if splitLineFloat is None: - return value - return splitLineFloat - -def getFeedRateMinute(feedRateMinute, splitLine): - """Get the feed rate per minute if the split line has a feed rate.""" - indexOfF = getIndexOfStartingWithSecond('F', splitLine) - if indexOfF > 0: - return getDoubleAfterFirstLetter( splitLine[indexOfF] ) - return feedRateMinute - -def getFirstWord(splitLine): - """Get the first word of a split line.""" - if len(splitLine) > 0: - return splitLine[0] - return '' - -def getFirstWordFromLine(line): - """Get the first word of a line.""" - return getFirstWord(line.split()) - -def getGcodeFileText(fileName, gcodeText): - """Get the gcode text from a file if it the gcode text is empty and if the file is a gcode file.""" - if gcodeText != '': - return gcodeText - if fileName.endswith('.gcode'): - return archive.getFileText(fileName) - return '' - -def getIndexOfStartingWithSecond(letter, splitLine): - """Get index of the first occurence of the given letter in the split line, starting with the second word. Return - 1 if letter is not found""" - for wordIndex in xrange( 1, len(splitLine) ): - word = splitLine[ wordIndex ] - firstLetter = word[0] - if firstLetter == letter: - return wordIndex - return - 1 - -def getLineWithValueString(character, line, splitLine, valueString): - """Get the line with a valueString.""" - roundedValueString = character + valueString - indexOfValue = getIndexOfStartingWithSecond(character, splitLine) - if indexOfValue == - 1: - return line + ' ' + roundedValueString - word = splitLine[indexOfValue] - return line.replace(word, roundedValueString) - -def getLocationFromSplitLine(oldLocation, splitLine): - """Get the location from the split line.""" - if oldLocation is None: - oldLocation = Vector3() - return Vector3( - getDoubleFromCharacterSplitLineValue('X', splitLine, oldLocation.x), - getDoubleFromCharacterSplitLineValue('Y', splitLine, oldLocation.y), - getDoubleFromCharacterSplitLineValue('Z', splitLine, oldLocation.z)) - -def getSplitLineBeforeBracketSemicolon(line): - """Get the split line before a bracket or semicolon.""" - line = line.split(';')[0] - bracketIndex = line.find('(') - if bracketIndex > 0: - return line[: bracketIndex].split() - return line.split() - -def getStringFromCharacterSplitLine(character, splitLine): - """Get the string after the first occurence of the character in the split line.""" - indexOfCharacter = getIndexOfStartingWithSecond(character, splitLine) - if indexOfCharacter < 0: - return None - return splitLine[indexOfCharacter][1 :] - -def getWithoutBracketsEqualTab(line): - """Get a string without the greater than sign, the bracket and less than sign, the equal sign or the tab.""" - line = line.replace('=', ' ') - line = line.replace('(<', '') - line = line.replace('>', '') - return line.replace('\t', '') - -def isProcedureDone(gcodeText, procedure): - """Determine if the procedure has been done on the gcode text.""" - if gcodeText == '': - return False - lines = archive.getTextLines(gcodeText) - for line in lines: - withoutBracketsEqualTabQuotes = getWithoutBracketsEqualTab(line).replace('"', '').replace("'", '') - splitLine = getWithoutBracketsEqualTab( withoutBracketsEqualTabQuotes ).split() - firstWord = getFirstWord(splitLine) - if firstWord == 'procedureName': - if splitLine[1].find(procedure) != -1: - return True - elif firstWord == 'extrusionStart': - return False - procedureIndex = line.find(procedure) - if procedureIndex != -1: - if 'procedureName' in splitLine: - nextIndex = splitLine.index('procedureName') + 1 - if nextIndex < len(splitLine): - nextWordSplit = splitLine[nextIndex].split(',') - if procedure in nextWordSplit: - return True - return False - -def isProcedureDoneOrFileIsEmpty(gcodeText, procedure): - """Determine if the procedure has been done on the gcode text or the file is empty.""" - if gcodeText == '': - return True - return isProcedureDone(gcodeText, procedure) - -def getFirstWordIndexReverse(firstWord, lines, startIndex): - """Parse gcode in reverse order until the first word if there is one, otherwise return -1.""" - for lineIndex in xrange(len(lines) - 1, startIndex - 1, -1): - if firstWord == getFirstWord(getSplitLineBeforeBracketSemicolon(lines[lineIndex])): - return lineIndex - return -1 - -def isThereAFirstWord(firstWord, lines, startIndex): - """Parse gcode until the first word if there is one.""" - for lineIndex in xrange(startIndex, len(lines)): - line = lines[lineIndex] - splitLine = getSplitLineBeforeBracketSemicolon(line) - if firstWord == getFirstWord(splitLine): - return True - return False - - -class BoundingRectangle: - """A class to get the corners of a gcode text.""" - def getFromGcodeLines(self, lines, radius): - """Parse gcode text and get the minimum and maximum corners.""" - self.cornerMaximum = complex(-987654321.0, -987654321.0) - self.cornerMinimum = complex(987654321.0, 987654321.0) - self.oldLocation = None - self.cornerRadius = complex(radius, radius) - for line in lines: - self.parseCorner(line) - return self - - def isPointInside(self, point): - """Determine if the point is inside the bounding rectangle.""" - return point.imag >= self.cornerMinimum.imag and point.imag <= self.cornerMaximum.imag and point.real >= self.cornerMinimum.real and point.real <= self.cornerMaximum.real - - def parseCorner(self, line): - """Parse a gcode line and use the location to update the bounding corners.""" - splitLine = getSplitLineBeforeBracketSemicolon(line) - firstWord = getFirstWord(splitLine) - if firstWord == '(': - locationComplex = getLocationFromSplitLine(None, splitLine).dropAxis() - self.cornerMaximum = euclidean.getMaximum(self.cornerMaximum, locationComplex) - self.cornerMinimum = euclidean.getMinimum(self.cornerMinimum, locationComplex) - elif firstWord == 'G1': - location = getLocationFromSplitLine(self.oldLocation, splitLine) - locationComplex = location.dropAxis() - self.cornerMaximum = euclidean.getMaximum(self.cornerMaximum, locationComplex + self.cornerRadius) - self.cornerMinimum = euclidean.getMinimum(self.cornerMinimum, locationComplex - self.cornerRadius) - self.oldLocation = location - - -class DistanceFeedRate: - """A class to limit the z feed rate and round values.""" - def __init__(self): - """Initialize.""" - self.decimalPlacesCarried = 3 - self.output = cStringIO.StringIO() - - def addGcodeFromFeedRateThreadZ(self, feedRateMinute, thread, travelFeedRateMinute, z): - """Add a thread to the output.""" - if len(thread) > 0: - self.addGcodeMovementZWithFeedRate(travelFeedRateMinute, thread[0], z) - else: - print('zero length vertex positions array which was skipped over, this should never happen.') - if len(thread) < 2: - print('thread of only one point in addGcodeFromFeedRateThreadZ in gcodec, this should never happen.') - print(thread) - return - self.addLine('M101') # Turn extruder on. - for point in thread[1 :]: - self.addGcodeMovementZWithFeedRate(feedRateMinute, point, z) - self.addLine('M103') # Turn extruder off. - - def addGcodeFromLoop(self, loop, z): - """Add the gcode loop.""" - euclidean.addSurroundingLoopBeginning(self, loop, z) - self.addPerimeterBlock(loop, z) - self.addLine('()') - self.addLine('()') - - def addGcodeFromThreadZ(self, thread, z): - """Add a thread to the output.""" - if len(thread) > 0: - self.addGcodeMovementZ(thread[0], z) - else: - print('zero length vertex positions array which was skipped over, this should never happen.') - if len(thread) < 2: - print('thread of only one point in addGcodeFromThreadZ in gcodec, this should never happen.') - print(thread) - return - self.addLine('M101') # Turn extruder on. - for point in thread[1 :]: - self.addGcodeMovementZ(point, z) - self.addLine('M103') # Turn extruder off. - - def addGcodeMovementZ(self, point, z): - """Add a movement to the output.""" - self.addLine(self.getLinearGcodeMovement(point, z)) - - def addGcodeMovementZWithFeedRate(self, feedRateMinute, point, z): - """Add a movement to the output.""" - self.addLine(self.getLinearGcodeMovementWithFeedRate(feedRateMinute, point, z)) - - def addLine(self, line): - """Add a line of text and a newline to the output.""" - if len(line) > 0: - self.output.write(line + '\n') - - def addLines(self, lines): - """Add lines of text to the output.""" - addLinesToCString(self.output, lines) - - def addLinesSetAbsoluteDistanceMode(self, lines): - """Add lines of text to the output and ensure the absolute mode is set.""" - if len(lines) < 1: - return - if len(lines[0]) < 1: - return - absoluteDistanceMode = True - self.addLine('()') - for line in lines: - splitLine = getSplitLineBeforeBracketSemicolon(line) - firstWord = getFirstWord(splitLine) - if firstWord == 'G90': - absoluteDistanceMode = True - elif firstWord == 'G91': - absoluteDistanceMode = False - self.addLine(line) - if not absoluteDistanceMode: - self.addLine('G90') - self.addLine('()') - - def addParameter(self, firstWord, parameter): - """Add the parameter.""" - self.addLine(firstWord + ' S' + euclidean.getRoundedToThreePlaces(parameter)) - - def addPerimeterBlock(self, loop, z): - """Add the perimeter gcode block for the loop.""" - if len(loop) < 2: - return - if euclidean.isWiddershins(loop): # Indicate that a perimeter is beginning. - self.addLine('( outer )') - else: - self.addLine('( inner )') - self.addGcodeFromThreadZ(loop + [loop[0]], z) - self.addLine('()') # Indicate that a perimeter is beginning. - - def addTagBracketedLine(self, tagName, value): - """Add a begin tag, value and end tag.""" - self.addLine('(<%s> %s )' % (tagName, value, tagName)) - - def addTagRoundedLine(self, tagName, value): - """Add a begin tag, rounded value and end tag.""" - self.addLine('(<%s> %s )' % (tagName, self.getRounded(value), tagName)) - - def getBoundaryLine(self, location): - """Get boundary gcode line.""" - return '( X%s Y%s Z%s )' % (self.getRounded(location.x), self.getRounded(location.y), self.getRounded(location.z)) - - def getFirstWordMovement(self, firstWord, location): - """Get the start of the arc line.""" - return '%s X%s Y%s Z%s' % (firstWord, self.getRounded(location.x), self.getRounded(location.y), self.getRounded(location.z)) - - def getLinearGcodeMovement(self, point, z): - """Get a linear gcode movement.""" - return 'G1 X%s Y%s Z%s' % ( self.getRounded( point.real ), self.getRounded( point.imag ), self.getRounded(z) ) - - def getLinearGcodeMovementWithFeedRate(self, feedRateMinute, point, z): - """Get a z limited gcode movement.""" - linearGcodeMovement = self.getLinearGcodeMovement(point, z) - if feedRateMinute is None: - return linearGcodeMovement - return linearGcodeMovement + ' F' + self.getRounded(feedRateMinute) - - def getLineWithFeedRate(self, feedRateMinute, line, splitLine): - """Get the line with a feed rate.""" - return getLineWithValueString('F', line, splitLine, self.getRounded(feedRateMinute)) - - def getLineWithX(self, line, splitLine, x): - """Get the line with an x.""" - return getLineWithValueString('X', line, splitLine, self.getRounded(x)) - - def getLineWithY(self, line, splitLine, y): - """Get the line with a y.""" - return getLineWithValueString('Y', line, splitLine, self.getRounded(y)) - - def getLineWithZ(self, line, splitLine, z): - """Get the line with a z.""" - return getLineWithValueString('Z', line, splitLine, self.getRounded(z)) - - def getRounded(self, number): - """Get number rounded to the number of carried decimal places as a string.""" - return euclidean.getRoundedToPlacesString(self.decimalPlacesCarried, number) - - def parseSplitLine(self, firstWord, splitLine): - """Parse gcode split line and store the parameters.""" - if firstWord == '(': - self.decimalPlacesCarried = int(splitLine[1]) diff --git a/skeinforge/fabmetheus_utilities/geometry/__init__.py b/skeinforge/fabmetheus_utilities/geometry/__init__.py deleted file mode 100644 index 3345e96..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -This page is in the table of contents. -This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -""" -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 2 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/__init__.py b/skeinforge/fabmetheus_utilities/geometry/creation/__init__.py deleted file mode 100644 index cefa3e7..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -This page is in the table of contents. -This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -""" -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/_drill.py b/skeinforge/fabmetheus_utilities/geometry/creation/_drill.py deleted file mode 100644 index 26b07df..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/_drill.py +++ /dev/null @@ -1,63 +0,0 @@ -""" -Drill negative solid. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import extrude -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.creation import teardrop -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getGeometryOutput(derivation, xmlElement): - """Get vector3 vertexes from attribute dictionary.""" - if derivation is None: - derivation = DrillDerivation(xmlElement) - negatives = [] - teardrop.addNegativesByRadius(derivation.end, negatives, derivation.radius, derivation.start, xmlElement) - return solid.getGeometryOutputByManipulation(negatives[0], xmlElement) - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get vector3 vertexes from attribute dictionary by arguments.""" - evaluate.setAttributeDictionaryByArguments(['radius', 'start', 'end'], arguments, xmlElement) - return getGeometryOutput(None, xmlElement) - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return DrillDerivation(xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - solid.processXMLElementByGeometry(getGeometryOutput(None, xmlElement), xmlElement) - - -class DrillDerivation: - """Class to hold drill variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.end = evaluate.getVector3ByPrefix(Vector3(0.0, 0.0, 1.0), 'end', xmlElement) - self.start = evaluate.getVector3ByPrefix(Vector3(), 'start', xmlElement) - self.radius = lineation.getFloatByPrefixBeginEnd('radius', 'diameter', 1.0, xmlElement) - size = evaluate.getEvaluatedFloat(None, 'size', xmlElement) - if size is not None: - self.radius = 0.5 * size - self.xmlElement = xmlElement - - def __repr__(self): - """Get the string representation of this DrillDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/_svg.py b/skeinforge/fabmetheus_utilities/geometry/creation/_svg.py deleted file mode 100644 index d416c6f..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/_svg.py +++ /dev/null @@ -1,64 +0,0 @@ -""" -Svg reader. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_tools import path -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import svg_reader - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getGeometryOutput(derivation, xmlElement): - """Get vector3 vertexes from attribute dictionary.""" - if derivation is None: - derivation = SVGDerivation(xmlElement) - return getGeometryOutputBySVGReader(derivation.svgReader, xmlElement) - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get vector3 vertexes from attribute dictionary by arguments.""" - derivation = SVGDerivation() - derivation.svgReader.parseSVG('', arguments[0]) - return getGeometryOutput(derivation, xmlElement) - -def getGeometryOutputBySVGReader(svgReader, xmlElement): - """Get vector3 vertexes from svgReader.""" - geometryOutput = [] - for rotatedLoopLayer in svgReader.rotatedLoopLayers: - for loop in rotatedLoopLayer.loops: - vector3Path = euclidean.getVector3Path(loop, rotatedLoopLayer.z) - sideLoop = lineation.SideLoop(vector3Path, None, None) - sideLoop.rotate(xmlElement) - geometryOutput += lineation.getGeometryOutputByManipulation(sideLoop, xmlElement) - return geometryOutput - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return SVGDerivation(xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - path.convertXMLElement(getGeometryOutput(None, xmlElement), xmlElement) - - -class SVGDerivation: - """Class to hold svg variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.svgReader = svg_reader.SVGReader() - self.svgReader.parseSVGByXMLElement(xmlElement) - - def __repr__(self): - """Get the string representation of this SVGDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/circle.py b/skeinforge/fabmetheus_utilities/geometry/creation/circle.py deleted file mode 100644 index bd11c94..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/circle.py +++ /dev/null @@ -1,83 +0,0 @@ -""" -Polygon path. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_tools import path -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getGeometryOutput(derivation, xmlElement): - """Get vector3 vertexes from attribute dictionary.""" - if derivation is None: - derivation = CircleDerivation(xmlElement) - angleTotal = math.radians(derivation.start) - loop = [] - sidesCeiling = int(math.ceil(abs(derivation.sides) * derivation.extent / 360.0)) - sideAngle = math.radians(derivation.extent) / sidesCeiling - if derivation.sides < 0.0: - sideAngle = -sideAngle - spiral = lineation.Spiral(derivation.spiral, 0.5 * sideAngle / math.pi) - for side in xrange(sidesCeiling + 1): - unitPolar = euclidean.getWiddershinsUnitPolar(angleTotal) - x = unitPolar.real * derivation.circularizedRadius.real - y = unitPolar.imag * derivation.circularizedRadius.imag - vertex = spiral.getSpiralPoint(unitPolar, Vector3(x, y)) - angleTotal += sideAngle - loop.append(vertex) - radiusMaximum = 0.000001 * max(derivation.circularizedRadius.real, derivation.circularizedRadius.imag) - loop = euclidean.getLoopWithoutCloseEnds(radiusMaximum, loop) - sideLength = sideAngle * lineation.getRadiusAverage(derivation.circularizedRadius) - lineation.setClosedAttribute(derivation.revolutions, xmlElement) - return lineation.getGeometryOutputByLoop(lineation.SideLoop(loop, sideAngle, sideLength), xmlElement) - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get vector3 vertexes from attribute dictionary by arguments.""" - evaluate.setAttributeDictionaryByArguments(['radius', 'start', 'end', 'revolutions'], arguments, xmlElement) - return getGeometryOutput(None, xmlElement) - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return CircleDerivation(xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - path.convertXMLElement(getGeometryOutput(None, xmlElement), xmlElement) - - -class CircleDerivation: - """Class to hold circle variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.radius = lineation.getRadiusComplex(complex(1.0, 1.0), xmlElement) - self.sides = evaluate.getEvaluatedFloat(None, 'sides', xmlElement) - if self.sides is None: - radiusMaximum = max(self.radius.real, self.radius.imag) - self.sides = evaluate.getSidesMinimumThreeBasedOnPrecisionSides(radiusMaximum, xmlElement) - self.circularizedRadius = self.radius - if evaluate.getEvaluatedBoolean(False, 'areaRadius', xmlElement): - self.circularizedRadius *= euclidean.getAreaRadiusMultiplier(self.sides) - self.start = evaluate.getEvaluatedFloat(0.0, 'start', xmlElement) - end = evaluate.getEvaluatedFloat(360.0, 'end', xmlElement) - self.revolutions = evaluate.getEvaluatedFloat(1.0, 'revolutions', xmlElement) - self.extent = evaluate.getEvaluatedFloat(end - self.start, 'extent', xmlElement) - self.extent += 360.0 * (self.revolutions - 1.0) - self.spiral = evaluate.getVector3ByPrefix(None, 'spiral', xmlElement) - - def __repr__(self): - """Get the string representation of this CircleDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/concatenate.py b/skeinforge/fabmetheus_utilities/geometry/creation/concatenate.py deleted file mode 100644 index 4ef880a..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/concatenate.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -Boolean geometry concatenation. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_tools import path -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getGeometryOutput(derivation, xmlElement): - """Get triangle mesh from attribute dictionary.""" - if derivation is None: - derivation = ConcatenateDerivation(xmlElement) - concatenatedList = euclidean.getConcatenatedList(derivation.target)[:] - if len(concatenatedList) == 0: - print('Warning, in concatenate there are no paths.') - print(xmlElement.attributeDictionary) - return None - if 'closed' not in xmlElement.attributeDictionary: - xmlElement.attributeDictionary['closed'] = 'true' - return lineation.getGeometryOutputByLoop(lineation.SideLoop(concatenatedList, None, None), xmlElement) - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get triangle mesh from attribute dictionary by arguments.""" - return getGeometryOutput(None, xmlElement) - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return ConcatenateDerivation(xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - path.convertXMLElement(getGeometryOutput(None, xmlElement), xmlElement) - - -class ConcatenateDerivation: - """Class to hold concatenate variables.""" - def __init__(self, xmlElement): - """Initialize.""" - self.target = evaluate.getTransformedPathsByKey([], 'target', xmlElement) - - def __repr__(self): - """Get the string representation of this ConcatenateDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/extrude.py b/skeinforge/fabmetheus_utilities/geometry/creation/extrude.py deleted file mode 100644 index e8ab87e..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/extrude.py +++ /dev/null @@ -1,445 +0,0 @@ -""" -Boolean geometry extrusion. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.geometry_utilities.evaluate_elements import setting -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities.vector3index import Vector3Index -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addLoop(derivation, endMultiplier, loopLists, path, portionDirectionIndex, portionDirections, vertexes): - """Add an indexed loop to the vertexes.""" - portionDirection = portionDirections[ portionDirectionIndex ] - if portionDirection.directionReversed == True: - loopLists.append([]) - loops = loopLists[-1] - interpolationOffset = derivation.interpolationDictionary['offset'] - offset = interpolationOffset.getVector3ByPortion( portionDirection ) - if endMultiplier is not None: - if portionDirectionIndex == 0: - setOffsetByMultiplier( interpolationOffset.path[1], interpolationOffset.path[0], endMultiplier, offset ) - elif portionDirectionIndex == len( portionDirections ) - 1: - setOffsetByMultiplier( interpolationOffset.path[-2], interpolationOffset.path[-1], endMultiplier, offset ) - scale = derivation.interpolationDictionary['scale'].getComplexByPortion( portionDirection ) - twist = derivation.interpolationDictionary['twist'].getYByPortion( portionDirection ) - projectiveSpace = euclidean.ProjectiveSpace() - if derivation.tiltTop is None: - tilt = derivation.interpolationDictionary['tilt'].getComplexByPortion( portionDirection ) - projectiveSpace = projectiveSpace.getByTilt( tilt ) - else: - normals = getNormals( interpolationOffset, offset, portionDirection ) - normalFirst = normals[0] - normalAverage = getNormalAverage(normals) - if derivation.tiltFollow and derivation.oldProjectiveSpace is not None: - projectiveSpace = derivation.oldProjectiveSpace.getNextSpace( normalAverage ) - else: - projectiveSpace = projectiveSpace.getByBasisZTop( normalAverage, derivation.tiltTop ) - derivation.oldProjectiveSpace = projectiveSpace - projectiveSpace.unbuckle( derivation.maximumUnbuckling, normalFirst ) - projectiveSpace = projectiveSpace.getSpaceByXYScaleAngle( twist, scale ) - loop = [] - if ( abs( projectiveSpace.basisX ) + abs( projectiveSpace.basisY ) ) < 0.0001: - vector3Index = Vector3Index(len(vertexes)) - addOffsetAddToLists( loop, offset, vector3Index, vertexes ) - loops.append(loop) - return - for point in path: - vector3Index = Vector3Index(len(vertexes)) - projectedVertex = projectiveSpace.getVector3ByPoint(point) - vector3Index.setToVector3( projectedVertex ) - addOffsetAddToLists( loop, offset, vector3Index, vertexes ) - loops.append(loop) - -def addNegatives(derivation, negatives, paths): - """Add pillars output to negatives.""" - portionDirections = getSpacedPortionDirections(derivation.interpolationDictionary) - for path in paths: - loopLists = getLoopListsByPath(derivation, 1.000001, path, portionDirections) - geometryOutput = triangle_mesh.getPillarsOutput(loopLists) - negatives.append(geometryOutput) - -def addNegativesPositives(derivation, negatives, paths, positives): - """Add pillars output to negatives and positives.""" - portionDirections = getSpacedPortionDirections(derivation.interpolationDictionary) - for path in paths: - endMultiplier = None - if not euclidean.getIsWiddershinsByVector3(path): - endMultiplier = 1.000001 - loopLists = getLoopListsByPath(derivation, endMultiplier, path, portionDirections) - geometryOutput = triangle_mesh.getPillarsOutput(loopLists) - if endMultiplier is None: - positives.append(geometryOutput) - else: - negatives.append(geometryOutput) - -def addOffsetAddToLists(loop, offset, vector3Index, vertexes): - """Add an indexed loop to the vertexes.""" - vector3Index += offset - loop.append(vector3Index) - vertexes.append(vector3Index) - -def addPositives(derivation, paths, positives): - """Add pillars output to positives.""" - portionDirections = getSpacedPortionDirections(derivation.interpolationDictionary) - for path in paths: - loopLists = getLoopListsByPath(derivation, None, path, portionDirections) - geometryOutput = triangle_mesh.getPillarsOutput(loopLists) - positives.append(geometryOutput) - -def addSpacedPortionDirection( portionDirection, spacedPortionDirections ): - """Add spaced portion directions.""" - lastSpacedPortionDirection = spacedPortionDirections[-1] - if portionDirection.portion - lastSpacedPortionDirection.portion > 0.003: - spacedPortionDirections.append( portionDirection ) - return - if portionDirection.directionReversed > lastSpacedPortionDirection.directionReversed: - spacedPortionDirections.append( portionDirection ) - -def addTwistPortions( interpolationTwist, remainderPortionDirection, twistPrecision ): - """Add twist portions.""" - lastPortionDirection = interpolationTwist.portionDirections[-1] - if remainderPortionDirection.portion == lastPortionDirection.portion: - return - lastTwist = interpolationTwist.getYByPortion( lastPortionDirection ) - remainderTwist = interpolationTwist.getYByPortion( remainderPortionDirection ) - twistSegments = int( math.floor( abs( remainderTwist - lastTwist ) / twistPrecision ) ) - if twistSegments < 1: - return - portionDifference = remainderPortionDirection.portion - lastPortionDirection.portion - twistSegmentsPlusOne = float( twistSegments + 1 ) - for twistSegment in xrange( twistSegments ): - additionalPortion = portionDifference * float( twistSegment + 1 ) / twistSegmentsPlusOne - portionDirection = PortionDirection( lastPortionDirection.portion + additionalPortion ) - interpolationTwist.portionDirections.append( portionDirection ) - -def comparePortionDirection( portionDirection, otherPortionDirection ): - """Comparison in order to sort portion directions in ascending order of portion then direction.""" - if portionDirection.portion > otherPortionDirection.portion: - return 1 - if portionDirection.portion < otherPortionDirection.portion: - return - 1 - if portionDirection.directionReversed < otherPortionDirection.directionReversed: - return - 1 - return portionDirection.directionReversed > otherPortionDirection.directionReversed - -def getGeometryOutput(derivation, xmlElement): - """Get triangle mesh from attribute dictionary.""" - if derivation is None: - derivation = ExtrudeDerivation(xmlElement) - if len(euclidean.getConcatenatedList(derivation.target)) == 0: - print('Warning, in extrude there are no paths.') - print(xmlElement.attributeDictionary) - return None - return getGeometryOutputByLoops(derivation, derivation.target) - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get triangle mesh from attribute dictionary by arguments.""" - return getGeometryOutput(None, xmlElement) - -def getGeometryOutputByLoops(derivation, loops): - """Get geometry output by sorted, nested loops.""" - loops.sort(key=euclidean.getAreaVector3LoopAbsolute, reverse=True) - complexLoops = euclidean.getComplexPaths(loops) - nestedRings = [] - for loopIndex, loop in enumerate(loops): - complexLoop = complexLoops[loopIndex] - leftPoint = euclidean.getLeftPoint(complexLoop) - isInFilledRegion = euclidean.getIsInFilledRegion(complexLoops[: loopIndex] + complexLoops[loopIndex + 1 :], leftPoint) - if isInFilledRegion == euclidean.isWiddershins(complexLoop): - loop.reverse() - nestedRing = euclidean.NestedRing() - nestedRing.boundary = complexLoop - nestedRing.vector3Loop = loop - nestedRings.append(nestedRing) - nestedRings = euclidean.getOrderedNestedRings(nestedRings) - nestedRings = euclidean.getFlattenedNestedRings(nestedRings) - portionDirections = getSpacedPortionDirections(derivation.interpolationDictionary) - if len(nestedRings) < 1: - return {} - if len(nestedRings) == 1: - geometryOutput = getGeometryOutputByNestedRing(derivation, nestedRings[0], portionDirections) - return solid.getGeometryOutputByManipulation(geometryOutput, derivation.xmlElement) - shapes = [] - for nestedRing in nestedRings: - shapes.append(getGeometryOutputByNestedRing(derivation, nestedRing, portionDirections)) - return solid.getGeometryOutputByManipulation({'union' : {'shapes' : shapes}}, derivation.xmlElement) - -def getGeometryOutputByNegativesPositives(negatives, positives, xmlElement): - """Get triangle mesh from derivation, negatives, positives and xmlElement.""" - positiveOutput = triangle_mesh.getUnifiedOutput(positives) - if len(negatives) < 1: - return solid.getGeometryOutputByManipulation(positiveOutput, xmlElement) - if len(positives) < 1: - negativeOutput = triangle_mesh.getUnifiedOutput(negatives) - return solid.getGeometryOutputByManipulation(negativeOutput, xmlElement) - return solid.getGeometryOutputByManipulation({'difference' : {'shapes' : [positiveOutput] + negatives}}, xmlElement) - -def getGeometryOutputByNestedRing(derivation, nestedRing, portionDirections): - """Get geometry output by sorted, nested loops.""" - loopLists = getLoopListsByPath(derivation, None, nestedRing.vector3Loop, portionDirections) - outsideOutput = triangle_mesh.getPillarsOutput(loopLists) - if len(nestedRing.innerNestedRings) < 1: - return outsideOutput - shapes = [outsideOutput] - for nestedRing.innerNestedRing in nestedRing.innerNestedRings: - loopLists = getLoopListsByPath(derivation, 1.000001, nestedRing.innerNestedRing.vector3Loop, portionDirections) - shapes.append(triangle_mesh.getPillarsOutput(loopLists)) - return {'difference' : {'shapes' : shapes}} - -def getLoopListsByPath(derivation, endMultiplier, path, portionDirections): - """Get loop lists from path.""" - vertexes = [] - loopLists = [[]] - derivation.oldProjectiveSpace = None - for portionDirectionIndex in xrange(len(portionDirections)): - addLoop(derivation, endMultiplier, loopLists, path, portionDirectionIndex, portionDirections, vertexes) - return loopLists - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return ExtrudeDerivation(xmlElement) - -def getNormalAverage(normals): - """Get normal.""" - if len(normals) < 2: - return normals[0] - return (normals[0] + normals[1]).getNormalized() - -def getNormals( interpolationOffset, offset, portionDirection ): - """Get normals.""" - normals = [] - portionFrom = portionDirection.portion - 0.0001 - portionTo = portionDirection.portion + 0.0001 - if portionFrom >= 0.0: - normals.append( ( offset - interpolationOffset.getVector3ByPortion( PortionDirection( portionFrom ) ) ).getNormalized() ) - if portionTo <= 1.0: - normals.append( ( interpolationOffset.getVector3ByPortion( PortionDirection( portionTo ) ) - offset ).getNormalized() ) - return normals - -def getSpacedPortionDirections( interpolationDictionary ): - """Get sorted portion directions.""" - portionDirections = [] - for interpolationDictionaryValue in interpolationDictionary.values(): - portionDirections += interpolationDictionaryValue.portionDirections - portionDirections.sort( comparePortionDirection ) - if len( portionDirections ) < 1: - return [] - spacedPortionDirections = [ portionDirections[0] ] - for portionDirection in portionDirections[1 :]: - addSpacedPortionDirection( portionDirection, spacedPortionDirections ) - return spacedPortionDirections - -def insertTwistPortions(derivation, xmlElement): - """Insert twist portions and radian the twist.""" - interpolationDictionary = derivation.interpolationDictionary - interpolationTwist = Interpolation().getByPrefixX(derivation.twistPathDefault, 'twist', xmlElement) - interpolationDictionary['twist'] = interpolationTwist - for point in interpolationTwist.path: - point.y = math.radians(point.y) - remainderPortionDirections = interpolationTwist.portionDirections[1 :] - interpolationTwist.portionDirections = [interpolationTwist.portionDirections[0]] - if xmlElement is not None: - twistPrecision = setting.getTwistPrecisionRadians(xmlElement) - for remainderPortionDirection in remainderPortionDirections: - addTwistPortions(interpolationTwist, remainderPortionDirection, twistPrecision) - interpolationTwist.portionDirections.append(remainderPortionDirection) - -def processXMLElement(xmlElement): - """Process the xml element.""" - solid.processXMLElementByGeometry(getGeometryOutput(None, xmlElement), xmlElement) - -def setXMLElementToEndStart(end, start, xmlElement): - """Set xmlElement attribute dictionary to a tilt following path from the start to end.""" - xmlElement.attributeDictionary['path'] = [start, end] - xmlElement.attributeDictionary['tiltFollow'] = 'true' - xmlElement.attributeDictionary['tiltTop'] = Vector3(0.0, 0.0, 1.0) - -def setOffsetByMultiplier(begin, end, multiplier, offset): - """Set the offset by the multiplier.""" - segment = end - begin - delta = segment * multiplier - segment - offset.setToVector3(offset + delta) - - -class ExtrudeDerivation: - """Class to hold extrude variables.""" - def __init__(self, xmlElement): - """Initialize.""" - self.interpolationDictionary = {} - self.tiltFollow = evaluate.getEvaluatedBoolean(True, 'tiltFollow', xmlElement) - self.tiltTop = evaluate.getVector3ByPrefix(None, 'tiltTop', xmlElement) - self.maximumUnbuckling = evaluate.getEvaluatedFloat(5.0, 'maximumUnbuckling', xmlElement) - scalePathDefault = [Vector3(1.0, 1.0, 0.0), Vector3(1.0, 1.0, 1.0)] - self.interpolationDictionary['scale'] = Interpolation().getByPrefixZ(scalePathDefault, 'scale', xmlElement) - self.target = evaluate.getTransformedPathsByKey([], 'target', xmlElement) - if self.tiltTop is None: - offsetPathDefault = [Vector3(), Vector3(0.0, 0.0, 1.0)] - self.interpolationDictionary['offset'] = Interpolation().getByPrefixZ(offsetPathDefault, '', xmlElement) - tiltPathDefault = [Vector3(), Vector3(0.0, 0.0, 1.0)] - self.interpolationDictionary['tilt'] = Interpolation().getByPrefixZ(tiltPathDefault, 'tilt', xmlElement) - for point in self.interpolationDictionary['tilt'].path: - point.x = math.radians(point.x) - point.y = math.radians(point.y) - else: - offsetAlongDefault = [Vector3(), Vector3(1.0, 0.0, 0.0)] - self.interpolationDictionary['offset'] = Interpolation().getByPrefixAlong(offsetAlongDefault, '', xmlElement) - self.twist = evaluate.getEvaluatedFloat(0.0, 'twist', xmlElement ) - self.twistPathDefault = [Vector3(), Vector3(1.0, self.twist) ] - self.xmlElement = xmlElement - insertTwistPortions(self, xmlElement) - - def __repr__(self): - """Get the string representation of this ExtrudeDerivation.""" - return str(self.__dict__) - - -class Interpolation: - """Class to interpolate a path.""" - def __init__(self): - """Set index.""" - self.interpolationIndex = 0 - - def __repr__(self): - """Get the string representation of this Interpolation.""" - return str(self.__dict__) - - def getByDistances(self): - """Get by distances.""" - beginDistance = self.distances[0] - self.interpolationLength = self.distances[-1] - beginDistance - self.close = abs(0.000001 * self.interpolationLength) - self.portionDirections = [] - oldDistance = -self.interpolationLength # so the difference should not be close - for distance in self.distances: - deltaDistance = distance - beginDistance - portionDirection = PortionDirection(deltaDistance / self.interpolationLength) - if abs(deltaDistance - oldDistance) < self.close: - portionDirection.directionReversed = True - self.portionDirections.append(portionDirection) - oldDistance = deltaDistance - return self - - def getByPrefixAlong(self, path, prefix, xmlElement): - """Get interpolation from prefix and xml element along the path.""" - if len(path) < 2: - print('Warning, path is too small in evaluate in Interpolation.') - return - if xmlElement is None: - self.path = path - else: - self.path = evaluate.getTransformedPathByPrefix(path, prefix, xmlElement) - self.distances = [0.0] - previousPoint = self.path[0] - for point in self.path[1 :]: - distanceDifference = abs(point - previousPoint) - self.distances.append(self.distances[-1] + distanceDifference) - previousPoint = point - return self.getByDistances() - - def getByPrefixX(self, path, prefix, xmlElement): - """Get interpolation from prefix and xml element in the z direction.""" - if len(path) < 2: - print('Warning, path is too small in evaluate in Interpolation.') - return - if xmlElement is None: - self.path = path - else: - self.path = evaluate.getTransformedPathByPrefix(path, prefix, xmlElement) - self.distances = [] - for point in self.path: - self.distances.append(point.x) - return self.getByDistances() - - def getByPrefixZ(self, path, prefix, xmlElement): - """Get interpolation from prefix and xml element in the z direction.""" - if len(path) < 2: - print('Warning, path is too small in evaluate in Interpolation.') - return - if xmlElement is None: - self.path = path - else: - self.path = evaluate.getTransformedPathByPrefix(path, prefix, xmlElement) - self.distances = [] - for point in self.path: - self.distances.append(point.z) - return self.getByDistances() - - def getComparison( self, first, second ): - """Compare the first with the second.""" - if abs( second - first ) < self.close: - return 0 - if second > first: - return 1 - return - 1 - - def getComplexByPortion( self, portionDirection ): - """Get complex from z portion.""" - self.setInterpolationIndexFromTo( portionDirection ) - return self.oneMinusInnerPortion * self.startVertex.dropAxis() + self.innerPortion * self.endVertex.dropAxis() - - def getInnerPortion(self): - """Get inner x portion.""" - fromDistance = self.distances[ self.interpolationIndex ] - innerLength = self.distances[ self.interpolationIndex + 1 ] - fromDistance - if abs( innerLength ) == 0.0: - return 0.0 - return ( self.absolutePortion - fromDistance ) / innerLength - - def getVector3ByPortion( self, portionDirection ): - """Get vector3 from z portion.""" - self.setInterpolationIndexFromTo( portionDirection ) - return self.oneMinusInnerPortion * self.startVertex + self.innerPortion * self.endVertex - - def getYByPortion( self, portionDirection ): - """Get y from x portion.""" - self.setInterpolationIndexFromTo( portionDirection ) - return self.oneMinusInnerPortion * self.startVertex.y + self.innerPortion * self.endVertex.y - - def setInterpolationIndex( self, portionDirection ): - """Set the interpolation index.""" - self.absolutePortion = self.distances[0] + self.interpolationLength * portionDirection.portion - interpolationIndexes = range( 0, len( self.distances ) - 1 ) - if portionDirection.directionReversed: - interpolationIndexes.reverse() - for self.interpolationIndex in interpolationIndexes: - begin = self.distances[ self.interpolationIndex ] - end = self.distances[ self.interpolationIndex + 1 ] - if self.getComparison( begin, self.absolutePortion ) != self.getComparison( end, self.absolutePortion ): - return - - def setInterpolationIndexFromTo( self, portionDirection ): - """Set the interpolation index, the start vertex and the end vertex.""" - self.setInterpolationIndex( portionDirection ) - self.innerPortion = self.getInnerPortion() - self.oneMinusInnerPortion = 1.0 - self.innerPortion - self.startVertex = self.path[ self.interpolationIndex ] - self.endVertex = self.path[ self.interpolationIndex + 1 ] - - -class PortionDirection: - """Class to hold a portion and direction.""" - def __init__( self, portion ): - """Initialize.""" - self.directionReversed = False - self.portion = portion - - def __repr__(self): - """Get the string representation of this PortionDirection.""" - return '%s: %s' % ( self.portion, self.directionReversed ) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/gear.py b/skeinforge/fabmetheus_utilities/geometry/creation/gear.py deleted file mode 100644 index e85d3f0..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/gear.py +++ /dev/null @@ -1,1156 +0,0 @@ -""" -This page is in the table of contents. -The gear script can generate a spur gear couple, a bevel gear couple, a ring gear couple and a rack & pinion couple. - -A helix pattern can be added to each gear type. All the gear types have a clearance and all the teeth can be beveled. A keyway, shaft and lightening holes can be added to all the round gears, and rack holes can be added to the rack. The script can output solid gears or only the gear profiles. Both gears of the couple can be generated or just one. - -The couple has a pinion gear and a complement. - -==Examples== -The link text includes the distinguishing parameters. Each svg page was generated from an xml page of the same root name using carve. For example, default_gear.svg was generated by clicking 'Carve' on the carve tool panel and choosing default_gear.xml in the file chooser. - -Each generated svg file has the xml fabmetheus element without comments towards the end of the file. To see it, open the svg file in a text editor and search for 'fabmetheus' If you copy that into a new text document, add the line '' at the beginning and then give it a file name with the extension '.xml', you could then generate another svg file using carve. - -===Bevel=== -Bevel gear couple. - -gear operatingAngle=90 - -===Collar=== -Spur gear couple and each gear has a collar. - -gear complementCollarHeightOverHeight='1' pinionCollarHeightOverHeight='1' shaftRadius='5' - -===Default Gear=== -Default spur gear with no parameters. - -gear - -===Keyway=== -Spur gear couple and each gear has a collar and defined keyway. - -gear complementCollarHeightOverHeight='1' keywayRadius='2' pinionCollarHeightOverHeight='1' shaftRadius='5' - -===Rack=== -Rack and pinion couple. - -gear teethComplement='0' - -===Rack Hole=== -Rack and pinion couple, with holes in the rack. - -gear rackHoleRadiusOverWidth='0.2' rackWidthOverHeight='2' teethComplement='0' - -===Ring=== -Pinion and ring gear. - -gear teethComplement='-23' - -===Shaft=== -Spur gear couple and each gear has a square shaft hole. - -gear shaftRadius='5' - -===Shaft Top=== -Spur gear couple and each gear has a round shaft hole, truncated on top. - -gear shaftRadius='5' shaftSides='13' shaftDepthTop='2' - -===Spur Helix=== -Spur gear couple with the gear teeth following a helix path. - -gear helixAngle='45' - -===Spur Herringbone=== -Spur gear couple with the gear teeth following a herringbone path. - -gear helixAngle='45' helixType='herringbone' - -===Spur Parabolic=== -Spur gear couple with the gear teeth following a parabolic path. - -gear helixAngle='45' helixType='parabolic' - -===Spur Profile=== -Spur gear couple profile. Since this is just a horizontal path, it can not be sliced, so the path is then extruded to create a solid which can be sliced and viewed. - -gear id='spurProfile' height='0' | extrude target='=document.getElementByID(spurProfile) - -==Parameters== -===Center Distance=== -Default is such that the pitch radius works out to twenty. - -Defines the distance between the gear centers. - -===Clearance Couplet=== -====Clearance Over Wavelength==== -Default is 0.1. - -Defines the ratio of the clearance over the wavelength of the gear profile. The wavelength is the arc distance between the gear teeth. - -====Clearance==== -Default is the 'Clearance Over Wavelength' times the wavelength. - -Defines the clearance between the gear tooth and the other gear of the couple. If the clearance is zero, the outside of the gear tooth will touch the other gear. If the clearance is too high, the gear teeth will be long and weak. - -===Collar Width Couplet=== -====Collar Width Over Radius==== -Default is one. - -Defines the ratio of the collar width over the shaft radius. - -====Collar Width==== -Default is the 'Collar Width Over Radius' times the shaft radius. - -Defines the collar width. - -===Complement Collar Height Couplet=== -====Complement Collar Height Over Height==== -Default is zero. - -Defines the ratio of the complement collar height over the tooth height. - -====Complement Collar Height==== -Default is the 'Complement Collar Height Over Height' times the tooth height. - -Defines the complement collar height. If the complement collar height is zero, there will not be a collar on the complement gear. - -===Creation Type=== -Default is 'both'. - -====Both==== -When selected, the pinion and complement will be generated. - -====Complement==== -When selected, only the complement gear or rack will be generated. - -====Pinion==== -When selected, only the pinion will be generated. - -===Gear Hole Paths=== -Default is empty. - -Defines the centers of the gear holes. If the gear hole paths parameter is the default empty, then the centers of the gear holes will be generated from other parameters. - -===Height=== -Default is ten. - -Defines the tooth height. - -===Helix Angle=== -Default is zero. - -===Helix Path=== -Default is empty. - -Defines the helix path of the gear teeth. If the helix path is the default empty, then the helix will be generated from the helix angle and helix type. - -===Helix Type=== -Default is 'basic'. - -====Basic==== -When selected, the helix will be basic. - -====Herringbone==== -When selected, the helix will have a herringbone pattern. - -====Parabolic==== -When selected, the helix will have a parabolic pattern. - -===Keyway Radius Couplet=== -====Keyway Radius Over Radius==== -Default is half. - -Defines the ratio of the keyway radius over the shaft radius. - -====Keyway Radius==== -Default is the 'Keyway Radius Over Radius' times the shaft radius. - -Defines the keyway radius. If the keyway radius is zero, there will not be a keyway on the collar. - -===Lightening Hole Margin Couplet=== -====Lightening Hole Margin Over Rim Width==== -Default is one. - -Defines the ratio of the lightening hole margin over the rim width. - -====Lightening Hole Margin==== -Default is the 'Lightening Hole Margin Over Rim Width' times the rim width. - -Defines the minimum margin between lightening holes. - -===Lightening Hole Minimum Radius=== -Default is one. - -Defines the minimum radius of the lightening holes. - -===Move Type=== -Default is 'separate'. - -====None==== -When selected, the gears will be not be moved and will therefore overlap. Afterwards the write plugin could be used to write each gear to a different file, so they can be fabricated in separate operations. - -====Mesh==== -When selected, the gears will be separated horizontally so that they just mesh. This is useful to test if the gears mesh properly. - -====Separate==== -When selected, the gears will be separated horizontally with a gap between them. - -====Vertical==== -When selected, the gears will be separated vertically. - -===Operating Angle=== -Default is 180 degrees. - -Defines the operating angle between the gear axes. If the operating angle is not 180 degrees, a bevel gear couple will be generated. - -===Pinion Collar Height Over Height Couplet=== -====Pinion Collar Height Over Height==== -Default is zero. - -Defines the ratio of the pinion collar height over the tooth height. - -====Pinion Collar Height==== -Default is the 'Pinion Collar Height Over Height' times the tooth height. - -Defines the pinion collar height. If the pinion collar height is zero, there will not be a collar on the pinion gear. - -===Pitch Radius=== -Default is twenty if the pitch radius has not been set. If the center distance is set, the default pitch radius is the center distance times the number of pinion teeth divided by the total number of gear teeth. - -Defines the pinion pitch radius. - -===Plate Clearance Over Height Couplet=== -====Plate Clearance Over Height==== -Default is 0.2. - -Defines the ratio of the plate clearance over the plate height. - -====Plate Clearance==== -Default is the 'Plate Clearance Over Height' times the plate height. - -Defines the clearance between the pinoin and the plate of the ring gear. If the clearance is zero, they will touch. - -===Plate Height Over Height Couplet=== -====Plate Height Over Height==== -Default is half. - -Defines the ratio of the plate height over the tooth height. - -====Plate Height==== -Default is the 'Plate Height Over Height' times the tooth height. - -Defines the height of the plate of the ring gear. - -===Pressure Angle=== -Default is twenty degrees. - -Defines the pressure angle of the gear couple. - -===Profile Surfaces=== -Default is eleven. - -Defines the number of profile surfaces. - -===Rack Hole Radius Over Width Couplet=== -====Rack Hole Radius Over Width==== -Default is zero. - -Defines the ratio of the rack hole radius over the rack width. - -====Rack Hole Radius==== -Default is the 'Rack Hole Radius Over Width' times the rack width. - -Defines the radius of the rack holes. If the rack hole radius is zero, there won't be any rack holes. - -===Rack Hole Below Over Width Couplet=== -====Rack Hole Below Over Width==== -Default is 0.6. - -Defines the ratio of the distance below the pitch of the rack holes over the rack width. - -====Rack Hole Below==== -Default is the 'Rack Hole Below Over Width' times the rack width. - -Defines the the distance below the pitch of the rack holes. - -===Rack Hole Step Over Width Couplet=== -====Rack Hole Step Over Width==== -Default is one. - -Defines the ratio of the rack hole step over the rack width. - -====Rack Hole Step==== -Default is the 'Rack Hole Step Over Width' times the rack width. - -Defines the horizontal step distance between the rack holes. - -===Rack Length Over Radius Couplet=== -====Rack Length Over Radius==== -Default is two times pi. - -Defines the ratio of the rack length over the pitch radius. - -====Rack Length==== -Default is the 'Rack Length Over Radius' times the pitch radius. - -Defines the rack length. - -===Rack Width Over Height Couplet=== -====Rack Width Over Height==== -Default is one. - -Defines the ratio of the rack width over the tooth height. - -====Rack Width==== -Default is the 'Rack Width Over Height' times the tooth height. - -Defines the rack width. - -===Rim Width Over Height Couplet=== -====Rim Width Over Height==== -Default is 0.2. - -Defines the ratio of the rim width over the pitch radius. - -====Rim Width==== -Default is the 'Rim Width Over Height' times the pitch radius. - -Defines the rim width of the gear. - -===Root Bevel Over Clearance Couplet=== -====Root Bevel Over Clearance==== -Default is half. - -Defines the ratio of the root bevel over the clearance. - -====Root Bevel==== -Default is the 'Root Bevel Over Clearance' times the clearance. - -Defines the bevel at the root of the gear tooth. - -===Shaft Depth Bottom Couplet=== -====Shaft Depth Bottom Over Radius==== -Default is zero. - -Defines the ratio of the bottom shaft depth over the shaft radius. - -====Shaft Depth Bottom==== -Default is the 'Shaft Depth Bottom Over Radius' times the shaft radius. - -Defines the bottom shaft depth. - -===Shaft Depth Top Couplet=== -====Shaft Depth Top Over Radius==== -Default is zero. - -Defines the ratio of the top shaft depth over the shaft radius. - -====Shaft Depth Top==== -Default is the 'Shaft Depth Top Over Radius' times the shaft radius. - -Defines the top shaft depth. - -===Shaft Path=== -Default is empty. - -Defines the path of the shaft hole. If the shaft path is the default empty, then the shaft path will be generated from the shaft depth bottom, shaft depth top, shaft radius and shaft sides. - -===Shaft Radius Over Pitch Radius Couplet=== -====Shaft Radius Over Pitch Radius==== -Default is zero. - -Defines the ratio of the shaft radius over the pitch radius. - -====Shaft Radius==== -Default is the 'Shaft Radius Over Pitch Radius' times the pitch radius. - -Defines the shaft radius. - -===Shaft Sides=== -Default is four. - -Defines the number of shaft sides. - -===Teeth Pinion=== -Default is seven. - -Defines the number of teeth in the pinion. - -===Teeth Complement=== -Default is seventeen. - -Defines the number of teeth in the complement of the gear couple. If the number of teeth is positive, the gear couple will be a spur or bevel type. If the number of teeth is zero, the gear couple will be a rack and pinion. If the number of teeth is negative, the gear couple will be a spur and ring. - -===Tip Bevel Over Clearance Couplet=== -====Tip Bevel Over Clearance==== -Default is 0.1. - -Defines the ratio of the tip bevel over the clearance. - -====Tip Bevel==== -Default is the 'Tip Bevel Over Clearance' times the clearance. - -Defines the bevel at the tip of the gear tooth. - -===Tooth Width Multiplier=== -Default is 0.99999. - -Defines the amount the width of the tooth will multiplied. If when the gears are produced, they mesh too tightly, you can reduce the tooth width multiplier so that they mesh with reasonable tightness. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import extrude -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.creation import shaft -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.creation import teardrop -from fabmetheus_utilities.geometry.geometry_tools import path -from fabmetheus_utilities.geometry.geometry_utilities.evaluate_elements import setting -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities.vector3index import Vector3Index -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addBevelGear(derivation, extrudeDerivation, pitchRadius, positives, teeth, vector3GearProfile): - """Get extrude output for a cylinder gear.""" - totalPitchRadius = derivation.pitchRadiusComplement + derivation.pitchRadius - totalTeeth = derivation.teethPinion + derivation.teethComplement - portionDirections = extrude.getSpacedPortionDirections(extrudeDerivation.interpolationDictionary) - loopLists = extrude.getLoopListsByPath(extrudeDerivation, None, vector3GearProfile[0], portionDirections) - firstLoopList = loopLists[0] - gearOverPinion = float(totalTeeth - teeth) / float(teeth) - thirdLayerHeight = 0.33333333333 * setting.getLayerHeight(derivation.xmlElement) - pitchRadian = math.atan(math.sin(derivation.operatingRadian) / (gearOverPinion + math.cos(derivation.operatingRadian))) - coneDistance = pitchRadius / math.sin(pitchRadian) - apex = Vector3(0.0, 0.0, math.sqrt(coneDistance * coneDistance - pitchRadius * pitchRadius)) - cosPitch = apex.z / coneDistance - sinPitch = math.sin(pitchRadian) - for loop in firstLoopList: - for point in loop: - alongWay = point.z / coneDistance - oneMinusAlongWay = 1.0 - alongWay - pointComplex = point.dropAxis() - pointComplexLength = abs(pointComplex) - deltaRadius = pointComplexLength - pitchRadius - cosDeltaRadius = cosPitch * deltaRadius - sinDeltaRadius = sinPitch * deltaRadius - pointComplex *= (cosDeltaRadius + pitchRadius) / pointComplexLength - point.x = pointComplex.real - point.y = pointComplex.imag - point.z += sinDeltaRadius - point.x *= oneMinusAlongWay - point.y *= oneMinusAlongWay - addBottomLoop(-thirdLayerHeight, firstLoopList) - topLoop = firstLoopList[-1] - topAddition = [] - topZ = euclidean.getTopPath(topLoop) + thirdLayerHeight - oldIndex = topLoop[-1].index - for point in topLoop: - oldIndex += 1 - topAddition.append(Vector3Index(oldIndex, 0.8 * point.x, 0.8 * point.y, topZ)) - firstLoopList.append(topAddition) - translation = Vector3(0.0, 0.0, -euclidean.getBottomByPaths(firstLoopList)) - euclidean.translateVector3Paths(firstLoopList, translation) - geometryOutput = triangle_mesh.getPillarsOutput(loopLists) - positives.append(geometryOutput) - -def addBottomLoop(deltaZ, loops): - """Add bottom loop to loops.""" - bottomLoop = loops[0] - bottomAddition = [] - bottomZ = euclidean.getBottomByPath(bottomLoop) + deltaZ - for point in bottomLoop: - bottomAddition.append(Vector3Index(len(bottomAddition), point.x, point.y, bottomZ)) - loops.insert(0, bottomAddition) - numberOfVertexes = 0 - for loop in loops: - for point in loop: - point.index = numberOfVertexes - numberOfVertexes += 1 - -def addCollarShaft(collarHeight, derivation, negatives, positives, xmlElement): - """Add collar.""" - if collarHeight <= 0.0: - addShaft(derivation, negatives, positives) - return - connectionEnd = Vector3(0.0, 0.0, derivation.height + collarHeight) - copyShallow = derivation.xmlElement.getCopyShallow() - copyShallow.attributeDictionary['path'] = [Vector3(0.0, 0.0, derivation.height), connectionEnd] - collarDerivation = extrude.ExtrudeDerivation(copyShallow) - addCollarShaftSetDerivation(collarDerivation, collarHeight, derivation, negatives, positives, xmlElement) - -def addCollarShaftSetDerivation(collarDerivation, collarHeight, derivation, negatives, positives, xmlElement): - """Add collar and shaft.""" - collarSides = evaluate.getSidesMinimumThreeBasedOnPrecision(derivation.shaftRimRadius, xmlElement) - collarProfile = euclidean.getComplexPolygon(complex(), derivation.shaftRimRadius, collarSides) - vector3CollarProfile = euclidean.getVector3Path(collarProfile) - extrude.addPositives(collarDerivation, [vector3CollarProfile], positives) - addShaft(derivation, negatives, positives) - drillZ = derivation.height + 0.5 * collarHeight - drillEnd = Vector3(0.0, derivation.shaftRimRadius, drillZ) - drillStart = Vector3(0.0, 0.0, drillZ) - teardrop.addNegativesByRadius(drillEnd, negatives, derivation.keywayRadius, drillStart, xmlElement) - -def addLighteningHoles(derivation, gearHolePaths, negatives, pitchRadius, positives): - """Add lightening holes.""" - positiveVertexes = matrix.getVertexes(positives) - bottomPath = euclidean.getTopPath(positiveVertexes) - topPath = euclidean.getBottomByPath(positiveVertexes) - copyShallow = derivation.xmlElement.getCopyShallow() - copyShallow.attributeDictionary['path'] = [Vector3(0.0, 0.0, bottomPath), Vector3(0.0, 0.0, topPath)] - extrudeDerivation = extrude.ExtrudeDerivation(copyShallow) - vector3LighteningHoles = getLighteningHoles(derivation, gearHolePaths, pitchRadius) - extrude.addNegativesPositives(extrudeDerivation, negatives, vector3LighteningHoles, positives) - -def addRackHole(derivation, vector3RackProfiles, x, xmlElement): - """Add rack hole to vector3RackProfiles.""" - rackHole = euclidean.getComplexPolygon(complex(x, -derivation.rackHoleBelow), derivation.rackHoleRadius, -13) - vector3RackProfiles.append(euclidean.getVector3Path(rackHole)) - -def addRackHoles(derivation, vector3RackProfiles, xmlElement): - """Add rack holes to vector3RackProfiles.""" - if len(derivation.gearHolePaths) > 0: - vector3RackProfiles += derivation.gearHolePaths - return - if derivation.rackHoleRadius <= 0.0: - return - addRackHole(derivation, vector3RackProfiles, 0.0, xmlElement) - rackHoleMargin = derivation.rackHoleRadius + derivation.rackHoleRadius - rackHoleSteps = int(math.ceil((derivation.rackDemilength - rackHoleMargin) / derivation.rackHoleStep)) - for rackHoleIndex in xrange(1, rackHoleSteps): - x = float(rackHoleIndex) * derivation.rackHoleStep - addRackHole(derivation, vector3RackProfiles, -x, xmlElement) - addRackHole(derivation, vector3RackProfiles, x, xmlElement) - -def addShaft(derivation, negatives, positives): - """Add shaft.""" - if len(derivation.shaftPath) < 3: - return - positiveVertexes = matrix.getVertexes(positives) - bottomPath = euclidean.getTopPath(positiveVertexes) - topPath = euclidean.getBottomByPath(positiveVertexes) - copyShallow = derivation.xmlElement.getCopyShallow() - copyShallow.attributeDictionary['path'] = [Vector3(0.0, 0.0, bottomPath), Vector3(0.0, 0.0, topPath)] - extrudeDerivation = extrude.ExtrudeDerivation(copyShallow) - extrude.addNegativesPositives(extrudeDerivation, negatives, [derivation.shaftPath], positives) - -def getAxialMargin(circleRadius, numberOfSides, polygonRadius): - """Get axial margin.""" - return polygonRadius * math.sin(math.pi / float(numberOfSides)) - circleRadius - -def getBevelPath(begin, bevel, center, end): - """Get bevel path.""" - centerMinusBegin = center - begin - centerMinusBeginLength = abs(centerMinusBegin) - endMinusCenter = end - center - endMinusCenterLength = abs(endMinusCenter) - endMinusCenter /= endMinusCenterLength - maximumExtensionLength = 0.333333333 * endMinusCenterLength - if centerMinusBeginLength <= bevel * 1.5: - extensionLength = min(maximumExtensionLength, centerMinusBeginLength) - return [complex(center.real, center.imag) + extensionLength * endMinusCenter] - centerMinusBegin *= (centerMinusBeginLength - bevel) / centerMinusBeginLength - extensionLength = min(maximumExtensionLength, bevel) - bevelPath = [complex(center.real, center.imag) + extensionLength * endMinusCenter] - bevelPath.append(begin + centerMinusBegin) - return bevelPath - -def getGearPaths(derivation, pitchRadius, teeth, toothProfile): - """Get gear paths.""" - if teeth < 0: - return getGearProfileAnnulus(derivation, pitchRadius, teeth, toothProfile) - if teeth == 0: - return [getGearProfileRack(derivation, toothProfile)] - return [getGearProfileCylinder(teeth, toothProfile)] - -def getGearProfileAnnulus(derivation, pitchRadius, teeth, toothProfile): - """Get gear profile for an annulus gear.""" - gearProfileCylinder = getGearProfileCylinder(teeth, toothProfile) - annulusRadius = derivation.dedendum + derivation.rimWidth - pitchRadius - return [euclidean.getComplexPolygon(complex(), annulusRadius, -teeth, 0.5 * math.pi), gearProfileCylinder] - -def getGearProfileCylinder(teeth, toothProfile): - """Get gear profile for a cylinder gear.""" - gearProfile = [] - toothAngleRadian = 2.0 * math.pi / float(teeth) - totalToothAngle = 0.0 - for toothIndex in xrange(abs(teeth)): - for toothPoint in toothProfile: - gearProfile.append(toothPoint * euclidean.getWiddershinsUnitPolar(totalToothAngle)) - totalToothAngle += toothAngleRadian - return gearProfile - -def getGearProfileRack(derivation, toothProfile): - """Get gear profile for rack.""" - derivation.extraRackDemilength = 0.0 - for complexPoint in derivation.helixPath: - derivation.extraRackDemilength = max(abs(derivation.helixHeight * complexPoint.imag), derivation.extraRackDemilength) - rackDemilengthPlus = derivation.rackDemilength - if derivation.height > 0.0: - derivation.extraRackDemilength *= 1.1 - rackDemilengthPlus += derivation.extraRackDemilength - teethRack = int(math.ceil(rackDemilengthPlus / derivation.wavelength)) - gearProfile = [] - for toothIndex in xrange(-teethRack, teethRack + 1): - translateComplex = complex(-toothIndex * derivation.wavelength, 0.0) - translatedPath = euclidean.getTranslatedComplexPath(toothProfile, translateComplex) - gearProfile += translatedPath - gearProfile = euclidean.getHorizontallyBoundedPath(rackDemilengthPlus, -rackDemilengthPlus, gearProfile) - firstPoint = gearProfile[0] - lastPoint = gearProfile[-1] - rackWidth = derivation.rackWidth - minimumRackWidth = 1.1 * derivation.dedendum - if rackWidth < minimumRackWidth: - rackWidth = minimumRackWidth - print('Warning, rackWidth is too small in getGearProfileRack in gear.') - print('RackWidth will be set to a bit more than the dedendum.') - gearProfile += [complex(lastPoint.real, -rackWidth),complex(firstPoint.real, -rackWidth)] - return gearProfile - -def getGeometryOutput(derivation, xmlElement): - """Get vector3 vertexes from attribute dictionary.""" - if derivation is None: - derivation = GearDerivation(xmlElement) - creationFirst = derivation.creationType.lower()[: 1] - toothProfileComplement = getToothProfile(derivation, derivation.pitchRadiusComplement, derivation.teethComplement) - pinionProfile = getGearProfileCylinder(derivation.teethPinion, derivation.pinionToothProfile) - complementPaths = getGearPaths( - derivation, derivation.pitchRadiusComplement, derivation.teethComplement, toothProfileComplement) - vector3PinionProfile = euclidean.getVector3Path(pinionProfile) - vector3ComplementPaths = euclidean.getVector3Paths(complementPaths) - translation = Vector3() - moveFirst = derivation.moveType.lower()[: 1] - if moveFirst != 'n': - distance = derivation.pitchRadius - if moveFirst == 'm': - distance += derivation.pitchRadiusComplement - else: - distance += abs(derivation.pitchRadiusComplement) - decimalPlaces = 1 - int(math.floor(math.log10(distance))) - distance += derivation.halfWavelength + derivation.halfWavelength - distance = round(1.15 * distance, decimalPlaces) - translation = Vector3(0.0, -distance) - if derivation.height <=0.0: - return getPathOutput( - creationFirst, derivation, translation, vector3ComplementPaths, vector3PinionProfile, xmlElement) - pitchRadius = derivation.pitchRadius - teeth = derivation.teethPinion - twist = derivation.helixHeight / derivation.pitchRadius - extrudeOutputPinion = getOutputCylinder( - derivation.pinionCollarHeight, derivation, None, pitchRadius, teeth, twist, [vector3PinionProfile], xmlElement) - if creationFirst == 'p': - return extrudeOutputPinion - teeth = derivation.teethComplement - extrudeOutputSecond = None - if teeth == 0: - extrudeOutputSecond = getOutputRack(derivation, vector3ComplementPaths[0], xmlElement) - else: - twist = -derivation.helixHeight / derivation.pitchRadiusComplement - extrudeOutputSecond = getOutputCylinder( - derivation.complementCollarHeight, - derivation, - derivation.gearHolePaths, - derivation.pitchRadiusComplement, - teeth, - twist, - vector3ComplementPaths, - xmlElement) - if creationFirst == 'c': - return extrudeOutputSecond - gearVertexes = matrix.getVertexes(extrudeOutputSecond) - if moveFirst == 'v': - translation = Vector3(0.0, 0.0, euclidean.getTopPath(gearVertexes)) - euclidean.translateVector3Path(matrix.getVertexes(extrudeOutputPinion), translation) - else: - euclidean.translateVector3Path(gearVertexes, translation) - return {'group' : {'shapes' : [extrudeOutputPinion, extrudeOutputSecond]}} - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get vector3 vertexes from attribute dictionary by arguments.""" - return getGeometryOutput(None, xmlElement) - -def getHalfwave(pitchRadius, teeth): - """Get tooth halfwave.""" - return pitchRadius * math.pi / float(teeth) - -def getHelixComplexPath(derivation, xmlElement): - """Set gear helix path.""" - helixTypeFirstCharacter = derivation.helixType.lower()[: 1] - if helixTypeFirstCharacter == 'b': - return [complex(), complex(1.0, 1.0)] - if helixTypeFirstCharacter == 'h': - return [complex(), complex(0.5, 0.5), complex(1.0, 0.0)] - if helixTypeFirstCharacter == 'p': - helixComplexPath = [] - x = 0.0 - xStep = setting.getLayerHeight(xmlElement) / derivation.height - justBelowOne = 1.0 - 0.5 * xStep - while x < justBelowOne: - distanceFromCenter = 0.5 - x - parabolicTwist = 0.25 - distanceFromCenter * distanceFromCenter - helixComplexPath.append(complex(x, parabolicTwist)) - x += xStep - helixComplexPath.append(complex(1.0, 0.0)) - return helixComplexPath - print('Warning, the helix type was not one of (basic, herringbone or parabolic) in getHelixComplexPath in gear for:') - print(derivation.helixType) - print(derivation.xmlElement) - -def getLiftedOutput(derivation, geometryOutput, xmlElement): - """Get extrude output for a rack.""" - if derivation.moveType.lower()[: 1] == 'm': - return geometryOutput - geometryOutputVertexes = matrix.getVertexes(geometryOutput) - translation = Vector3(0.0, 0.0, -euclidean.getBottomByPath(geometryOutputVertexes)) - euclidean.translateVector3Path(geometryOutputVertexes, translation) - return geometryOutput - -def getLighteningHoles(derivation, gearHolePaths, pitchRadius): - """Get cutout circles.""" - if gearHolePaths is not None: - if len(gearHolePaths) > 0: - return gearHolePaths - innerRadius = abs(pitchRadius) - derivation.dedendum - lighteningHoleOuterRadius = innerRadius - derivation.rimWidth - shaftRimRadius = max(derivation.shaftRimRadius, lighteningHoleOuterRadius * (0.5 - math.sqrt(0.1875))) - lighteningHoleRadius = 0.5 * (lighteningHoleOuterRadius - derivation.shaftRimRadius) - if lighteningHoleRadius < derivation.lighteningHoleMinimumRadius: - return [] - lighteningHoles = [] - numberOfLighteningHoles = 3 - polygonRadius = lighteningHoleOuterRadius - lighteningHoleRadius - rimDemiwidth = 0.5 * derivation.lighteningHoleMargin - axialMargin = getAxialMargin(lighteningHoleRadius, numberOfLighteningHoles, polygonRadius) - if axialMargin < rimDemiwidth: - while axialMargin < rimDemiwidth: - lighteningHoleRadius *= 0.999 - if lighteningHoleRadius < derivation.lighteningHoleMinimumRadius: - return [] - axialMargin = getAxialMargin(lighteningHoleRadius, numberOfLighteningHoles, polygonRadius) - else: - newNumberOfLighteningHoles = numberOfLighteningHoles - while axialMargin > rimDemiwidth: - numberOfLighteningHoles = newNumberOfLighteningHoles - newNumberOfLighteningHoles += 2 - axialMargin = getAxialMargin(lighteningHoleRadius, newNumberOfLighteningHoles, polygonRadius) - sideAngle = 2.0 * math.pi / float(numberOfLighteningHoles) - startAngle = 0.0 - for lighteningHoleIndex in xrange(numberOfLighteningHoles): - unitPolar = euclidean.getWiddershinsUnitPolar(startAngle) - lighteningHole = euclidean.getComplexPolygon(unitPolar * polygonRadius, lighteningHoleRadius, -13) - lighteningHoles.append(lighteningHole) - startAngle += sideAngle - return euclidean.getVector3Paths(lighteningHoles) - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return GearDerivation(xmlElement) - -def getOutputCylinder( - collarHeight, derivation, gearHolePaths, pitchRadius, teeth, twist, vector3GearProfile, xmlElement): - """Get extrude output for a cylinder gear.""" - copyShallow = derivation.xmlElement.getCopyShallow() - copyShallow.attributeDictionary['path'] = [Vector3(), Vector3(0.0, 0.0, derivation.height)] - extrudeDerivation = extrude.ExtrudeDerivation(copyShallow) - negatives = [] - positives = [] - if twist != 0.0: - twistDegrees = math.degrees(twist) - extrudeDerivation.twistPathDefault = [] - for complexPoint in derivation.helixPath: - extrudeDerivation.twistPathDefault.append(Vector3(complexPoint.real, twistDegrees * complexPoint.imag)) - extrude.insertTwistPortions(extrudeDerivation, xmlElement) - if derivation.operatingAngle != 180.0: - addBevelGear(derivation, extrudeDerivation, pitchRadius, positives, teeth, vector3GearProfile) - addCollarShaft(collarHeight, derivation, negatives, positives, xmlElement) - return extrude.getGeometryOutputByNegativesPositives(negatives, positives, xmlElement) - if pitchRadius > 0: - extrude.addNegativesPositives(extrudeDerivation, negatives, vector3GearProfile, positives) - addLighteningHoles(derivation, gearHolePaths, negatives, pitchRadius, positives) - addCollarShaft(collarHeight, derivation, negatives, positives, xmlElement) - return extrude.getGeometryOutputByNegativesPositives(negatives, positives, xmlElement) - if derivation.plateHeight <= 0.0: - extrude.addNegativesPositives(extrudeDerivation, negatives, vector3GearProfile, positives) - return extrude.getGeometryOutputByNegativesPositives(negatives, positives, xmlElement) - portionDirections = extrude.getSpacedPortionDirections(extrudeDerivation.interpolationDictionary) - outerGearProfile = vector3GearProfile[0] - outerLoopLists = extrude.getLoopListsByPath(extrudeDerivation, None, outerGearProfile, portionDirections) - addBottomLoop(-derivation.plateClearance, outerLoopLists[0]) - geometryOutput = triangle_mesh.getPillarsOutput(outerLoopLists) - positives.append(geometryOutput) - innerLoopLists = extrude.getLoopListsByPath(extrudeDerivation, None, vector3GearProfile[1], portionDirections) - addBottomLoop(-derivation.plateClearance, innerLoopLists[0]) - geometryOutput = triangle_mesh.getPillarsOutput(innerLoopLists) - negatives.append(geometryOutput) - connectionStart = Vector3(0.0, 0.0, -derivation.plateHeight) - copyShallow = derivation.xmlElement.getCopyShallow() - copyShallow.attributeDictionary['path'] = [connectionStart, Vector3(0.0, 0.0, -derivation.plateClearance)] - plateDerivation = extrude.ExtrudeDerivation(copyShallow) - extrude.addNegativesPositives(plateDerivation, negatives, [outerGearProfile], positives) - vector3LighteningHoles = getLighteningHoles(derivation, gearHolePaths, pitchRadius) - extrude.addNegativesPositives(plateDerivation, negatives, vector3LighteningHoles, positives) - addShaft(derivation, negatives, positives) - positiveOutput = triangle_mesh.getUnifiedOutput(positives) - annulusPlateOutput = {'difference' : {'shapes' : [positiveOutput] + negatives}} - if collarHeight <= 0.0: - outputCylinder = solid.getGeometryOutputByManipulation(annulusPlateOutput, xmlElement) - return getLiftedOutput(derivation, outputCylinder, xmlElement) - negatives = [] - positives = [] - connectionEnd = Vector3(0.0, 0.0, derivation.height + collarHeight) - copyShallow = derivation.xmlElement.getCopyShallow() - copyShallow.attributeDictionary['path'] = [Vector3(0.0, 0.0, -derivation.plateClearance), connectionEnd] - collarDerivation = extrude.ExtrudeDerivation(copyShallow) - addCollarShaftSetDerivation(collarDerivation, collarHeight, derivation, negatives, positives, xmlElement) - collarOutput = {'difference' : {'shapes' : positives + negatives}} - cylinderOutput = {'union' : {'shapes' : [annulusPlateOutput, collarOutput]}} - outputCylinder = solid.getGeometryOutputByManipulation(cylinderOutput, xmlElement) - return getLiftedOutput(derivation, outputCylinder, xmlElement) - -def getOutputRack(derivation, vector3GearProfile, xmlElement): - """Get extrude output for a rack.""" - path = [] - for complexPoint in derivation.helixPath: - point = Vector3(derivation.helixHeight * complexPoint.imag, 0.0, derivation.height * complexPoint.real) - path.append(point) - copyShallow = derivation.xmlElement.getCopyShallow() - copyShallow.attributeDictionary['path'] = path - extrudeDerivation = extrude.ExtrudeDerivation(copyShallow) - negatives = [] - positives = [] - vector3RackProfiles = [vector3GearProfile] - if derivation.extraRackDemilength > 0.0: - yMaximum = -912345678.0 - yMinimum = 912345678.0 - for point in vector3GearProfile: - yMaximum = max(point.y, yMaximum) - yMinimum = min(point.y, yMinimum) - muchLessThanWidth = 0.01 * derivation.rackWidth - yMaximum += muchLessThanWidth - yMinimum -= muchLessThanWidth - extraRackLength = derivation.extraRackDemilength + derivation.extraRackDemilength - rackDemilengthPlus = derivation.rackDemilength + extraRackLength - leftNegative = [ - Vector3(-derivation.rackDemilength, yMaximum), - Vector3(-derivation.rackDemilength, yMinimum), - Vector3(-rackDemilengthPlus, yMinimum), - Vector3(-rackDemilengthPlus, yMaximum)] - vector3RackProfiles.append(leftNegative) - rightNegative = [ - Vector3(rackDemilengthPlus, yMaximum), - Vector3(rackDemilengthPlus, yMinimum), - Vector3(derivation.rackDemilength, yMinimum), - Vector3(derivation.rackDemilength, yMaximum)] - vector3RackProfiles.append(rightNegative) - addRackHoles(derivation, vector3RackProfiles, xmlElement) - extrude.addNegativesPositives(extrudeDerivation, negatives, vector3RackProfiles, positives) - return extrude.getGeometryOutputByNegativesPositives(negatives, positives, xmlElement) - -def getPathOutput(creationFirst, derivation, translation, vector3ComplementPaths, vector3PinionProfile, xmlElement): - """Get gear path output.""" - vector3PinionProfile = lineation.getPackedGeometryOutputByLoop(lineation.SideLoop(vector3PinionProfile), xmlElement) - if creationFirst == 'p': - return vector3PinionProfile - packedGearGeometry = [] - for vector3ComplementPath in vector3ComplementPaths: - sideLoop = lineation.SideLoop(vector3ComplementPath) - packedGearGeometry += lineation.getPackedGeometryOutputByLoop(sideLoop, xmlElement) - if creationFirst == 'c': - return packedGearGeometry - euclidean.translateVector3Paths(packedGearGeometry, translation) - return vector3PinionProfile + packedGearGeometry - -def getToothProfile(derivation, pitchRadius, teeth): - """Get profile for one tooth.""" - if teeth < 0: - return getToothProfileAnnulus(derivation, pitchRadius, teeth) - if teeth == 0: - return getToothProfileRack(derivation) - return getToothProfileCylinder(derivation, pitchRadius, teeth) - -def getToothProfileAnnulus(derivation, pitchRadius, teeth): - """Get profile for one tooth of an annulus.""" - toothProfileHalf = [] - toothProfileHalfCylinder = getToothProfileHalfCylinder(derivation, pitchRadius) - pitchRadius = -pitchRadius - innerRadius = pitchRadius - derivation.addendum - # tooth is multiplied by 1.02 because at around 1.01 for a 7/-23/20.0 test case, there is intersection since the paths are bending together - for point in getWidthMultipliedPath(toothProfileHalfCylinder, 1.02 / derivation.toothWidthMultiplier): - if abs(point) >= innerRadius: - toothProfileHalf.append(point) - profileFirst = toothProfileHalf[0] - profileSecond = toothProfileHalf[1] - firstMinusSecond = profileFirst - profileSecond - remainingAddendum = abs(profileFirst) - innerRadius - firstMinusSecond *= remainingAddendum / abs(firstMinusSecond) - extensionPoint = profileFirst + firstMinusSecond - if derivation.tipBevel > 0.0: - unitPolar = euclidean.getWiddershinsUnitPolar(2.0 / float(teeth) * math.pi) - mirrorPoint = complex(-extensionPoint.real, extensionPoint.imag) * unitPolar - bevelPath = getBevelPath(profileFirst, derivation.tipBevel, extensionPoint, mirrorPoint) - toothProfileHalf = bevelPath + toothProfileHalf - else: - toothProfileHalf.insert(0, extensionPoint) - profileLast = toothProfileHalf[-1] - profilePenultimate = toothProfileHalf[-2] - lastMinusPenultimate = profileLast - profilePenultimate - remainingDedendum = pitchRadius - abs(profileLast) + derivation.dedendum - lastMinusPenultimate *= remainingDedendum / abs(lastMinusPenultimate) - extensionPoint = profileLast + lastMinusPenultimate - if derivation.rootBevel > 0.0: - mirrorPoint = complex(-extensionPoint.real, extensionPoint.imag) - bevelPath = getBevelPath(profileLast, derivation.rootBevel, extensionPoint, mirrorPoint) - bevelPath.reverse() - toothProfileHalf += bevelPath - else: - toothProfileHalf.append(extensionPoint) - toothProfileAnnulus = euclidean.getMirrorPath(toothProfileHalf) - toothProfileAnnulus.reverse() - return toothProfileAnnulus - -def getToothProfileCylinder(derivation, pitchRadius, teeth): - """Get profile for one tooth of a cylindrical gear.""" - toothProfileHalfCylinder = getToothProfileHalfCylinder(derivation, pitchRadius) - toothProfileHalfCylinder = getWidthMultipliedPath(toothProfileHalfCylinder, derivation.toothWidthMultiplier) - toothProfileHalf = [] - innerRadius = pitchRadius - derivation.dedendum - for point in toothProfileHalfCylinder: - if abs(point) >= innerRadius: - toothProfileHalf.append(point) - return getToothProfileCylinderByProfile(derivation, pitchRadius, teeth, toothProfileHalf) - -def getToothProfileCylinderByProfile(derivation, pitchRadius, teeth, toothProfileHalf): - """Get profile for one tooth of a cylindrical gear.""" - profileFirst = toothProfileHalf[0] - profileSecond = toothProfileHalf[1] - firstMinusSecond = profileFirst - profileSecond - remainingDedendum = abs(profileFirst) - pitchRadius + derivation.dedendum - firstMinusSecond *= remainingDedendum / abs(firstMinusSecond) - extensionPoint = profileFirst + firstMinusSecond - if derivation.rootBevel > 0.0: - unitPolar = euclidean.getWiddershinsUnitPolar(-2.0 / float(teeth) * math.pi) - mirrorPoint = complex(-extensionPoint.real, extensionPoint.imag) * unitPolar - bevelPath = getBevelPath(profileFirst, derivation.rootBevel, extensionPoint, mirrorPoint) - toothProfileHalf = bevelPath + toothProfileHalf - else: - toothProfileHalf.insert(0, extensionPoint) - if derivation.tipBevel > 0.0: - profileLast = toothProfileHalf[-1] - profilePenultimate = toothProfileHalf[-2] - mirrorPoint = complex(-profileLast.real, profileLast.imag) - bevelPath = getBevelPath(profilePenultimate, derivation.tipBevel, profileLast, mirrorPoint) - bevelPath.reverse() - toothProfileHalf = toothProfileHalf[: -1] + bevelPath - return euclidean.getMirrorPath(toothProfileHalf) - -def getToothProfileHalfCylinder(derivation, pitchRadius): - """Get profile for half of a one tooth of a cylindrical gear.""" - toothProfile=[] -# x = -y * tan(p) + 1 -# x*x + y*y = (2-cos(p))^2 -# y*y*t*t-2yt+1+y*y=4-4c-c*c -# y*y*(t*t+1)-2yt=3-4c-c*c -# y*y*(t*t+1)-2yt-3+4c-c*c=0 -# a=tt+1 -# b=-2t -# c=c(4-c)-3 - a = derivation.tanPressure * derivation.tanPressure + 1.0 - b = -derivation.tanPressure - derivation.tanPressure - cEnd = derivation.cosPressure * (4.0 - derivation.cosPressure) - 3.0 - yEnd = (-b - math.sqrt(b*b - 4 * a * cEnd)) * 0.5 / a - yEnd *= derivation.pitchRadius / abs(pitchRadius) - yEnd -= derivation.clearance / abs(pitchRadius) - # to prevent intersections, yBegin is moved towards the base circle, giving a thinner tooth - yBegin = -yEnd - if pitchRadius > 0.0: - yBegin = 0.5 * derivation.sinPressure + 0.5 * yBegin - beginComplex = complex(1.0 - yBegin * derivation.tanPressure, yBegin) - endComplex = complex(1.0 - yEnd * derivation.tanPressure, yEnd) - endMinusBeginComplex = endComplex - beginComplex - wholeAngle = -abs(endMinusBeginComplex) / derivation.cosPressure - wholeAngleIncrement = wholeAngle / float(derivation.profileSurfaces) - stringStartAngle = abs(beginComplex - complex(1.0, 0.0)) / derivation.cosPressure - wholeDepthIncrementComplex = endMinusBeginComplex / float(derivation.profileSurfaces) - for profileIndex in xrange(derivation.profileSurfaces + 1): - contactPoint = beginComplex + wholeDepthIncrementComplex * float(profileIndex) - stringAngle = stringStartAngle + wholeAngleIncrement * float(profileIndex) - angle = math.atan2(contactPoint.imag, contactPoint.real) - stringAngle - angle += 0.5 * math.pi - derivation.quarterWavelength / abs(pitchRadius) - toothPoint = abs(contactPoint) * euclidean.getWiddershinsUnitPolar(angle) * abs(pitchRadius) - toothProfile.append(toothPoint) - return toothProfile - -def getToothProfileRack(derivation): - """Get profile for one rack tooth.""" - addendumSide = derivation.quarterWavelength - derivation.addendum * derivation.tanPressure - addendumComplex = complex(addendumSide, derivation.addendum) - dedendumSide = derivation.quarterWavelength + derivation.dedendum * derivation.tanPressure - dedendumComplex = complex(dedendumSide, -derivation.dedendum) - toothProfile = [dedendumComplex] - if derivation.rootBevel > 0.0: - mirrorPoint = complex(derivation.wavelength - dedendumSide, -derivation.dedendum) - toothProfile = getBevelPath(addendumComplex, derivation.rootBevel, dedendumComplex, mirrorPoint) - if derivation.tipBevel > 0.0: - mirrorPoint = complex(-addendumComplex.real, addendumComplex.imag) - bevelPath = getBevelPath(dedendumComplex, derivation.tipBevel, addendumComplex, mirrorPoint) - bevelPath.reverse() - toothProfile += bevelPath - else: - toothProfile.append(addendumComplex) - return euclidean.getMirrorPath(getWidthMultipliedPath(toothProfile, derivation.toothWidthMultiplier)) - -def getWidthMultipliedPath(path, widthMultiplier): - """Get width multiplied path.""" - for pointIndex, point in enumerate(path): - path[pointIndex] = complex(point.real * widthMultiplier, point.imag) - return path - -def processXMLElement(xmlElement): - """Process the xml element.""" - geometryOutput = getGeometryOutput(None, xmlElement) - if geometryOutput.__class__ == list: - path.convertXMLElement(geometryOutput, xmlElement) - else: - solid.processXMLElementByGeometry(geometryOutput, xmlElement) - - -class GearDerivation: - """Class to hold gear variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.clearanceOverWavelength = evaluate.getEvaluatedFloat(0.1, 'clearanceOverWavelength', xmlElement) - self.collarWidthOverRadius = evaluate.getEvaluatedFloat(1.0, 'collarWidthOverRadius', xmlElement) - self.complementCollarHeightOverHeight = evaluate.getEvaluatedFloat( - 0.0, 'complementCollarHeightOverHeight', xmlElement) - self.copyShallow = xmlElement.getCopyShallow() - self.creationType = evaluate.getEvaluatedString('both', 'creationType', xmlElement) - self.creationTypeMenuRadioStrings = 'both complement pinion'.split() - self.helixAngle = evaluate.getEvaluatedFloat(0.0, 'helixAngle', xmlElement) - self.helixType = evaluate.getEvaluatedString('basic', 'helixType', xmlElement) - self.helixTypeMenuRadioStrings = 'basic herringbone parabolic'.split() - self.keywayRadiusOverRadius = evaluate.getEvaluatedFloat(0.5, 'keywayRadiusOverRadius', xmlElement) - self.lighteningHoleMarginOverRimWidth = evaluate.getEvaluatedFloat( - 1.0, 'lighteningHoleMarginOverRimWidth', xmlElement) - self.lighteningHoleMinimumRadius = evaluate.getEvaluatedFloat( - 1.0, 'lighteningHoleMinimumRadius', xmlElement) - self.moveType = evaluate.getEvaluatedString('separate', 'moveType', xmlElement) - self.moveTypeMenuRadioStrings = 'mesh none separate vertical'.split() - self.operatingAngle = evaluate.getEvaluatedFloat(180.0, 'operatingAngle', xmlElement) - self.pinionCollarHeightOverHeight = evaluate.getEvaluatedFloat( - 0.0, 'pinionCollarHeightOverHeight', xmlElement) - self.plateClearanceOverHeight = evaluate.getEvaluatedFloat(0.2, 'plateClearanceOverHeight', xmlElement) - self.plateHeightOverHeight = evaluate.getEvaluatedFloat(0.5, 'plateHeightOverHeight', xmlElement) - self.pressureAngle = evaluate.getEvaluatedFloat(20.0, 'pressureAngle', xmlElement) - self.profileSurfaces = evaluate.getEvaluatedInt(11, 'profileSurfaces', xmlElement) - self.rackHoleBelowOverWidth = evaluate.getEvaluatedFloat(0.6, 'rackHoleBelowOverWidth', xmlElement) - self.rackHoleRadiusOverWidth = evaluate.getEvaluatedFloat(0.0, 'rackHoleRadiusOverWidth', xmlElement) - self.rackHoleStepOverWidth = evaluate.getEvaluatedFloat(1.0, 'rackHoleStepOverWidth', xmlElement) - self.rackLengthOverRadius = evaluate.getEvaluatedFloat(math.pi + math.pi, 'rackLengthOverRadius', xmlElement) - self.rackWidthOverHeight = evaluate.getEvaluatedFloat(1.0, 'rackWidthOverHeight', xmlElement) - self.rimWidthOverRadius = evaluate.getEvaluatedFloat(0.2, 'rimWidthOverRadius', xmlElement) - self.rootBevelOverClearance = evaluate.getEvaluatedFloat(0.5, 'rootBevelOverClearance', xmlElement) - self.shaftDepthBottomOverRadius = evaluate.getEvaluatedFloat(0.0, 'shaftDepthBottomOverRadius', xmlElement) - self.shaftDepthTopOverRadius = evaluate.getEvaluatedFloat(0.0, 'shaftDepthOverRadius', xmlElement) - self.shaftRadiusOverPitchRadius = evaluate.getEvaluatedFloat(0.0, 'shaftRadiusOverPitchRadius', xmlElement) - self.shaftSides = evaluate.getEvaluatedInt(4, 'shaftSides', xmlElement) - self.teethComplement = evaluate.getEvaluatedInt(17, 'teethComplement', xmlElement) - self.teethPinion = evaluate.getEvaluatedInt(7, 'teeth', xmlElement) - totalTeethOverPinionTeeth = float(self.teethComplement + self.teethPinion) / float(self.teethPinion) - self.centerDistance = evaluate.getEvaluatedFloat(20.0 * totalTeethOverPinionTeeth, 'centerDistance', xmlElement) - derivedPitchRadius = self.centerDistance / totalTeethOverPinionTeeth - self.pitchRadius = evaluate.getEvaluatedFloat(derivedPitchRadius, 'pitchRadius', xmlElement) - self.tipBevelOverClearance = evaluate.getEvaluatedFloat(0.1, 'tipBevelOverClearance', xmlElement) - self.height = evaluate.getEvaluatedFloat(10.0, 'height', xmlElement) - # tooth multiplied by 0.99999 to avoid an intersection - self.toothWidthMultiplier = evaluate.getEvaluatedFloat(0.99999, 'toothWidthMultiplier', xmlElement) - # Set derived variables. - self.wavelength = self.pitchRadius * 2.0 * math.pi / float(self.teethPinion) - self.clearance = self.wavelength * self.clearanceOverWavelength - self.clearance = evaluate.getEvaluatedFloat(self.clearance, 'clearance', xmlElement) - self.complementCollarHeight = self.height * self.complementCollarHeightOverHeight - self.complementCollarHeight = evaluate.getEvaluatedFloat(self.complementCollarHeight, 'complementCollarHeight', xmlElement) - self.gearHolePaths = evaluate.getTransformedPathsByKey([], 'gearHolePaths', xmlElement) - self.pinionCollarHeight = self.height * self.pinionCollarHeightOverHeight - self.pinionCollarHeight = evaluate.getEvaluatedFloat(self.pinionCollarHeight, 'pinionCollarHeight', xmlElement) - self.plateHeight = self.height * self.plateHeightOverHeight - self.plateHeight = evaluate.getEvaluatedFloat(self.plateHeight, 'plateHeight', xmlElement) - self.plateClearance = self.plateHeight * self.plateClearanceOverHeight - self.plateClearance = evaluate.getEvaluatedFloat(self.plateClearance, 'plateClearance', xmlElement) - self.rackLength = self.pitchRadius * self.rackLengthOverRadius - self.rackLength = evaluate.getEvaluatedFloat(self.rackLength, 'rackLength', xmlElement) - self.rackDemilength = 0.5 * self.rackLength - self.rackWidth = self.height * self.rackWidthOverHeight - self.rackWidth = evaluate.getEvaluatedFloat(self.rackWidth, 'rackWidth', xmlElement) - self.rimWidth = self.pitchRadius * self.rimWidthOverRadius - self.rimWidth = evaluate.getEvaluatedFloat(self.rimWidth, 'rimWidth', xmlElement) - self.rootBevel = self.clearance * self.rootBevelOverClearance - self.rootBevel = evaluate.getEvaluatedFloat(self.rootBevel, 'rootBevel', xmlElement) - self.shaftRadius = self.pitchRadius * self.shaftRadiusOverPitchRadius - self.shaftRadius = evaluate.getEvaluatedFloat(self.shaftRadius, 'shaftRadius', xmlElement) - self.collarWidth = self.shaftRadius * self.collarWidthOverRadius - self.collarWidth = evaluate.getEvaluatedFloat(self.collarWidth, 'collarWidth', xmlElement) - self.keywayRadius = self.shaftRadius * self.keywayRadiusOverRadius - self.keywayRadius = lineation.getFloatByPrefixBeginEnd('keywayRadius', 'keywayDiameter', self.keywayRadius, xmlElement) - self.lighteningHoleMargin = self.rimWidth * self.lighteningHoleMarginOverRimWidth - self.lighteningHoleMargin = evaluate.getEvaluatedFloat( - self.lighteningHoleMargin, 'lighteningHoleMargin', xmlElement) - self.rackHoleBelow = self.rackWidth * self.rackHoleBelowOverWidth - self.rackHoleBelow = evaluate.getEvaluatedFloat(self.rackHoleBelow, 'rackHoleBelow', xmlElement) - self.rackHoleRadius = self.rackWidth * self.rackHoleRadiusOverWidth - self.rackHoleRadius = lineation.getFloatByPrefixBeginEnd('rackHoleRadius', 'rackHoleDiameter', self.rackHoleRadius, xmlElement) - self.rackHoleStep = self.rackWidth * self.rackHoleStepOverWidth - self.rackHoleStep = evaluate.getEvaluatedFloat(self.rackHoleStep, 'rackHoleStep', xmlElement) - self.shaftDepthBottom = self.shaftRadius * self.shaftDepthBottomOverRadius - self.shaftDepthBottom = evaluate.getEvaluatedFloat(self.shaftDepthBottom, 'shaftDepthBottom', xmlElement) - self.shaftDepthTop = self.shaftRadius * self.shaftDepthTopOverRadius - self.shaftDepthTop = evaluate.getEvaluatedFloat(self.shaftDepthTop, 'shaftDepthTop', xmlElement) - self.shaftPath = evaluate.getTransformedPathByKey([], 'shaftPath', xmlElement) - if len(self.shaftPath) < 3: - self.shaftPath = shaft.getShaftPath(self.shaftDepthBottom, self.shaftDepthTop, self.shaftRadius, -self.shaftSides) - self.tipBevel = self.clearance * self.tipBevelOverClearance - self.tipBevel = evaluate.getEvaluatedFloat(self.tipBevel, 'tipBevel', xmlElement) - # Set derived values. - self.helixRadian = math.radians(self.helixAngle) - if self.teethComplement <= 0.0 and self.operatingAngle != 180.0: - print('Warning, an operatingAngle other than 180 degrees can only work with a positive number of gear teeth.') - print('Therefore the operatingAngle will be reset to 180 degrees.') - self.operatingAngle = 180.0 - self.tanHelix = math.tan(self.helixRadian) - self.helixHeight = self.tanHelix * self.height - self.operatingRadian = math.radians(self.operatingAngle) - self.pitchRadiusComplement = self.pitchRadius * float(self.teethComplement) / float(self.teethPinion) - self.pressureRadian = math.radians(self.pressureAngle) - self.cosPressure = math.cos(self.pressureRadian) - self.sinPressure = math.sin(self.pressureRadian) - self.tanPressure = math.tan(self.pressureRadian) - self.halfWavelength = 0.5 * self.wavelength - self.helixPath = euclidean.getComplexPath(evaluate.getTransformedPathByKey([], 'helixPath', xmlElement)) - if len(self.helixPath) < 1: - self.helixPath = getHelixComplexPath(self, xmlElement) - self.quarterWavelength = 0.25 * self.wavelength - self.shaftRimRadius = self.shaftRadius + self.collarWidth - self.toothProfileHalf = getToothProfileHalfCylinder(self, self.pitchRadius) - self.toothProfileHalf = getWidthMultipliedPath(self.toothProfileHalf, self.toothWidthMultiplier) - self.addendum = self.toothProfileHalf[-1].imag - self.pitchRadius - self.dedendum = abs(self.toothProfileHalf[-1]) - self.pitchRadius + self.clearance - self.pinionToothProfile = getToothProfileCylinderByProfile(self, self.pitchRadius, self.teethPinion, self.toothProfileHalf) - self.xmlElement = xmlElement - - def __repr__(self): - """Get the string representation of this GearDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/grid.py b/skeinforge/fabmetheus_utilities/geometry/creation/grid.py deleted file mode 100644 index d960af9..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/grid.py +++ /dev/null @@ -1,172 +0,0 @@ -""" -Grid path points. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_tools import path -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math -import random - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addGridRow(diameter, gridPath, loopsComplex, maximumComplex, rowIndex, x, y, zigzag): - """Add grid row.""" - row = [] - while x < maximumComplex.real: - point = complex(x, y) - if euclidean.getIsInFilledRegion(loopsComplex, point): - row.append(point) - x += diameter.real - if zigzag and rowIndex % 2 == 1: - row.reverse() - gridPath += row - -def getGeometryOutput(xmlElement): - """Get vector3 vertexes from attribute dictionary.""" - derivation = GridDerivation(xmlElement) - diameter = derivation.radius + derivation.radius - typeStringTwoCharacters = derivation.typeString.lower()[: 2] - typeStringFirstCharacter = typeStringTwoCharacters[: 1] - topRight = complex(derivation.demiwidth, derivation.demiheight) - bottomLeft = -topRight - loopsComplex = [euclidean.getSquareLoopWiddershins(bottomLeft, topRight)] - if len(derivation.target) > 0: - loopsComplex = euclidean.getComplexPaths(derivation.target) - maximumComplex = euclidean.getMaximumByComplexPaths(loopsComplex) - minimumComplex = euclidean.getMinimumByComplexPaths(loopsComplex) - gridPath = None - if typeStringTwoCharacters == 'he': - gridPath = getHexagonalGrid(diameter, loopsComplex, maximumComplex, minimumComplex, derivation.zigzag) - elif typeStringTwoCharacters == 'ra' or typeStringFirstCharacter == 'a': - gridPath = getRandomGrid(derivation, diameter, loopsComplex, maximumComplex, minimumComplex, xmlElement) - elif typeStringTwoCharacters == 're' or typeStringFirstCharacter == 'e': - gridPath = getRectangularGrid(diameter, loopsComplex, maximumComplex, minimumComplex, derivation.zigzag) - if gridPath is None: - print('Warning, the step type was not one of (hexagonal, random or rectangular) in getGeometryOutput in grid for:') - print(derivation.typeString) - print(xmlElement) - return [] - loop = euclidean.getVector3Path(gridPath) - xmlElement.attributeDictionary['closed'] = 'false' - return lineation.getGeometryOutputByLoop(lineation.SideLoop(loop, 0.5 * math.pi), xmlElement) - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get vector3 vertexes from attribute dictionary by arguments.""" - if len(arguments) < 1: - return getGeometryOutput(xmlElement) - inradius = 0.5 * euclidean.getFloatFromValue(arguments[0]) - xmlElement.attributeDictionary['inradius.x'] = str(inradius) - if len(arguments) > 1: - inradius = 0.5 * euclidean.getFloatFromValue(arguments[1]) - xmlElement.attributeDictionary['inradius.y'] = str(inradius) - return getGeometryOutput(xmlElement) - -def getHexagonalGrid(diameter, loopsComplex, maximumComplex, minimumComplex, zigzag): - """Get hexagonal grid.""" - diameter = complex(diameter.real, math.sqrt(0.75) * diameter.imag) - demiradius = 0.25 * diameter - xRadius = 0.5 * diameter.real - xStart = minimumComplex.real - demiradius.real - y = minimumComplex.imag - demiradius.imag - gridPath = [] - rowIndex = 0 - while y < maximumComplex.imag: - x = xStart - if rowIndex % 2 == 1: - x -= xRadius - addGridRow(diameter, gridPath, loopsComplex, maximumComplex, rowIndex, x, y, zigzag) - y += diameter.imag - rowIndex += 1 - return gridPath - -def getIsPointInsideZoneAwayOthers(diameterReciprocal, loopsComplex, point, pixelDictionary): - """Determine if the point is inside the loops zone and and away from the other points.""" - if not euclidean.getIsInFilledRegion(loopsComplex, point): - return False - pointOverDiameter = complex(point.real * diameterReciprocal.real, point.imag * diameterReciprocal.imag) - squareValues = euclidean.getSquareValuesFromPoint(pixelDictionary, pointOverDiameter) - for squareValue in squareValues: - if abs(squareValue - pointOverDiameter) < 1.0: - return False - euclidean.addElementToPixelListFromPoint(pointOverDiameter, pixelDictionary, pointOverDiameter) - return True - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return GridDerivation(xmlElement) - -def getRandomGrid(derivation, diameter, loopsComplex, maximumComplex, minimumComplex, xmlElement): - """Get rectangular grid.""" - gridPath = [] - diameterReciprocal = complex(1.0 / diameter.real, 1.0 / diameter.imag) - diameterSquared = diameter.real * diameter.real + diameter.imag * diameter.imag - elements = int(math.ceil(derivation.packingDensity * euclidean.getAreaLoops(loopsComplex) / diameterSquared / math.sqrt(0.75))) - elements = evaluate.getEvaluatedInt(elements, 'elements', xmlElement) - failedPlacementAttempts = 0 - pixelDictionary = {} - if derivation.seed is not None: - random.seed(derivation.seed) - successfulPlacementAttempts = 0 - while failedPlacementAttempts < 100: - point = euclidean.getRandomComplex(minimumComplex, maximumComplex) - if getIsPointInsideZoneAwayOthers(diameterReciprocal, loopsComplex, point, pixelDictionary): - gridPath.append(point) - euclidean.addElementToPixelListFromPoint(point, pixelDictionary, point) - successfulPlacementAttempts += 1 - else: - failedPlacementAttempts += 1 - if successfulPlacementAttempts >= elements: - return gridPath - return gridPath - -def getRectangularGrid(diameter, loopsComplex, maximumComplex, minimumComplex, zigzag): - """Get rectangular grid.""" - demiradius = 0.25 * diameter - xStart = minimumComplex.real - demiradius.real - y = minimumComplex.imag - demiradius.imag - gridPath = [] - rowIndex = 0 - while y < maximumComplex.imag: - addGridRow(diameter, gridPath, loopsComplex, maximumComplex, rowIndex, xStart, y, zigzag) - y += diameter.imag - rowIndex += 1 - return gridPath - -def processXMLElement(xmlElement): - """Process the xml element.""" - path.convertXMLElement(getGeometryOutput(xmlElement), xmlElement) - - -class GridDerivation: - """Class to hold grid variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.inradius = lineation.getComplexByPrefixes(['demisize', 'inradius'], complex(10.0, 10.0), xmlElement) - self.inradius = lineation.getComplexByMultiplierPrefix(2.0, 'size', self.inradius, xmlElement) - self.demiwidth = lineation.getFloatByPrefixBeginEnd('demiwidth', 'width', self.inradius.real, xmlElement) - self.demiheight = lineation.getFloatByPrefixBeginEnd('demiheight', 'height', self.inradius.imag, xmlElement) - self.packingDensity = evaluate.getEvaluatedFloatByKeys(0.2, ['packingDensity', 'density'], xmlElement) - self.radius = lineation.getComplexByPrefixBeginEnd('elementRadius', 'elementDiameter', complex(1.0, 1.0), xmlElement) - self.radius = lineation.getComplexByPrefixBeginEnd('radius', 'diameter', self.radius, xmlElement) - self.seed = evaluate.getEvaluatedInt(None, 'seed', xmlElement) - self.target = evaluate.getTransformedPathsByKey([], 'target', xmlElement) - self.typeMenuRadioStrings = 'hexagonal random rectangular'.split() - self.typeString = evaluate.getEvaluatedString('rectangular', 'type', xmlElement) - self.zigzag = evaluate.getEvaluatedBoolean(True, 'zigzag', xmlElement) - - def __repr__(self): - """Get the string representation of this GridDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/heightmap.py b/skeinforge/fabmetheus_utilities/geometry/creation/heightmap.py deleted file mode 100644 index d753f67..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/heightmap.py +++ /dev/null @@ -1,210 +0,0 @@ -""" -Heightmap. -http://www.cs.otago.ac.nz/graphics/Mirage/node59.html -http://en.wikipedia.org/wiki/Heightmap -http://en.wikipedia.org/wiki/Netpbm_format - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.geometry_tools import path -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities.vector3index import Vector3Index -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -import math -import random - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addHeightsByBitmap(heights, textLines): - """Add heights by bitmap.""" - for line in textLines[3:]: - for integerWord in line.split(): - heights.append(float(integerWord)) - -def addHeightsByGraymap(heights, textLines): - """Add heights by graymap.""" - divisor = float(textLines[3]) - for line in textLines[4:]: - for integerWord in line.split(): - heights.append(float(integerWord) / divisor) - -def getAddIndexedHeightGrid(heightGrid, minimumXY, step, top, vertexes): - """Get and add an indexed heightGrid.""" - indexedHeightGrid = [] - for rowIndex, row in enumerate(heightGrid): - indexedRow = [] - indexedHeightGrid.append(indexedRow) - rowOffset = step.imag * float(rowIndex) + minimumXY.imag - for columnIndex, element in enumerate(row): - columnOffset = step.real * float(columnIndex) + minimumXY.real - vector3index = Vector3Index(len(vertexes), columnOffset, rowOffset, top * element) - indexedRow.append(vector3index) - vertexes.append(vector3index) - return indexedHeightGrid - -def getAddIndexedSegmentedPerimeter(heightGrid, maximumXY, minimumXY, step, vertexes, z=0.0): - """Get and add an indexed segmented perimeter.""" - indexedSegmentedPerimeter = [] - firstRow = heightGrid[0] - columnOffset = minimumXY.real - numberOfRowsMinusTwo = len(heightGrid) - 2 - for column in firstRow: - vector3index = Vector3Index(len(vertexes), columnOffset, minimumXY.imag, z) - vertexes.append(vector3index) - indexedSegmentedPerimeter.append(vector3index) - columnOffset += step.real - rowOffset = minimumXY.imag - for rowIndex in xrange(numberOfRowsMinusTwo): - rowOffset += step.imag - vector3index = Vector3Index(len(vertexes), maximumXY.real, rowOffset, z) - vertexes.append(vector3index) - indexedSegmentedPerimeter.append(vector3index) - columnOffset = maximumXY.real - for column in firstRow: - vector3index = Vector3Index(len(vertexes), columnOffset, maximumXY.imag, z) - vertexes.append(vector3index) - indexedSegmentedPerimeter.append(vector3index) - columnOffset -= step.real - rowOffset = maximumXY.imag - for rowIndex in xrange(numberOfRowsMinusTwo): - rowOffset -= step.imag - vector3index = Vector3Index(len(vertexes), minimumXY.real, rowOffset, z) - vertexes.append(vector3index) - indexedSegmentedPerimeter.append(vector3index) - return indexedSegmentedPerimeter - -def getGeometryOutput(xmlElement): - """Get vector3 vertexes from attribute dictionary.""" - derivation = HeightmapDerivation(xmlElement) - heightGrid = derivation.heightGrid - if derivation.fileName != '': - heightGrid = getHeightGrid(archive.getAbsoluteFolderPath(xmlElement.getParser().fileName, derivation.fileName)) - return getGeometryOutputByHeightGrid(derivation, heightGrid, xmlElement) - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get vector3 vertexes from attribute dictionary by arguments.""" - evaluate.setAttributeDictionaryByArguments(['file', 'start'], arguments, xmlElement) - return getGeometryOutput(xmlElement) - -def getGeometryOutputByHeightGrid(derivation, heightGrid, xmlElement): - """Get vector3 vertexes from attribute dictionary.""" - numberOfColumns = len(heightGrid) - if numberOfColumns < 2: - print('Warning, in getGeometryOutputByHeightGrid in heightmap there are fewer than two rows for:') - print(heightGrid) - print(xmlElement) - return None - numberOfRows = len(heightGrid[0]) - if numberOfRows < 2: - print('Warning, in getGeometryOutputByHeightGrid in heightmap there are fewer than two columns for:') - print(heightGrid) - print(xmlElement) - return None - for row in heightGrid: - if len(row) != numberOfRows: - print('Warning, in getGeometryOutputByHeightGrid in heightmap the heightgrid is not rectangular for:') - print(heightGrid) - print(xmlElement) - return None - inradiusComplex = derivation.inradius.dropAxis() - minimumXY = -inradiusComplex - step = complex(derivation.inradius.x / float(numberOfRows - 1), derivation.inradius.y / float(numberOfColumns - 1)) - step += step - faces = [] - heightGrid = getRaisedHeightGrid(heightGrid, derivation.start) - top = derivation.inradius.z + derivation.inradius.z - vertexes = [] - indexedBottomLoop = getAddIndexedSegmentedPerimeter(heightGrid, inradiusComplex, minimumXY, step, vertexes) - indexedLoops = [indexedBottomLoop] - indexedGridTop = getAddIndexedHeightGrid(heightGrid, minimumXY, step, top, vertexes) - indexedLoops.append(triangle_mesh.getIndexedLoopFromIndexedGrid(indexedGridTop)) - vertexes = triangle_mesh.getUniqueVertexes(indexedLoops + indexedGridTop) - triangle_mesh.addPillarFromConvexLoopsGridTop(faces, indexedGridTop, indexedLoops) - return triangle_mesh.getGeometryOutputByFacesVertexes(faces, vertexes) - -def getHeightGrid(fileName): - """Get heightGrid by fileName.""" - if 'models/' not in fileName: - print('Warning, models/ was not in the absolute file path, so for security nothing will be done for:') - print(xmlElement) - print('For which the absolute file path is:') - print(fileName) - print('The heightmap tool can only read a file which has models/ in the file path.') - print('To import the file, move the file into a folder called model/ or a subfolder which is inside the model folder tree.') - return - pgmText = archive.getFileText(fileName) - textLines = archive.getTextLines(pgmText) - format = textLines[0].lower() - sizeWords = textLines[2].split() - numberOfColumns = int(sizeWords[0]) - numberOfRows = int(sizeWords[1]) - heights = [] - if format == 'p1': - addHeightsByBitmap(heights, textLines) - elif format == 'p2': - addHeightsByGraymap(heights, textLines) - else: - print('Warning, the file format was not recognized for:') - print(fileName) - print('Heightmap can only read the Netpbm Portable bitmap format and the Netpbm Portable graymap format.') - print('The Netpbm formats are described at:') - print('http://en.wikipedia.org/wiki/Netpbm_format') - return [] - heightGrid = [] - heightIndex = 0 - for rowIndex in xrange(numberOfRows): - row = [] - heightGrid.append(row) - for columnIndex in xrange(numberOfColumns): - row.append(heights[heightIndex]) - heightIndex += 1 - return heightGrid - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return HeightmapDerivation(xmlElement) - -def getRaisedHeightGrid(heightGrid, start): - """Get heightGrid raised above start.""" - raisedHeightGrid = [] - remainingHeight = 1.0 - start - for row in heightGrid: - raisedRow = [] - raisedHeightGrid.append(raisedRow) - for element in row: - raisedElement = remainingHeight * element + start - raisedRow.append(raisedElement) - return raisedHeightGrid - -def processXMLElement(xmlElement): - """Process the xml element.""" - solid.processXMLElementByGeometry(getGeometryOutput(xmlElement), xmlElement) - - -class HeightmapDerivation: - """Class to hold heightmap variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.fileName = evaluate.getEvaluatedString('', 'file', xmlElement) - self.heightGrid = evaluate.getEvaluatedValue([], 'heightGrid', xmlElement) - self.inradius = evaluate.getVector3ByPrefixes(['demisize', 'inradius'], Vector3(10.0, 10.0, 5.0), xmlElement) - self.inradius = evaluate.getVector3ByMultiplierPrefix(2.0, 'size', self.inradius, xmlElement) - self.start = evaluate.getEvaluatedFloat(0.0, 'start', xmlElement) - - def __repr__(self): - """Get the string representation of this HeightmapDerivation.""" - return euclidean.getDictionaryString(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/lathe.py b/skeinforge/fabmetheus_utilities/geometry/creation/lathe.py deleted file mode 100644 index 3442c0a..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/lathe.py +++ /dev/null @@ -1,180 +0,0 @@ -""" -Boolean geometry extrusion. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - -def addLoopByComplex(derivation, endMultiplier, loopLists, path, pointComplex, vertexes): - """Add an indexed loop to the vertexes.""" - loops = loopLists[-1] - loop = [] - loops.append(loop) - for point in path: - pointMinusBegin = point - derivation.axisStart - dotVector3 = derivation.axisProjectiveSpace.getDotVector3(pointMinusBegin) - dotVector3Complex = dotVector3.dropAxis() - dotPointComplex = pointComplex * dotVector3Complex - dotPoint = Vector3(dotPointComplex.real, dotPointComplex.imag, dotVector3.z) - projectedVector3 = derivation.axisProjectiveSpace.getVector3ByPoint(dotPoint) + derivation.axisStart - loop.append(projectedVector3) - -def addNegatives(derivation, negatives, paths): - """Add pillars output to negatives.""" - for path in paths: - loopListsByPath = getLoopListsByPath(derivation, 1.000001, path) - geometryOutput = triangle_mesh.getPillarsOutput(loopListsByPath) - negatives.append(geometryOutput) - -def addNegativesPositives(derivation, negatives, paths, positives): - """Add pillars output to negatives and positives.""" - for path in paths: - endMultiplier = None - normal = euclidean.getNormalByPath(path) - if normal.dot(derivation.normal) < 0.0: - endMultiplier = 1.000001 - loopListsByPath = getLoopListsByPath(derivation, endMultiplier, path) - geometryOutput = triangle_mesh.getPillarsOutput(loopListsByPath) - if endMultiplier is None: - positives.append(geometryOutput) - else: - negatives.append(geometryOutput) - -def addOffsetAddToLists( loop, offset, vector3Index, vertexes ): - """Add an indexed loop to the vertexes.""" - vector3Index += offset - loop.append( vector3Index ) - vertexes.append( vector3Index ) - -def addPositives(derivation, paths, positives): - """Add pillars output to positives.""" - for path in paths: - loopListsByPath = getLoopListsByPath(derivation, None, path) - geometryOutput = triangle_mesh.getPillarsOutput(loopListsByPath) - positives.append(geometryOutput) - -def getGeometryOutput(derivation, xmlElement): - """Get triangle mesh from attribute dictionary.""" - if derivation is None: - derivation = LatheDerivation(xmlElement) - if len(euclidean.getConcatenatedList(derivation.target)) == 0: - print('Warning, in lathe there are no paths.') - print(xmlElement.attributeDictionary) - return None - negatives = [] - positives = [] - addNegativesPositives(derivation, negatives, derivation.target, positives) - return getGeometryOutputByNegativesPositives(derivation, negatives, positives, xmlElement) - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get triangle mesh from attribute dictionary by arguments.""" - return getGeometryOutput(None, xmlElement) - -def getGeometryOutputByNegativesPositives(derivation, negatives, positives, xmlElement): - """Get triangle mesh from derivation, negatives, positives and xmlElement.""" - positiveOutput = triangle_mesh.getUnifiedOutput(positives) - if len(negatives) < 1: - return solid.getGeometryOutputByManipulation(positiveOutput, xmlElement) - return solid.getGeometryOutputByManipulation({'difference' : {'shapes' : [positiveOutput] + negatives}}, xmlElement) - -def getLoopListsByPath(derivation, endMultiplier, path): - """Get loop lists from path.""" - vertexes = [] - loopLists = [[]] - if len(derivation.loop) < 2: - return loopLists - for pointIndex, pointComplex in enumerate(derivation.loop): - if endMultiplier is not None and not derivation.isEndCloseToStart: - if pointIndex == 0: - nextPoint = derivation.loop[1] - pointComplex = endMultiplier * (pointComplex - nextPoint) + nextPoint - elif pointIndex == len(derivation.loop) - 1: - previousPoint = derivation.loop[pointIndex - 1] - pointComplex = endMultiplier * (pointComplex - previousPoint) + previousPoint - addLoopByComplex(derivation, endMultiplier, loopLists, path, pointComplex, vertexes) - if derivation.isEndCloseToStart: - loopLists[-1].append([]) - return loopLists - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return LatheDerivation(xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - solid.processXMLElementByGeometry(getGeometryOutput(None, xmlElement), xmlElement) - - -class LatheDerivation: - """Class to hold lathe variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.axisEnd = evaluate.getVector3ByPrefix(None, 'axisEnd', xmlElement) - self.axisStart = evaluate.getVector3ByPrefix(None, 'axisStart', xmlElement) - self.end = evaluate.getEvaluatedFloat(360.0, 'end', xmlElement) - self.loop = evaluate.getTransformedPathByKey([], 'loop', xmlElement) - self.sides = evaluate.getEvaluatedInt(None, 'sides', xmlElement) - self.start = evaluate.getEvaluatedFloat(0.0, 'start', xmlElement) - self.target = evaluate.getTransformedPathsByKey([], 'target', xmlElement) - if len(self.target) < 1: - print('Warning, no target in derive in lathe for:') - print(xmlElement) - return - firstPath = self.target[0] - if len(firstPath) < 3: - print('Warning, firstPath length is less than three in derive in lathe for:') - print(xmlElement) - self.target = [] - return - if self.axisStart is None: - if self.axisEnd is None: - self.axisStart = firstPath[0] - self.axisEnd = firstPath[-1] - else: - self.axisStart = Vector3() - self.axis = self.axisEnd - self.axisStart - axisLength = abs(self.axis) - if axisLength <= 0.0: - print('Warning, axisLength is zero in derive in lathe for:') - print(xmlElement) - self.target = [] - return - self.axis /= axisLength - firstVector3 = firstPath[1] - self.axisStart - firstVector3Length = abs(firstVector3) - if firstVector3Length <= 0.0: - print('Warning, firstVector3Length is zero in derive in lathe for:') - print(xmlElement) - self.target = [] - return - firstVector3 /= firstVector3Length - self.axisProjectiveSpace = euclidean.ProjectiveSpace().getByBasisZFirst(self.axis, firstVector3) - if self.sides is None: - distanceToLine = euclidean.getDistanceToLineByPaths(self.axisStart, self.axisEnd, self.target) - self.sides = evaluate.getSidesMinimumThreeBasedOnPrecisionSides(distanceToLine, xmlElement) - endRadian = math.radians(self.end) - startRadian = math.radians(self.start) - self.isEndCloseToStart = euclidean.getIsRadianClose(endRadian, startRadian) - if len(self.loop) < 1: - self.loop = euclidean.getComplexPolygonByStartEnd(endRadian, 1.0, self.sides, startRadian) - self.normal = euclidean.getNormalByPath(firstPath) - - def __repr__(self): - """Get the string representation of this LatheDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/line.py b/skeinforge/fabmetheus_utilities/geometry/creation/line.py deleted file mode 100644 index cca046e..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/line.py +++ /dev/null @@ -1,108 +0,0 @@ -""" -Square path. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_tools import path -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getGeometryOutput(derivation, xmlElement): - """Get vector3 vertexes from attribute dictionary.""" - if derivation is None: - derivation = LineDerivation(xmlElement) - endMinusStart = derivation.end - derivation.start - endMinusStartLength = abs(endMinusStart) - if endMinusStartLength <= 0.0: - print('Warning, end is the same as start in getGeometryOutput in line for:') - print(derivation.start) - print(derivation.end) - print(xmlElement) - return None - typeStringTwoCharacters = derivation.typeString.lower()[: 2] - xmlElement.attributeDictionary['closed'] = str(derivation.closed) - if derivation.step is None and derivation.steps is None: - return lineation.getGeometryOutputByLoop(lineation.SideLoop([derivation.start, derivation.end]), xmlElement) - loop = [derivation.start] - if derivation.step is not None and derivation.steps is not None: - stepVector = derivation.step / endMinusStartLength * endMinusStart - derivation.end = derivation.start + stepVector * derivation.steps - return getGeometryOutputByStep(derivation.end, loop, derivation.steps, stepVector, xmlElement) - if derivation.step is None: - stepVector = endMinusStart / derivation.steps - return getGeometryOutputByStep(derivation.end, loop, derivation.steps, stepVector, xmlElement) - endMinusStartLengthOverStep = endMinusStartLength / derivation.step - if typeStringTwoCharacters == 'av': - derivation.steps = max(1.0, round(endMinusStartLengthOverStep)) - stepVector = derivation.step / endMinusStartLength * endMinusStart - derivation.end = derivation.start + stepVector * derivation.steps - return getGeometryOutputByStep(derivation.end, loop, derivation.steps, stepVector, xmlElement) - if typeStringTwoCharacters == 'ma': - derivation.steps = math.ceil(endMinusStartLengthOverStep) - if derivation.steps < 1.0: - return lineation.getGeometryOutputByLoop(lineation.SideLoop([derivation.start, derivation.end]), xmlElement) - stepVector = endMinusStart / derivation.steps - return getGeometryOutputByStep(derivation.end, loop, derivation.steps, stepVector, xmlElement) - if typeStringTwoCharacters == 'mi': - derivation.steps = math.floor(endMinusStartLengthOverStep) - if derivation.steps < 1.0: - return lineation.getGeometryOutputByLoop(lineation.SideLoop(loop), xmlElement) - stepVector = endMinusStart / derivation.steps - return getGeometryOutputByStep(derivation.end, loop, derivation.steps, stepVector, xmlElement) - print('Warning, the step type was not one of (average, maximum or minimum) in getGeometryOutput in line for:') - print(derivation.typeString) - print(xmlElement) - loop.append(derivation.end) - return lineation.getGeometryOutputByLoop(lineation.SideLoop(loop), xmlElement) - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get vector3 vertexes from attribute dictionary by arguments.""" - evaluate.setAttributeDictionaryByArguments(['start', 'end', 'step'], arguments, xmlElement) - return getGeometryOutput(None, xmlElement) - -def getGeometryOutputByStep(end, loop, steps, stepVector, xmlElement): - """Get line geometry output by the end, loop, steps and stepVector.""" - stepsFloor = int(math.floor(abs(steps))) - for stepIndex in xrange(1, stepsFloor): - loop.append(loop[stepIndex - 1] + stepVector) - loop.append(end) - return lineation.getGeometryOutputByLoop(lineation.SideLoop(loop), xmlElement) - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return LineDerivation(xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - path.convertXMLElement(getGeometryOutput(None, xmlElement), xmlElement) - - -class LineDerivation: - """Class to hold line variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.closed = evaluate.getEvaluatedBoolean(False, 'closed', xmlElement) - self.end = evaluate.getVector3ByPrefix(Vector3(), 'end', xmlElement) - self.start = evaluate.getVector3ByPrefix(Vector3(), 'start', xmlElement) - self.step = evaluate.getEvaluatedFloat(None, 'step', xmlElement) - self.steps = evaluate.getEvaluatedFloat(None, 'steps', xmlElement) - self.typeMenuRadioStrings = 'average maximum minimum'.split() - self.typeString = evaluate.getEvaluatedString('minimum', 'type', xmlElement) - - def __repr__(self): - """Get the string representation of this LineDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/linear_bearing_cage.py b/skeinforge/fabmetheus_utilities/geometry/creation/linear_bearing_cage.py deleted file mode 100644 index a51f00d..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/linear_bearing_cage.py +++ /dev/null @@ -1,245 +0,0 @@ -""" -Linear bearing cage. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import extrude -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.creation import peg -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.geometry.manipulation_matrix import translate -from fabmetheus_utilities.geometry.solids import cylinder -from fabmetheus_utilities.geometry.solids import sphere -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addAssemblyCage(derivation, negatives, positives): - """Add assembly linear bearing cage.""" - addCageGroove(derivation, negatives, positives) - for pegCenterX in derivation.pegCenterXs: - addPositivePeg(derivation, positives, pegCenterX, -derivation.pegY) - addPositivePeg(derivation, positives, pegCenterX, derivation.pegY) - translate.translateNegativesPositives(negatives, positives, Vector3(0.0, -derivation.halfSeparationWidth)) - femaleNegatives = [] - femalePositives = [] - addCageGroove(derivation, femaleNegatives, femalePositives) - for pegCenterX in derivation.pegCenterXs: - addNegativePeg(derivation, femaleNegatives, pegCenterX, -derivation.pegY) - addNegativePeg(derivation, femaleNegatives, pegCenterX, derivation.pegY) - translate.translateNegativesPositives(femaleNegatives, femalePositives, Vector3(0.0, derivation.halfSeparationWidth)) - negatives += femaleNegatives - positives += femalePositives - -def addCage(derivation, height, negatives, positives): - """Add linear bearing cage.""" - copyShallow = derivation.xmlElement.getCopyShallow() - copyShallow.attributeDictionary['path'] = [Vector3(), Vector3(0.0, 0.0, height)] - extrudeDerivation = extrude.ExtrudeDerivation(copyShallow) - roundedExtendedRectangle = getRoundedExtendedRectangle(derivation.demiwidth, derivation.rectangleCenterX, 14) - outsidePath = euclidean.getVector3Path(roundedExtendedRectangle) - extrude.addPositives(extrudeDerivation, [outsidePath], positives) - for bearingCenterX in derivation.bearingCenterXs: - addNegativeSphere(derivation, negatives, bearingCenterX) - -def addCageGroove(derivation, negatives, positives): - """Add cage and groove.""" - addCage(derivation, derivation.demiheight, negatives, positives) - addGroove(derivation, negatives) - -def addGroove(derivation, negatives): - """Add groove on each side of cage.""" - bottom = derivation.demiheight - 0.5 * derivation.grooveWidth - outside = 1.0001 * derivation.demiwidth - top = derivation.demiheight - leftGroove = [ - complex(-outside, top), - complex(-derivation.innerDemiwidth, derivation.demiheight), - complex(-outside, bottom)] - rightGroove = [ - complex(outside, bottom), - complex(derivation.innerDemiwidth, derivation.demiheight), - complex(outside, top)] - extrude.addSymmetricXPaths(negatives, [leftGroove, rightGroove], derivation.demilength) - -def addNegativePeg(derivation, negatives, x, y): - """Add negative cylinder at x and y.""" - negativePegRadius = derivation.pegRadius + derivation.halfPegClearance - inradius = complex(negativePegRadius, negativePegRadius) - copyShallow = derivation.xmlElement.getCopyShallow() - start = Vector3(x, y, derivation.height) - sides = evaluate.getSidesMinimumThreeBasedOnPrecision(negativePegRadius, copyShallow ) - cylinder.addCylinderOutputByEndStart(0.0, inradius, negatives, sides, start, derivation.topOverBottom) - -def addNegativeSphere(derivation, negatives, x): - """Add negative sphere at x.""" - radius = Vector3(derivation.radiusPlusClearance, derivation.radiusPlusClearance, derivation.radiusPlusClearance) - sphereOutput = sphere.getGeometryOutput(radius, derivation.xmlElement.getCopyShallow()) - euclidean.translateVector3Path(matrix.getVertexes(sphereOutput), Vector3(x, 0.0, derivation.demiheight)) - negatives.append(sphereOutput) - -def addPositivePeg(derivation, positives, x, y): - """Add positive cylinder at x and y.""" - positivePegRadius = derivation.pegRadius - derivation.halfPegClearance - radius = complex(positivePegRadius, positivePegRadius) - copyShallow = derivation.xmlElement.getCopyShallow() - start = Vector3(x, y, derivation.demiheight) - endZ = derivation.height - peg.addPegOutput(derivation.pegBevel, endZ, positives, radius, start, derivation.topOverBottom, copyShallow) - -def getBearingCenterXs(bearingCenterX, numberOfSteps, stepX): - """Get the bearing center x list.""" - bearingCenterXs = [] - for stepIndex in xrange(numberOfSteps + 1): - bearingCenterXs.append(bearingCenterX) - bearingCenterX += stepX - return bearingCenterXs - -def getGeometryOutput(xmlElement): - """Get vector3 vertexes from attribute dictionary.""" - derivation = LinearBearingCageDerivation(xmlElement) - negatives = [] - positives = [] - if derivation.typeStringFirstCharacter == 'a': - addAssemblyCage(derivation, negatives, positives) - else: - addCage(derivation, derivation.height, negatives, positives) - return extrude.getGeometryOutputByNegativesPositives(negatives, positives, xmlElement) - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get vector3 vertexes from attribute dictionary by arguments.""" - evaluate.setAttributeDictionaryByArguments(['length', 'radius'], arguments, xmlElement) - return getGeometryOutput(xmlElement) - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return LinearBearingCageDerivation(xmlElement) - -def getPegCenterXs(numberOfSteps, pegCenterX, stepX): - """Get the peg center x list.""" - pegCenterXs = [] - for stepIndex in xrange(numberOfSteps): - pegCenterXs.append(pegCenterX) - pegCenterX += stepX - return pegCenterXs - -def getRoundedExtendedRectangle(radius, rectangleCenterX, sides): - """Get the rounded extended rectangle.""" - roundedExtendedRectangle = [] - halfSides = int(sides / 2) - halfSidesPlusOne = abs(halfSides + 1) - sideAngle = math.pi / float(halfSides) - extensionMultiplier = 1.0 / math.cos(0.5 * sideAngle) - center = complex(rectangleCenterX, 0.0) - startAngle = 0.5 * math.pi - for halfSide in xrange(halfSidesPlusOne): - unitPolar = euclidean.getWiddershinsUnitPolar(startAngle) - unitPolarExtended = complex(unitPolar.real * extensionMultiplier, unitPolar.imag) - roundedExtendedRectangle.append(unitPolarExtended * radius + center) - startAngle += sideAngle - center = complex(-rectangleCenterX, 0.0) - startAngle = -0.5 * math.pi - for halfSide in xrange(halfSidesPlusOne): - unitPolar = euclidean.getWiddershinsUnitPolar(startAngle) - unitPolarExtended = complex(unitPolar.real * extensionMultiplier, unitPolar.imag) - roundedExtendedRectangle.append(unitPolarExtended * radius + center) - startAngle += sideAngle - return roundedExtendedRectangle - -def processXMLElement(xmlElement): - """Process the xml element.""" - solid.processXMLElementByGeometry(getGeometryOutput(xmlElement), xmlElement) - - -class LinearBearingCageDerivation: - """Class to hold linear bearing cage variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.length = evaluate.getEvaluatedFloat(50.0, 'length', xmlElement) - self.demilength = 0.5 * self.length - self.radius = lineation.getFloatByPrefixBeginEnd('radius', 'diameter', 5.0, xmlElement) - self.cageClearanceOverRadius = evaluate.getEvaluatedFloat(0.05, 'cageClearanceOverRadius', xmlElement) - self.cageClearance = self.cageClearanceOverRadius * self.radius - self.cageClearance = evaluate.getEvaluatedFloat(self.cageClearance, 'cageClearance', xmlElement) - self.racewayClearanceOverRadius = evaluate.getEvaluatedFloat(0.1, 'racewayClearanceOverRadius', xmlElement) - self.racewayClearance = self.racewayClearanceOverRadius * self.radius - self.racewayClearance = evaluate.getEvaluatedFloat(self.racewayClearance, 'racewayClearance', xmlElement) - self.typeMenuRadioStrings = 'assembly integral'.split() - self.typeString = evaluate.getEvaluatedString('assembly', 'type', xmlElement) - self.typeStringFirstCharacter = self.typeString[: 1 ].lower() - self.wallThicknessOverRadius = evaluate.getEvaluatedFloat(0.5, 'wallThicknessOverRadius', xmlElement) - self.wallThickness = self.wallThicknessOverRadius * self.radius - self.wallThickness = evaluate.getEvaluatedFloat(self.wallThickness, 'wallThickness', xmlElement) - self.zenithAngle = evaluate.getEvaluatedFloat(45.0, 'zenithAngle', xmlElement) - self.zenithRadian = math.radians(self.zenithAngle) - self.demiheight = self.radius * math.cos(self.zenithRadian) - self.racewayClearance - self.height = self.demiheight + self.demiheight - self.radiusPlusClearance = self.radius + self.cageClearance - self.cageRadius = self.radiusPlusClearance + self.wallThickness - self.demiwidth = self.cageRadius - self.bearingCenterX = self.cageRadius - self.demilength - separation = self.cageRadius + self.radiusPlusClearance - bearingLength = -self.bearingCenterX - self.bearingCenterX - self.numberOfSteps = int(math.floor(bearingLength / separation)) - self.stepX = bearingLength / float(self.numberOfSteps) - self.bearingCenterXs = getBearingCenterXs(self.bearingCenterX, self.numberOfSteps, self.stepX) - self.xmlElement = xmlElement - if self.typeStringFirstCharacter == 'a': - self.setAssemblyCage() - self.rectangleCenterX = self.demiwidth - self.demilength - - def __repr__(self): - """Get the string representation of this LinearBearingCageDerivation.""" - return str(self.__dict__) - - def setAssemblyCage(self): - """Set two piece assembly parameters.""" - self.grooveDepthOverRadius = evaluate.getEvaluatedFloat(0.15, 'grooveDepthOverRadius', self.xmlElement) - self.grooveDepth = self.grooveDepthOverRadius * self.radius - self.grooveDepth = evaluate.getEvaluatedFloat(self.grooveDepth, 'grooveDepth', self.xmlElement) - self.grooveWidthOverRadius = evaluate.getEvaluatedFloat(0.6, 'grooveWidthOverRadius', self.xmlElement) - self.grooveWidth = self.grooveWidthOverRadius * self.radius - self.grooveWidth = evaluate.getEvaluatedFloat(self.grooveWidth, 'grooveWidth', self.xmlElement) - self.pegClearanceOverRadius = evaluate.getEvaluatedFloat(0.0, 'pegClearanceOverRadius', self.xmlElement) - self.pegClearance = self.pegClearanceOverRadius * self.radius - self.pegClearance = evaluate.getEvaluatedFloat(self.pegClearance, 'pegClearance', self.xmlElement) - self.halfPegClearance = 0.5 * self.pegClearance - self.pegRadiusOverRadius = evaluate.getEvaluatedFloat(0.5, 'pegRadiusOverRadius', self.xmlElement) - self.pegRadius = self.pegRadiusOverRadius * self.radius - self.pegRadius = evaluate.getEvaluatedFloat(self.pegRadius, 'pegRadius', self.xmlElement) - self.pegBevelOverPegRadius = evaluate.getEvaluatedFloat(0.25, 'pegBevelOverPegRadius', self.xmlElement) - self.pegBevel = self.pegBevelOverPegRadius * self.pegRadius - self.pegBevel = evaluate.getEvaluatedFloat(self.pegBevel, 'pegBevel', self.xmlElement) - self.pegMaximumRadius = self.pegRadius + abs(self.halfPegClearance) - self.separationOverRadius = evaluate.getEvaluatedFloat(0.5, 'separationOverRadius', self.xmlElement) - self.separation = self.separationOverRadius * self.radius - self.separation = evaluate.getEvaluatedFloat(self.separation, 'separation', self.xmlElement) - self.topOverBottom = evaluate.getEvaluatedFloat(0.8, 'topOverBottom', self.xmlElement) - self.quarterHeight = 0.5 * self.demiheight - self.pegY = 0.5 * self.wallThickness + self.pegMaximumRadius - cagePegRadius = self.cageRadius + self.pegMaximumRadius - halfStepX = 0.5 * self.stepX - pegHypotenuse = math.sqrt(self.pegY * self.pegY + halfStepX * halfStepX) - if cagePegRadius > pegHypotenuse: - self.pegY = math.sqrt(cagePegRadius * cagePegRadius - halfStepX * halfStepX) - self.demiwidth = max(self.pegY + self.pegMaximumRadius + self.wallThickness, self.demiwidth) - self.innerDemiwidth = self.demiwidth - self.demiwidth += self.grooveDepth - self.halfSeparationWidth = self.demiwidth + 0.5 * self.separation - if self.pegRadius <= 0.0: - self.pegCenterXs = [] - else: - self.pegCenterXs = getPegCenterXs(self.numberOfSteps, self.bearingCenterX + halfStepX, self.stepX) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/lineation.py b/skeinforge/fabmetheus_utilities/geometry/creation/lineation.py deleted file mode 100644 index 286165d..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/lineation.py +++ /dev/null @@ -1,307 +0,0 @@ -""" -Polygon path. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_tools import path -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getComplexByDictionary(dictionary, valueComplex): - """Get complex by dictionary.""" - if 'x' in dictionary: - valueComplex = complex(euclidean.getFloatFromValue(dictionary['x']),valueComplex.imag) - if 'y' in dictionary: - valueComplex = complex(valueComplex.real, euclidean.getFloatFromValue(dictionary['y'])) - return valueComplex - -def getComplexByDictionaryListValue(value, valueComplex): - """Get complex by dictionary, list or value.""" - if value.__class__ == complex: - return value - if value.__class__ == dict: - return getComplexByDictionary(value, valueComplex) - if value.__class__ == list: - return getComplexByFloatList(value, valueComplex) - floatFromValue = euclidean.getFloatFromValue(value) - if floatFromValue is None: - return valueComplex - return complex( floatFromValue, floatFromValue ) - -def getComplexByFloatList( floatList, valueComplex ): - """Get complex by float list.""" - if len(floatList) > 0: - valueComplex = complex(euclidean.getFloatFromValue(floatList[0]), valueComplex.imag) - if len(floatList) > 1: - valueComplex = complex(valueComplex.real, euclidean.getFloatFromValue(floatList[1])) - return valueComplex - -def getComplexByMultiplierPrefix( multiplier, prefix, valueComplex, xmlElement ): - """Get complex from multiplier, prefix and xml element.""" - if multiplier == 0.0: - return valueComplex - oldMultipliedValueComplex = valueComplex * multiplier - complexByPrefix = getComplexByPrefix( prefix, oldMultipliedValueComplex, xmlElement ) - if complexByPrefix == oldMultipliedValueComplex: - return valueComplex - return complexByPrefix / multiplier - -def getComplexByMultiplierPrefixes( multiplier, prefixes, valueComplex, xmlElement ): - """Get complex from multiplier, prefixes and xml element.""" - for prefix in prefixes: - valueComplex = getComplexByMultiplierPrefix( multiplier, prefix, valueComplex, xmlElement ) - return valueComplex - -def getComplexByPrefix( prefix, valueComplex, xmlElement ): - """Get complex from prefix and xml element.""" - value = evaluate.getEvaluatedValue(None, prefix, xmlElement) - if value is not None: - valueComplex = getComplexByDictionaryListValue(value, valueComplex) - x = evaluate.getEvaluatedFloat(None, prefix + '.x', xmlElement) - if x is not None: - valueComplex = complex( x, getComplexIfNone( valueComplex ).imag ) - y = evaluate.getEvaluatedFloat(None, prefix + '.y', xmlElement) - if y is not None: - valueComplex = complex( getComplexIfNone( valueComplex ).real, y ) - return valueComplex - -def getComplexByPrefixBeginEnd(prefixBegin, prefixEnd, valueComplex, xmlElement): - """Get complex from prefixBegin, prefixEnd and xml element.""" - valueComplex = getComplexByPrefix(prefixBegin, valueComplex, xmlElement) - if prefixEnd in xmlElement.attributeDictionary: - return 0.5 * getComplexByPrefix(valueComplex + valueComplex, prefixEnd, xmlElement) - else: - return valueComplex - -def getComplexByPrefixes( prefixes, valueComplex, xmlElement ): - """Get complex from prefixes and xml element.""" - for prefix in prefixes: - valueComplex = getComplexByPrefix( prefix, valueComplex, xmlElement ) - return valueComplex - -def getComplexIfNone( valueComplex ): - """Get new complex if the original complex is none.""" - if valueComplex is None: - return complex() - return valueComplex - -def getFloatByPrefixBeginEnd(prefixBegin, prefixEnd, valueFloat, xmlElement): - """Get float from prefixBegin, prefixEnd and xml element.""" - valueFloat = evaluate.getEvaluatedFloat(valueFloat, prefixBegin, xmlElement) - if prefixEnd in xmlElement.attributeDictionary: - return 0.5 * evaluate.getEvaluatedFloat(valueFloat + valueFloat, prefixEnd, xmlElement) - return valueFloat - -def getFloatByPrefixSide( prefix, side, xmlElement ): - """Get float by prefix and side.""" - floatByDenominatorPrefix = evaluate.getEvaluatedFloat(0.0, prefix, xmlElement) - return floatByDenominatorPrefix + evaluate.getEvaluatedFloat(0.0, prefix + 'OverSide', xmlElement ) * side - -def getGeometryOutput(derivation, xmlElement): - """Get geometry output from paths.""" - if derivation is None: - derivation = LineationDerivation(xmlElement) - geometryOutput = [] - for path in derivation.target: - sideLoop = SideLoop(path) - geometryOutput += getGeometryOutputByLoop(sideLoop, xmlElement) - return geometryOutput - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get vector3 vertexes from attribute dictionary by arguments.""" - return getGeometryOutput(None, xmlElement) - -def getGeometryOutputByLoop( sideLoop, xmlElement ): - """Get geometry output by side loop.""" - sideLoop.rotate(xmlElement) - return getGeometryOutputByManipulation( sideLoop, xmlElement ) - -def getGeometryOutputByManipulation( sideLoop, xmlElement ): - """Get geometry output by manipulation.""" - sideLoop.loop = euclidean.getLoopWithoutCloseSequentialPoints( sideLoop.close, sideLoop.loop ) - return sideLoop.getManipulationPluginLoops(xmlElement) - -def getMinimumRadius( beginComplexSegmentLength, endComplexSegmentLength, radius ): - """Get minimum radius.""" - return min( abs(radius), 0.5 * min( beginComplexSegmentLength, endComplexSegmentLength ) ) - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return LineationDerivation(xmlElement) - -def getNumberOfBezierPoints(begin, end, xmlElement): - """Get the numberOfBezierPoints.""" - numberOfBezierPoints = int(math.ceil(0.5 * evaluate.getSidesMinimumThreeBasedOnPrecision(abs(end - begin), xmlElement))) - return evaluate.getEvaluatedInt(numberOfBezierPoints, 'sides', xmlElement) - -def getPackedGeometryOutputByLoop(sideLoop, xmlElement): - """Get packed geometry output by side loop.""" - sideLoop.rotate(xmlElement) - return getGeometryOutputByManipulation(sideLoop, xmlElement) - -def getRadiusAverage(radiusComplex): - """Get average radius from radiusComplex.""" - if radiusComplex.real == radiusComplex.imag: - return radiusComplex.real - return math.sqrt(radiusComplex.real * radiusComplex.imag) - -def getRadiusComplex(radius, xmlElement): - """Get radius complex for xmlElement.""" - radius = getComplexByPrefixes(['demisize', 'radius'], radius, xmlElement) - return getComplexByMultiplierPrefixes(2.0, ['diameter', 'size'], radius, xmlElement) - -def getRadiusByPrefix(prefix, sideLength, xmlElement): - """Get radius by prefix.""" - radius = getFloatByPrefixSide(prefix + 'radius', sideLength, xmlElement) - radius += 0.5 * getFloatByPrefixSide(prefix + 'diameter', sideLength, xmlElement) - return radius + 0.5 * getFloatByPrefixSide(prefix + 'size', sideLength, xmlElement) - -def getStrokeRadiusByPrefix(prefix, xmlElement): - """Get strokeRadius by prefix.""" - strokeRadius = getFloatByPrefixBeginEnd(prefix + 'strokeRadius', prefix + 'strokeWidth', 1.0, xmlElement ) - return getFloatByPrefixBeginEnd(prefix + 'radius', prefix + 'diameter', strokeRadius, xmlElement ) - -def processTargetByFunction(manipulationFunction, target): - """Process the target by the manipulationFunction.""" - if target.xmlObject is None: - print('Warning, there is no object in processTargetByFunction in lineation for:') - print(target) - return - geometryOutput = [] - transformedPaths = target.xmlObject.getTransformedPaths() - for transformedPath in transformedPaths: - sideLoop = SideLoop(transformedPath) - sideLoop.rotate(target) - sideLoop.loop = euclidean.getLoopWithoutCloseSequentialPoints( sideLoop.close, sideLoop.loop ) - geometryOutput += manipulationFunction( sideLoop.close, sideLoop.loop, '', sideLoop.sideLength, target ) - if len(geometryOutput) < 1: - print('Warning, there is no geometryOutput in processTargetByFunction in lineation for:') - print(target) - return - removeChildrenFromElementObject(target) - path.convertXMLElement(geometryOutput, target) - -def processXMLElement(xmlElement): - """Process the xml element.""" - path.convertXMLElement(getGeometryOutput(None, xmlElement), xmlElement) - -def processXMLElementByFunction(manipulationFunction, xmlElement): - """Process the xml element by the manipulationFunction.""" - targets = evaluate.getXMLElementsByKey('target', xmlElement) - for target in targets: - processTargetByFunction(manipulationFunction, target) - -def removeChildrenFromElementObject(xmlElement): - """Process the xml element by manipulationFunction.""" - xmlElement.removeChildrenFromIDNameParent() - if xmlElement.xmlObject is not None: - if xmlElement.parent.xmlObject is not None: - if xmlElement.xmlObject in xmlElement.parent.xmlObject.archivableObjects: - xmlElement.parent.xmlObject.archivableObjects.remove(xmlElement.xmlObject) - -def setClosedAttribute(revolutions, xmlElement): - """Set the closed attribute of the xmlElement.""" - closedBoolean = evaluate.getEvaluatedBoolean(revolutions <= 1, 'closed', xmlElement) - xmlElement.attributeDictionary['closed'] = str(closedBoolean).lower() - - -class LineationDerivation: - """Class to hold lineation variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.target = evaluate.getTransformedPathsByKey([], 'target', xmlElement) - - def __repr__(self): - """Get the string representation of this LineationDerivation.""" - return str(self.__dict__) - - -class SideLoop: - """Class to handle loop, side angle and side length.""" - def __init__(self, loop, sideAngle=None, sideLength=None): - """Initialize.""" - if sideAngle is None: - if len(loop) > 0: - sideAngle = 2.0 * math.pi / float(len(loop)) - else: - sideAngle = 1.0 - print('Warning, loop has no sides in SideLoop in lineation.') - if sideLength is None: - if len(loop) > 0: - sideLength = euclidean.getLoopLength(loop) / float(len(loop)) - else: - sideLength = 1.0 - print('Warning, loop has no length in SideLoop in lineation.') - self.loop = loop - self.sideAngle = abs(sideAngle) - self.sideLength = abs(sideLength) - self.close = 0.001 * sideLength - - def getManipulationPluginLoops(self, xmlElement): - """Get loop manipulated by the plugins in the manipulation paths folder.""" - xmlProcessor = xmlElement.getXMLProcessor() -# matchingPlugins = evaluate.getFromCreationEvaluatorPlugins(xmlProcessor.manipulationMatrixDictionary, xmlElement) - matchingPlugins = evaluate.getMatchingPlugins(xmlProcessor.manipulationMatrixDictionary, xmlElement) - matchingPlugins += evaluate.getMatchingPlugins(xmlProcessor.manipulationPathDictionary, xmlElement) - matchingPlugins += evaluate.getMatchingPlugins(xmlProcessor.manipulationShapeDictionary, xmlElement) - matchingPlugins.sort(evaluate.compareExecutionOrderAscending) - loops = [self.loop] - for matchingPlugin in matchingPlugins: - matchingLoops = [] - prefix = matchingPlugin.__name__.replace('_', '') + '.' - for loop in loops: - matchingLoops += matchingPlugin.getManipulatedPaths(self.close, loop, prefix, self.sideLength, xmlElement) - loops = matchingLoops - return loops - - def rotate(self, xmlElement): - """Rotate.""" - rotation = math.radians( evaluate.getEvaluatedFloat(0.0, 'rotation', xmlElement ) ) - rotation += evaluate.getEvaluatedFloat(0.0, 'rotationOverSide', xmlElement ) * self.sideAngle - if rotation != 0.0: - planeRotation = euclidean.getWiddershinsUnitPolar( rotation ) - for vertex in self.loop: - rotatedComplex = vertex.dropAxis() * planeRotation - vertex.x = rotatedComplex.real - vertex.y = rotatedComplex.imag - if 'clockwise' in xmlElement.attributeDictionary: - isClockwise = euclidean.getBooleanFromValue( evaluate.getEvaluatedValueObliviously('clockwise', xmlElement ) ) - if isClockwise == euclidean.getIsWiddershinsByVector3( self.loop ): - self.loop.reverse() - - -class Spiral: - """Class to add a spiral.""" - def __init__(self, spiral, stepRatio): - """Initialize.""" - self.spiral = spiral - if self.spiral is None: - return - self.spiralIncrement = self.spiral * stepRatio - self.spiralTotal = Vector3() - - def __repr__(self): - """Get the string representation of this Spiral.""" - return self.spiral - - def getSpiralPoint(self, unitPolar, vector3): - """Add spiral to the vector.""" - if self.spiral is None: - return vector3 - vector3 += Vector3(unitPolar.real * self.spiralTotal.x, unitPolar.imag * self.spiralTotal.y, self.spiralTotal.z) - self.spiralTotal += self.spiralIncrement - return vector3 diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/mechaslab.py b/skeinforge/fabmetheus_utilities/geometry/creation/mechaslab.py deleted file mode 100644 index 5580fed..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/mechaslab.py +++ /dev/null @@ -1,257 +0,0 @@ -""" -Mechaslab. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import extrude -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.creation import peg -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.geometry_utilities.evaluate_elements import setting -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.geometry.manipulation_matrix import translate -from fabmetheus_utilities.geometry.solids import cylinder -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addAlongWay(begin, distance, end, loop): - """Get the beveled rectangle.""" - endMinusBegin = end - begin - endMinusBeginLength = abs(endMinusBegin) - if endMinusBeginLength <= 0.0: - return - alongWayMultiplier = distance / endMinusBeginLength - loop.append(begin + alongWayMultiplier * endMinusBegin) - -def addGroove(derivation, negatives): - """Add groove on each side of cage.""" - copyShallow = derivation.xmlElement.getCopyShallow() - extrude.setXMLElementToEndStart(Vector3(-derivation.demilength), Vector3(derivation.demilength), copyShallow) - extrudeDerivation = extrude.ExtrudeDerivation(copyShallow) - bottom = derivation.demiheight - 0.5 * derivation.grooveWidth - outside = derivation.demiwidth - top = derivation.demiheight - leftGroove = [ - complex(-outside, bottom), - complex(-derivation.innerDemiwidth, derivation.demiheight), - complex(-outside, top)] - rightGroove = [ - complex(outside, top), - complex(derivation.innerDemiwidth, derivation.demiheight), - complex(outside, bottom)] - groovesComplex = [leftGroove, rightGroove] - groovesVector3 = euclidean.getVector3Paths(groovesComplex) - extrude.addPositives(extrudeDerivation, groovesVector3, negatives) - -def addHollowPegSocket(derivation, hollowPegSocket, negatives, positives): - """Add the socket and hollow peg.""" - pegHeight = derivation.pegHeight - pegRadians = derivation.pegRadians - pegRadiusComplex = complex(derivation.pegRadius, derivation.pegRadius) - pegTip = 0.8 * derivation.pegRadius - sides = derivation.pegSides - start = Vector3(hollowPegSocket.center.real, hollowPegSocket.center.imag, derivation.height) - tinyHeight = 0.0001 * pegHeight - topRadians = 0.25 * math.pi - boltTop = derivation.height - if hollowPegSocket.shouldAddPeg: - boltTop = peg.getTopAddBiconicOutput( - pegRadians, pegHeight, positives, pegRadiusComplex, sides, start, pegTip, topRadians) - sides = derivation.socketSides - socketHeight = 1.05 * derivation.pegHeight - socketRadiusComplex = complex(derivation.socketRadius, derivation.socketRadius) - socketTip = 0.5 * derivation.overhangSpan - start = Vector3(hollowPegSocket.center.real, hollowPegSocket.center.imag, -tinyHeight) - topRadians = derivation.interiorOverhangRadians - if hollowPegSocket.shouldAddSocket: - peg.getTopAddBiconicOutput(pegRadians, socketHeight, negatives, socketRadiusComplex, sides, start, socketTip, topRadians) - if derivation.boltRadius <= 0.0: - return - if (not hollowPegSocket.shouldAddPeg) and (not hollowPegSocket.shouldAddSocket): - return - boltRadiusComplex = complex(derivation.boltRadius, derivation.boltRadius) - cylinder.addCylinderOutputByEndStart(boltTop + tinyHeight, boltRadiusComplex, negatives, derivation.boltSides, start) - -def addSlab(derivation, positives): - """Add slab.""" - copyShallow = derivation.xmlElement.getCopyShallow() - copyShallow.attributeDictionary['path'] = [Vector3(), Vector3(0.0, 0.0, derivation.height)] - extrudeDerivation = extrude.ExtrudeDerivation(copyShallow) - beveledRectangle = getBeveledRectangle(derivation.bevel, -derivation.topRight) - outsidePath = euclidean.getVector3Path(beveledRectangle) - extrude.addPositives(extrudeDerivation, [outsidePath], positives) - -def addXGroove(derivation, negatives, y): - """Add x groove.""" - if derivation.topBevel <= 0.0: - return - bottom = derivation.height - derivation.topBevel - top = derivation.height - groove = [complex(y, bottom), complex(y - derivation.topBevel, top), complex(y + derivation.topBevel, top)] - triangle_mesh.addSymmetricXPath(negatives, groove, 1.0001 * derivation.topRight.real) - -def addYGroove(derivation, negatives, x): - """Add y groove""" - if derivation.topBevel <= 0.0: - return - bottom = derivation.height - derivation.topBevel - top = derivation.height - groove = [complex(x, bottom), complex(x - derivation.topBevel, top), complex(x + derivation.topBevel, top)] - triangle_mesh.addSymmetricYPath(negatives, groove, 1.0001 * derivation.topRight.imag) - -def getBeveledRectangle(bevel, bottomLeft): - """Get the beveled rectangle.""" - bottomRight = complex(-bottomLeft.real, bottomLeft.imag) - rectangle = [bottomLeft, bottomRight, -bottomLeft, -bottomRight] - if bevel <= 0.0: - return rectangle - beveledRectangle = [] - for pointIndex, point in enumerate(rectangle): - begin = rectangle[(pointIndex + len(rectangle) - 1) % len(rectangle)] - end = rectangle[(pointIndex + 1) % len(rectangle)] - addAlongWay(point, bevel, begin, beveledRectangle) - addAlongWay(point, bevel, end, beveledRectangle) - return beveledRectangle - -def getGeometryOutput(xmlElement): - """Get vector3 vertexes from attribute dictionary.""" - derivation = MechaslabDerivation(xmlElement) - negatives = [] - positives = [] - addSlab(derivation, positives) - for hollowPegSocket in derivation.hollowPegSockets: - addHollowPegSocket(derivation, hollowPegSocket, negatives, positives) - if 's' in derivation.topBevelPositions: - addXGroove(derivation, negatives, -derivation.topRight.imag) - if 'n' in derivation.topBevelPositions: - addXGroove(derivation, negatives, derivation.topRight.imag) - if 'w' in derivation.topBevelPositions: - addYGroove(derivation, negatives, -derivation.topRight.real) - if 'e' in derivation.topBevelPositions: - addYGroove(derivation, negatives, derivation.topRight.real) - return extrude.getGeometryOutputByNegativesPositives(negatives, positives, xmlElement) - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get vector3 vertexes from attribute dictionary by arguments.""" - evaluate.setAttributeDictionaryByArguments(['length', 'radius'], arguments, xmlElement) - return getGeometryOutput(xmlElement) - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return MechaslabDerivation(xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - solid.processXMLElementByGeometry(getGeometryOutput(xmlElement), xmlElement) - - -class CellExistence: - """Class to determine if a cell exists.""" - def __init__(self, columns, rows, value): - """Initialize.""" - self.existenceSet = None - if value is None: - return - self.existenceSet = set() - for element in value: - if element.__class__ == int: - columnIndex = (element + columns) % columns - for rowIndex in xrange(rows): - keyTuple = (columnIndex, rowIndex) - self.existenceSet.add(keyTuple) - else: - keyTuple = (element[0], element[1]) - self.existenceSet.add(keyTuple) - - def __repr__(self): - """Get the string representation of this CellExistence.""" - return euclidean.getDictionaryString(self.__dict__) - - def getIsInExistence(self, columnIndex, rowIndex): - """Detremine if the cell at the column and row exists.""" - if self.existenceSet is None: - return True - return (columnIndex, rowIndex) in self.existenceSet - - -class HollowPegSocket: - """Class to hold hollow peg socket variables.""" - def __init__(self, center): - """Initialize.""" - self.center = center - self.shouldAddPeg = True - self.shouldAddSocket = True - - def __repr__(self): - """Get the string representation of this HollowPegSocket.""" - return euclidean.getDictionaryString(self.__dict__) - - -class MechaslabDerivation: - """Class to hold mechaslab variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.bevelOverRadius = evaluate.getEvaluatedFloat(0.2, 'bevelOverRadius', xmlElement) - self.boltRadiusOverRadius = evaluate.getEvaluatedFloat(0.0, 'boltRadiusOverRadius', xmlElement) - self.columns = evaluate.getEvaluatedInt(2, 'columns', xmlElement) - self.heightOverRadius = evaluate.getEvaluatedFloat(2.0, 'heightOverRadius', xmlElement) - self.interiorOverhangRadians = setting.getInteriorOverhangRadians(xmlElement) - self.overhangSpan = setting.getOverhangSpan(xmlElement) - self.pegClearanceOverRadius = evaluate.getEvaluatedFloat(0.0, 'pegClearanceOverRadius', xmlElement) - self.pegRadians = math.radians(evaluate.getEvaluatedFloat(2.0, 'pegAngle', xmlElement)) - self.pegHeightOverHeight = evaluate.getEvaluatedFloat(0.4, 'pegHeightOverHeight', xmlElement) - self.pegRadiusOverRadius = evaluate.getEvaluatedFloat(0.7, 'pegRadiusOverRadius', xmlElement) - self.radius = lineation.getFloatByPrefixBeginEnd('radius', 'width', 5.0, xmlElement) - self.rows = evaluate.getEvaluatedInt(1, 'rows', xmlElement) - self.topBevelOverRadius = evaluate.getEvaluatedFloat(0.2, 'topBevelOverRadius', xmlElement) - self.xmlElement = xmlElement - # Set derived values. - self.bevel = evaluate.getEvaluatedFloat(self.bevelOverRadius * self.radius, 'bevel', xmlElement) - self.boltRadius = evaluate.getEvaluatedFloat(self.boltRadiusOverRadius * self.radius, 'boltRadius', xmlElement) - self.boltSides = evaluate.getSidesMinimumThreeBasedOnPrecision(self.boltRadius, xmlElement) - self.bottomLeftCenter = complex(-float(self.columns - 1), -float(self.rows - 1)) * self.radius - self.height = evaluate.getEvaluatedFloat(self.heightOverRadius * self.radius, 'height', xmlElement) - self.hollowPegSockets = [] - centerY = self.bottomLeftCenter.imag - diameter = self.radius + self.radius - self.pegExistence = CellExistence(self.columns, self.rows, evaluate.getEvaluatedValue(None, 'pegs', xmlElement)) - self.socketExistence = CellExistence(self.columns, self.rows, evaluate.getEvaluatedValue(None, 'sockets', xmlElement)) - for rowIndex in xrange(self.rows): - centerX = self.bottomLeftCenter.real - for columnIndex in xrange(self.columns): - hollowPegSocket = HollowPegSocket(complex(centerX, centerY)) - hollowPegSocket.shouldAddPeg = self.pegExistence.getIsInExistence(columnIndex, rowIndex) - hollowPegSocket.shouldAddSocket = self.socketExistence.getIsInExistence(columnIndex, rowIndex) - self.hollowPegSockets.append(hollowPegSocket) - centerX += diameter - centerY += diameter - self.pegClearance = evaluate.getEvaluatedFloat(self.pegClearanceOverRadius * self.radius, 'pegClearance', xmlElement) - halfPegClearance = 0.5 * self.pegClearance - self.pegHeight = evaluate.getEvaluatedFloat(self.pegHeightOverHeight * self.height, 'pegHeight', xmlElement) - self.pegRadius = evaluate.getEvaluatedFloat(self.pegRadiusOverRadius * self.radius, 'pegRadius', xmlElement) - sides = 24 * max(1, math.floor(evaluate.getSidesBasedOnPrecision(self.pegRadius, xmlElement) / 24)) - self.socketRadius = self.pegRadius + halfPegClearance - self.pegSides = evaluate.getEvaluatedInt(sides, 'pegSides', xmlElement) - self.socketSides = evaluate.getEvaluatedInt(sides, 'socketSides', xmlElement) - self.pegRadius -= halfPegClearance - self.topBevel = evaluate.getEvaluatedFloat(self.topBevelOverRadius * self.radius, 'topBevel', xmlElement) - self.topBevelPositions = evaluate.getEvaluatedString('nwse', 'topBevelPositions', xmlElement).lower() - self.topRight = complex(float(self.columns), float(self.rows)) * self.radius - - def __repr__(self): - """Get the string representation of this MechaslabDerivation.""" - return euclidean.getDictionaryString(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/peg.py b/skeinforge/fabmetheus_utilities/geometry/creation/peg.py deleted file mode 100644 index 6591c62..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/peg.py +++ /dev/null @@ -1,101 +0,0 @@ -""" -Peg. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import extrude -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.solids import cylinder -from fabmetheus_utilities.vector3 import Vector3 -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - - -def addPegOutput(bevel, endZ, outputs, radius, start, topOverBottom, xmlElement): - """Add beveled cylinder to outputs given bevel, endZ, radius and start.""" - height = abs(start.z - endZ) - bevelStartRatio = max(1.0 - bevel / height, 0.5) - oneMinusBevelStartRatio = 1.0 - bevelStartRatio - trunkEndZ = bevelStartRatio * endZ + oneMinusBevelStartRatio * start.z - trunkTopOverBottom = bevelStartRatio * topOverBottom + oneMinusBevelStartRatio - sides = evaluate.getSidesMinimumThreeBasedOnPrecision(max(radius.real, radius.imag), xmlElement ) - cylinder.addCylinderOutputByEndStart(trunkEndZ, radius, outputs, sides, start, trunkTopOverBottom) - capRadius = radius * trunkTopOverBottom - capStart = bevelStartRatio * Vector3(start.x, start.y, endZ) + oneMinusBevelStartRatio * start - radiusMaximum = max(radius.real, radius.imag) - endRadiusMaximum = radiusMaximum * topOverBottom - bevel - trunkRadiusMaximum = radiusMaximum * trunkTopOverBottom - capTopOverBottom = endRadiusMaximum / trunkRadiusMaximum - cylinder.addCylinderOutputByEndStart(endZ, capRadius, outputs, sides, capStart, capTopOverBottom) - -def getGeometryOutput(derivation, xmlElement): - """Get vector3 vertexes from attribute dictionary.""" - if derivation is None: - derivation = PegDerivation(xmlElement) - positives = [] - radius = complex(derivation.radius, derivation.radius) - addPegOutput(derivation.bevel, derivation.endZ, positives, radius, derivation.start, derivation.topOverBottom, xmlElement) - return extrude.getGeometryOutputByNegativesPositives([], positives, xmlElement) - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get vector3 vertexes from attribute dictionary by arguments.""" - evaluate.setAttributeDictionaryByArguments(['radius', 'endZ', 'start'], arguments, xmlElement) - return getGeometryOutput(None, xmlElement) - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return PegDerivation(xmlElement) - -def getTopAddBiconicOutput(bottomRadians, height, outputs, radius, sides, start, tipRadius, topRadians): - """Get top and add biconic cylinder to outputs.""" - radiusMaximum = max(radius.real, radius.imag) - topRadiusMaximum = radiusMaximum - height * math.tan(bottomRadians) - trunkEndZ = start.z + height - trunkTopOverBottom = topRadiusMaximum / radiusMaximum - topRadiusComplex = trunkTopOverBottom * radius - cylinder.addCylinderOutputByEndStart(trunkEndZ, radius, outputs, sides, start, trunkTopOverBottom) - tipOverTop = tipRadius / topRadiusMaximum - if tipOverTop >= 1.0: - return trunkEndZ - capStart = Vector3(start.x, start.y, trunkEndZ) - capEndZ = trunkEndZ + (topRadiusMaximum - tipRadius) / math.tan(topRadians) - cylinder.addCylinderOutputByEndStart(capEndZ, topRadiusComplex, outputs, sides, capStart, tipOverTop) - return capEndZ - -def processXMLElement(xmlElement): - """Process the xml element.""" - solid.processXMLElementByGeometry(getGeometryOutput(None, xmlElement), xmlElement) - - -class PegDerivation: - """Class to hold peg variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.endZ = evaluate.getEvaluatedFloat(10.0, 'endZ', xmlElement) - self.start = evaluate.getVector3ByPrefix(Vector3(), 'start', xmlElement) - self.radius = lineation.getFloatByPrefixBeginEnd('radius', 'diameter', 2.0, xmlElement) - self.topOverBottom = evaluate.getEvaluatedFloat(0.8, 'topOverBottom', xmlElement) - self.xmlElement = xmlElement - # Set derived variables. - self.bevelOverRadius = evaluate.getEvaluatedFloat(0.25, 'bevelOverRadius', xmlElement) - self.bevel = self.bevelOverRadius * self.radius - self.bevel = evaluate.getEvaluatedFloat(self.bevel, 'bevel', xmlElement) - self.clearanceOverRadius = evaluate.getEvaluatedFloat(0.0, 'clearanceOverRadius', xmlElement) - self.clearance = self.clearanceOverRadius * self.radius - self.clearance = evaluate.getEvaluatedFloat(self.clearance, 'clearance', xmlElement) - - def __repr__(self): - """Get the string representation of this PegDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/polygon.py b/skeinforge/fabmetheus_utilities/geometry/creation/polygon.py deleted file mode 100644 index 6503b18..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/polygon.py +++ /dev/null @@ -1,74 +0,0 @@ -""" -Polygon path. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_tools import path -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getGeometryOutput(derivation, xmlElement): - """Get vector3 vertexes from attribute dictionary.""" - if derivation is None: - derivation = PolygonDerivation(xmlElement) - loop = [] - spiral = lineation.Spiral(derivation.spiral, 0.5 * derivation.sideAngle / math.pi) - for side in xrange(derivation.start, derivation.start + derivation.extent + 1): - angle = float(side) * derivation.sideAngle - unitPolar = euclidean.getWiddershinsUnitPolar(angle) - vertex = spiral.getSpiralPoint(unitPolar, Vector3(unitPolar.real * derivation.radius.real, unitPolar.imag * derivation.radius.imag)) - loop.append(vertex) - loop = euclidean.getLoopWithoutCloseEnds(0.000001 * max(derivation.radius.real, derivation.radius.imag), loop) - sideLength = derivation.sideAngle * lineation.getRadiusAverage(derivation.radius) - lineation.setClosedAttribute(derivation.revolutions, xmlElement) - return lineation.getGeometryOutputByLoop(lineation.SideLoop(loop, derivation.sideAngle, sideLength), xmlElement) - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get vector3 vertexes from attribute dictionary by arguments.""" - evaluate.setAttributeDictionaryByArguments(['sides', 'radius'], arguments, xmlElement) - return getGeometryOutput(None, xmlElement) - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return PolygonDerivation(xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - path.convertXMLElement(getGeometryOutput(None, xmlElement), xmlElement) - - -class PolygonDerivation: - """Class to hold polygon variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.sides = evaluate.getEvaluatedFloat(4.0, 'sides', xmlElement) - self.sideAngle = 2.0 * math.pi / self.sides - cosSide = math.cos(0.5 * self.sideAngle) - self.radius = lineation.getComplexByMultiplierPrefixes(cosSide, ['apothem', 'inradius'], complex(1.0, 1.0), xmlElement) - self.radius = lineation.getComplexByPrefixes(['demisize', 'radius'], self.radius, xmlElement) - self.radius = lineation.getComplexByMultiplierPrefixes(2.0, ['diameter', 'size'], self.radius, xmlElement) - self.sidesCeiling = int(math.ceil(abs(self.sides))) - self.start = evaluate.getEvaluatedInt(0, 'start', xmlElement) - end = evaluate.getEvaluatedInt(self.sidesCeiling, 'end', xmlElement) - self.revolutions = evaluate.getEvaluatedInt(1, 'revolutions', xmlElement) - self.extent = evaluate.getEvaluatedInt(end - self.start, 'extent', xmlElement) - self.extent += self.sidesCeiling * (self.revolutions - 1) - self.spiral = evaluate.getVector3ByPrefix(None, 'spiral', xmlElement) - - def __repr__(self): - """Get the string representation of this PolygonDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/shaft.py b/skeinforge/fabmetheus_utilities/geometry/creation/shaft.py deleted file mode 100644 index 2a11576..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/shaft.py +++ /dev/null @@ -1,86 +0,0 @@ -""" -Shaft path. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_tools import path -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getGeometryOutput(derivation, xmlElement): - """Get vector3 vertexes from attribute dictionary.""" - if derivation is None: - derivation = ShaftDerivation(xmlElement) - shaftPath = getShaftPath(derivation.depthBottom, derivation.depthTop, derivation.radius, derivation.sides) - return lineation.getGeometryOutputByLoop(lineation.SideLoop(shaftPath), xmlElement) - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get vector3 vertexes from attribute dictionary by arguments.""" - evaluate.setAttributeDictionaryByArguments(['radius', 'sides'], arguments, xmlElement) - return getGeometryOutput(None, xmlElement) - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return ShaftDerivation(xmlElement) - -def getShaftPath(depthBottom, depthTop, radius, sides): - """Get shaft with the option of a flat on the top and/or bottom.""" - if radius <= 0.0: - return [] - sideAngle = 2.0 * math.pi / float(abs(sides)) - startAngle = 0.5 * sideAngle - endAngle = math.pi - 0.1 * sideAngle - shaftProfile = [] - while startAngle < endAngle: - unitPolar = euclidean.getWiddershinsUnitPolar(startAngle) - shaftProfile.append(unitPolar * radius) - startAngle += sideAngle - if abs(sides) % 2 == 1: - shaftProfile.append(complex(-radius, 0.0)) - horizontalBegin = radius - depthTop - horizontalEnd = depthBottom - radius - shaftProfile = euclidean.getHorizontallyBoundedPath(horizontalBegin, horizontalEnd, shaftProfile) - for shaftPointIndex, shaftPoint in enumerate(shaftProfile): - shaftProfile[shaftPointIndex] = complex(shaftPoint.imag, shaftPoint.real) - shaftPath = euclidean.getVector3Path(euclidean.getMirrorPath(shaftProfile)) - if sides > 0: - shaftPath.reverse() - return shaftPath - -def processXMLElement(xmlElement): - """Process the xml element.""" - path.convertXMLElement(getGeometryOutput(None, xmlElement), xmlElement) - - -class ShaftDerivation: - """Class to hold shaft variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.depthBottomOverRadius = evaluate.getEvaluatedFloat(0.0, 'depthBottomOverRadius', xmlElement) - self.depthTopOverRadius = evaluate.getEvaluatedFloat(0.0, 'depthOverRadius', xmlElement) - self.depthTopOverRadius = evaluate.getEvaluatedFloat( - self.depthTopOverRadius, 'depthTopOverRadius', xmlElement) - self.radius = evaluate.getEvaluatedFloat(1.0, 'radius', xmlElement) - self.sides = evaluate.getEvaluatedInt(4, 'sides', xmlElement) - self.depthBottom = self.radius * self.depthBottomOverRadius - self.depthBottom = evaluate.getEvaluatedFloat(self.depthBottom, 'depthBottom', xmlElement) - self.depthTop = self.radius * self.depthTopOverRadius - self.depthTop = evaluate.getEvaluatedFloat(self.depthTop, 'depth', xmlElement) - self.depthTop = evaluate.getEvaluatedFloat(self.depthTop, 'depthTop', xmlElement) - - def __repr__(self): - """Get the string representation of this ShaftDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/solid.py b/skeinforge/fabmetheus_utilities/geometry/creation/solid.py deleted file mode 100644 index 6d17c1e..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/solid.py +++ /dev/null @@ -1,137 +0,0 @@ -""" -Solid. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_tools import path -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getGeometryOutput(derivation, xmlElement): - """Get geometry output from paths.""" - if derivation is None: - derivation = SolidDerivation(xmlElement) - geometryOutput = [] - for path in derivation.target: - sideLoop = SideLoop(path) - geometryOutput += getGeometryOutputByLoop( sideLoop, xmlElement ) - return geometryOutput - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get triangle mesh from attribute dictionary by arguments.""" - return getGeometryOutput(None, xmlElement) -# -#def getGeometryOutputByLoop( sideLoop, xmlElement ): -# 'Get geometry output by side loop.' -# sideLoop.rotate(xmlElement) -# return getUnpackedLoops( getGeometryOutputByManipulation( sideLoop, xmlElement ) ) -# -#def processXMLElement(xmlElement): -# 'Process the xml element.' -# processXMLElementByGeometry(getGeometryOutput(None, xmlElement), xmlElement) - -def getGeometryOutputByFunction(geometryFunction, xmlElement): - """Get geometry output by manipulationFunction.""" - if xmlElement.xmlObject is None: - print('Warning, there is no object in getGeometryOutputByFunction in solid for:') - print(xmlElement) - return None - geometryOutput = xmlElement.xmlObject.getGeometryOutput() - if geometryOutput is None: - print('Warning, there is no geometryOutput in getGeometryOutputByFunction in solid for:') - print(xmlElement) - return None - return geometryFunction(geometryOutput, '', xmlElement) - -def getGeometryOutputByManipulation(geometryOutput, xmlElement): - """Get geometryOutput manipulated by the plugins in the manipulation shapes & solids folders.""" - xmlProcessor = xmlElement.getXMLProcessor() - matchingPlugins = getSolidMatchingPlugins(xmlElement) - matchingPlugins.sort(evaluate.compareExecutionOrderAscending) - for matchingPlugin in matchingPlugins: - prefix = matchingPlugin.__name__.replace('_', '') + '.' - geometryOutput = matchingPlugin.getManipulatedGeometryOutput(geometryOutput, prefix, xmlElement) - return geometryOutput - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return SolidDerivation(xmlElement) - -def getSolidMatchingPlugins(xmlElement): - """Get solid plugins in the manipulation matrix, shapes & solids folders.""" - xmlProcessor = xmlElement.getXMLProcessor() - matchingPlugins = evaluate.getMatchingPlugins(xmlProcessor.manipulationMatrixDictionary, xmlElement) - return matchingPlugins + evaluate.getMatchingPlugins(xmlProcessor.manipulationShapeDictionary, xmlElement) - -def processArchiveRemoveSolid(geometryOutput, xmlElement): - """Process the target by the manipulationFunction.""" - solidMatchingPlugins = getSolidMatchingPlugins(xmlElement) - if len(solidMatchingPlugins) < 1: - xmlElement.parent.xmlObject.archivableObjects.append(xmlElement.xmlObject) - return - processXMLElementByGeometry(getGeometryOutputByManipulation(geometryOutput, xmlElement), xmlElement) - xmlElement.removeFromIDNameParent() - matrix.getBranchMatrixSetXMLElement(xmlElement) - -def processTargetByFunctions(geometryFunction, pathFunction, target): - """Process the target by the manipulationFunction.""" - if target.xmlObject is None: - return - if len(target.xmlObject.getPaths()) > 0: - lineation.processTargetByFunction(pathFunction, target) - return - geometryOutput = getGeometryOutputByFunction(geometryFunction, target) - lineation.removeChildrenFromElementObject(target) - xmlProcessor = target.getXMLProcessor() - xmlProcessor.convertXMLElement(geometryOutput, target) - -def processXMLElementByFunction(manipulationFunction, xmlElement): - """Process the xml element.""" - if 'target' not in xmlElement.attributeDictionary: - print('Warning, there was no target in processXMLElementByFunction in solid for:') - print(xmlElement) - return - target = evaluate.getEvaluatedLinkValue(str(xmlElement.attributeDictionary['target']).strip(), xmlElement) - if target.__class__.__name__ == 'XMLElement': - manipulationFunction(target, xmlElement) - return - path.convertXMLElement(target, xmlElement) - manipulationFunction(xmlElement, xmlElement) - -def processXMLElementByFunctions(geometryFunction, pathFunction, xmlElement): - """Process the xml element by the appropriate manipulationFunction.""" - targets = evaluate.getXMLElementsByKey('target', xmlElement) - for target in targets: - processTargetByFunctions(geometryFunction, pathFunction, target) - -def processXMLElementByGeometry(geometryOutput, xmlElement): - """Process the xml element by geometryOutput.""" - if geometryOutput is None: - return - xmlElement.getXMLProcessor().convertXMLElement(geometryOutput, xmlElement) - - -class SolidDerivation: - """Class to hold solid variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.target = evaluate.getTransformedPathsByKey([], 'target', xmlElement) - - def __repr__(self): - """Get the string representation of this SolidDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/square.py b/skeinforge/fabmetheus_utilities/geometry/creation/square.py deleted file mode 100644 index 91ebe6f..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/square.py +++ /dev/null @@ -1,85 +0,0 @@ -""" -Square path. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_tools import path -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getGeometryOutput(derivation, xmlElement): - """Get vector3 vertexes from attribute dictionary.""" - if derivation is None: - derivation = SquareDerivation(xmlElement) - topRight = complex(derivation.topDemiwidth, derivation.demiheight) - topLeft = complex(-derivation.topDemiwidth, derivation.demiheight) - bottomLeft = complex(-derivation.bottomDemiwidth, -derivation.demiheight) - bottomRight = complex(derivation.bottomDemiwidth, -derivation.demiheight) - if derivation.interiorAngle != 90.0: - interiorPlaneAngle = euclidean.getWiddershinsUnitPolar(math.radians(derivation.interiorAngle - 90.0)) - topRight = (topRight - bottomRight) * interiorPlaneAngle + bottomRight - topLeft = (topLeft - bottomLeft) * interiorPlaneAngle + bottomLeft - lineation.setClosedAttribute(derivation.revolutions, xmlElement) - complexLoop = [topRight, topLeft, bottomLeft, bottomRight] - originalLoop = complexLoop[:] - for revolution in xrange(1, derivation.revolutions): - complexLoop += originalLoop - spiral = lineation.Spiral(derivation.spiral, 0.25) - loop = [] - loopCentroid = euclidean.getLoopCentroid(originalLoop) - for point in complexLoop: - unitPolar = euclidean.getNormalized(point - loopCentroid) - loop.append(spiral.getSpiralPoint(unitPolar, Vector3(point.real, point.imag))) - return lineation.getGeometryOutputByLoop(lineation.SideLoop(loop, 0.5 * math.pi), xmlElement) - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get vector3 vertexes from attribute dictionary by arguments.""" - if len(arguments) < 1: - return getGeometryOutput(None, xmlElement) - inradius = 0.5 * euclidean.getFloatFromValue(arguments[0]) - xmlElement.attributeDictionary['inradius.x'] = str(inradius) - if len(arguments) > 1: - inradius = 0.5 * euclidean.getFloatFromValue(arguments[1]) - xmlElement.attributeDictionary['inradius.y'] = str(inradius) - return getGeometryOutput(None, xmlElement) - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return SquareDerivation(xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - path.convertXMLElement(getGeometryOutput(None, xmlElement), xmlElement) - - -class SquareDerivation: - """Class to hold square variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.inradius = lineation.getComplexByPrefixes(['demisize', 'inradius'], complex(1.0, 1.0), xmlElement) - self.inradius = lineation.getComplexByMultiplierPrefix(2.0, 'size', self.inradius, xmlElement) - self.demiwidth = lineation.getFloatByPrefixBeginEnd('demiwidth', 'width', self.inradius.real, xmlElement) - self.demiheight = lineation.getFloatByPrefixBeginEnd('demiheight', 'height', self.inradius.imag, xmlElement) - self.bottomDemiwidth = lineation.getFloatByPrefixBeginEnd('bottomdemiwidth', 'bottomwidth', self.demiwidth, xmlElement) - self.topDemiwidth = lineation.getFloatByPrefixBeginEnd('topdemiwidth', 'topwidth', self.demiwidth, xmlElement) - self.interiorAngle = evaluate.getEvaluatedFloat(90.0, 'interiorangle', xmlElement) - self.revolutions = evaluate.getEvaluatedInt(1, 'revolutions', xmlElement) - self.spiral = evaluate.getVector3ByPrefix(None, 'spiral', xmlElement) - - def __repr__(self): - """Get the string representation of this SquareDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/teardrop.py b/skeinforge/fabmetheus_utilities/geometry/creation/teardrop.py deleted file mode 100644 index 9f5c922..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/teardrop.py +++ /dev/null @@ -1,114 +0,0 @@ -""" -Teardrop path. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import extrude -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_tools import path -from fabmetheus_utilities.geometry.geometry_utilities.evaluate_elements import setting -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addNegativesByRadius(end, negatives, radius, start, xmlElement): - """Add teardrop drill hole to negatives.""" - if radius <= 0.0: - return - copyShallow = xmlElement.getCopyShallow() - extrude.setXMLElementToEndStart(end, start, copyShallow) - extrudeDerivation = extrude.ExtrudeDerivation(copyShallow) - extrude.addNegatives(extrudeDerivation, negatives, [getTeardropPathByEndStart(end, radius, start, xmlElement)]) - -def getGeometryOutput(derivation, xmlElement): - """Get vector3 vertexes from attribute dictionary.""" - if derivation is None: - derivation = TeardropDerivation(xmlElement) - teardropPath = getTeardropPath(derivation.inclination, derivation.radius, xmlElement) - return lineation.getGeometryOutputByLoop(lineation.SideLoop(teardropPath), xmlElement) - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get vector3 vertexes from attribute dictionary by arguments.""" - evaluate.setAttributeDictionaryByArguments(['radius', 'inclination'], arguments, xmlElement) - return getGeometryOutput(None, xmlElement) - -def getInclination(end, start): - """Get inclination.""" - if end is None or start is None: - return 0.0 - endMinusStart = end - start - return math.atan2(endMinusStart.z, abs(endMinusStart.dropAxis())) - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return TeardropDerivation(xmlElement) - -def getTeardropPath(inclination, radius, xmlElement): - """Get vector3 teardrop path.""" - teardropSides = evaluate.getSidesMinimumThreeBasedOnPrecision(radius, xmlElement) - sideAngle = 2.0 * math.pi / float(teardropSides) - overhangRadians = setting.getOverhangRadians(xmlElement) - overhangPlaneAngle = euclidean.getWiddershinsUnitPolar(overhangRadians) - overhangRadians = math.atan2(overhangPlaneAngle.imag, overhangPlaneAngle.real * math.cos(inclination)) - tanOverhangAngle = math.tan(overhangRadians) - beginAngle = overhangRadians - beginMinusEndAngle = math.pi + overhangRadians + overhangRadians - withinSides = int(math.ceil(beginMinusEndAngle / sideAngle)) - withinSideAngle = -beginMinusEndAngle / float(withinSides) - teardropPath = [] - for side in xrange(withinSides + 1): - unitPolar = euclidean.getWiddershinsUnitPolar(beginAngle) - teardropPath.append(unitPolar * radius) - beginAngle += withinSideAngle - firstPoint = teardropPath[0] - overhangSpan = setting.getOverhangSpan(xmlElement) - if overhangSpan <= 0.0: - teardropPath.append(complex(0.0, firstPoint.imag + firstPoint.real / tanOverhangAngle)) - else: - deltaX = (radius - firstPoint.imag) * tanOverhangAngle - overhangPoint = complex(firstPoint.real - deltaX, radius) - remainingDeltaX = max(0.0, overhangPoint.real - 0.5 * overhangSpan ) - overhangPoint += complex(-remainingDeltaX, remainingDeltaX / tanOverhangAngle) - teardropPath.append(complex(-overhangPoint.real, overhangPoint.imag)) - teardropPath.append(overhangPoint) - return euclidean.getVector3Path(teardropPath) - -def getTeardropPathByEndStart(end, radius, start, xmlElement): - """Get vector3 teardrop path by end and start.""" - inclination = getInclination(end, start) - return getTeardropPath(inclination, radius, xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - path.convertXMLElement(getGeometryOutput(None, xmlElement), xmlElement) - - -class TeardropDerivation: - """Class to hold teardrop variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - end = evaluate.getVector3ByPrefix(None, 'end', xmlElement) - start = evaluate.getVector3ByPrefix(Vector3(), 'start', xmlElement) - inclinationDegree = math.degrees(getInclination(end, start)) - self.inclination = math.radians(evaluate.getEvaluatedFloat(inclinationDegree, 'inclination', xmlElement)) - self.radius = lineation.getFloatByPrefixBeginEnd('radius', 'diameter', 1.0, xmlElement) - size = evaluate.getEvaluatedFloat(None, 'size', xmlElement) - if size is not None: - self.radius = 0.5 * size - self.xmlElement = xmlElement - - def __repr__(self): - """Get the string representation of this TeardropDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/creation/text.py b/skeinforge/fabmetheus_utilities/geometry/creation/text.py deleted file mode 100644 index 184bd02..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/creation/text.py +++ /dev/null @@ -1,67 +0,0 @@ -""" -Text vertexes. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_tools import path -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import svg_reader - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getGeometryOutput(derivation, xmlElement): - """Get vector3 vertexes from attribute dictionary.""" - if derivation is None: - derivation = TextDerivation(xmlElement) - if derivation.textString == '': - print('Warning, textString is empty in getGeometryOutput in text for:') - print(xmlElement) - return [] - geometryOutput = [] - for textComplexLoop in svg_reader.getTextComplexLoops(derivation.fontFamily, derivation.fontSize, derivation.textString): - textComplexLoop.reverse() - vector3Path = euclidean.getVector3Path(textComplexLoop) - sideLoop = lineation.SideLoop(vector3Path, None, None) - sideLoop.rotate(xmlElement) - geometryOutput += lineation.getGeometryOutputByManipulation(sideLoop, xmlElement) - return geometryOutput - -def getGeometryOutputByArguments(arguments, xmlElement): - """Get vector3 vertexes from attribute dictionary by arguments.""" - evaluate.setAttributeDictionaryByArguments(['text', 'fontSize', 'fontFamily'], arguments, xmlElement) - return getGeometryOutput(None, xmlElement) - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return TextDerivation(xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - path.convertXMLElement(getGeometryOutput(None, xmlElement), xmlElement) - - -class TextDerivation: - """Class to hold text variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.fontFamily = evaluate.getEvaluatedString('Gentium Basic Regular', 'font-family', xmlElement) - self.fontFamily = evaluate.getEvaluatedString(self.fontFamily, 'fontFamily', xmlElement) - self.fontSize = evaluate.getEvaluatedFloat(12.0, 'font-size', xmlElement) - self.fontSize = evaluate.getEvaluatedFloat(self.fontSize, 'fontSize', xmlElement) - self.textString = xmlElement.text - self.textString = evaluate.getEvaluatedString(self.textString, 'text', xmlElement) - - def __repr__(self): - """Get the string representation of this TextDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/__init__.py b/skeinforge/fabmetheus_utilities/geometry/geometry_tools/__init__.py deleted file mode 100644 index 1121e8a..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/_comment.py b/skeinforge/fabmetheus_utilities/geometry/geometry_tools/_comment.py deleted file mode 100644 index dba1094..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/_comment.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -Face of a triangle mesh. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_tools import dictionary -from fabmetheus_utilities.geometry.geometry_utilities import evaluate - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def processXMLElement(xmlElement): - """Process the xml element.""" - evaluate.processArchivable( _Comment, xmlElement) - - -class _Comment(dictionary.Dictionary): - """A comment.""" - def addXML(self, depth, output): - """Add xml for this object.""" - output.write( self.xmlElement.text ) - diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/dictionary.py b/skeinforge/fabmetheus_utilities/geometry/geometry_tools/dictionary.py deleted file mode 100644 index a0f9965..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/dictionary.py +++ /dev/null @@ -1,173 +0,0 @@ -""" -Boolean geometry dictionary object. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import xml_simple_writer -import cStringIO - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getAllPaths(paths, xmlObject): - """Get all paths.""" - for archivableObject in xmlObject.archivableObjects: - paths += archivableObject.getPaths() - return paths - -def getAllTransformedPaths(transformedPaths, xmlObject): - """Get all transformed paths.""" - for archivableObject in xmlObject.archivableObjects: - transformedPaths += archivableObject.getTransformedPaths() - return transformedPaths - -def getAllTransformedVertexes(transformedVertexes, xmlObject): - """Get all transformed vertexes.""" - for archivableObject in xmlObject.archivableObjects: - transformedVertexes += archivableObject.getTransformedVertexes() - return transformedVertexes - -def getAllVertexes(vertexes, xmlObject): - """Get all vertexes.""" - for archivableObject in xmlObject.archivableObjects: - vertexes += archivableObject.getVertexes() - return vertexes - -def processXMLElement(xmlElement): - """Process the xml element.""" - evaluate.processArchivable( Dictionary, xmlElement) - - -class Dictionary: - """A dictionary object.""" - def __init__(self): - """Add empty lists.""" - self.archivableObjects = [] - self.xmlElement = None - - def __repr__(self): - """Get the string representation of this object info.""" - output = xml_simple_writer.getBeginGeometryXMLOutput(self.xmlElement) - self.addXML( 1, output ) - return xml_simple_writer.getEndGeometryXMLString(output) - - def addXML(self, depth, output): - """Add xml for this object.""" - attributeCopy = {} - if self.xmlElement is not None: - attributeCopy = evaluate.getEvaluatedDictionaryByCopyKeys(['paths', 'target', 'vertexes'], self.xmlElement) - euclidean.removeElementsFromDictionary(attributeCopy, matrix.getKeysM()) - euclidean.removeTrueFromDictionary(attributeCopy, 'visible') - innerOutput = cStringIO.StringIO() - self.addXMLInnerSection(depth + 1, innerOutput) - self.addXMLArchivableObjects(depth + 1, innerOutput) - xml_simple_writer.addBeginEndInnerXMLTag(attributeCopy, self.getXMLClassName(), depth, innerOutput.getvalue(), output) - - def addXMLArchivableObjects(self, depth, output): - """Add xml for this object.""" - xml_simple_writer.addXMLFromObjects( depth, self.archivableObjects, output ) - - def addXMLInnerSection(self, depth, output): - """Add xml section for this object.""" - pass - - def createShape(self): - """Create the shape.""" - pass - - def getAttributeDictionary(self): - """Get attribute table.""" - if self.xmlElement is None: - return {} - return self.xmlElement.attributeDictionary - - def getComplexTransformedPathLists(self): - """Get complex transformed path lists.""" - complexTransformedPathLists = [] - for archivableObject in self.archivableObjects: - complexTransformedPathLists.append(euclidean.getComplexPaths(archivableObject.getTransformedPaths())) - return complexTransformedPathLists - - def getFabricationExtension(self): - """Get fabrication extension.""" - return 'xml' - - def getFabricationText(self, addLayerTemplate): - """Get fabrication text.""" - return self.__repr__() - - def getGeometryOutput(self): - """Get geometry output dictionary.""" - visibleObjects = evaluate.getVisibleObjects(self.archivableObjects) - shapeOutput = [] - for visibleObject in visibleObjects: - visibleObjectOutput = visibleObject.getGeometryOutput() - if visibleObjectOutput is not None: - shapeOutput.append(visibleObjectOutput) - if len(shapeOutput) < 1: - return None - return {self.getXMLClassName() : {'shapes' : shapeOutput}} - - def getMatrix4X4(self): - """Get the matrix4X4.""" - return None - - def getMatrixChainTetragrid(self): - """Get the matrix chain tetragrid.""" - return self.xmlElement.parent.xmlObject.getMatrixChainTetragrid() - - def getMinimumZ(self): - """Get the minimum z.""" - return None - - def getPaths(self): - """Get all paths.""" - return getAllPaths([], self) - - def getTransformedPaths(self): - """Get all transformed paths.""" - return getAllTransformedPaths([], self) - - def getTransformedVertexes(self): - """Get all transformed vertexes.""" - return getAllTransformedVertexes([], self) - - def getTriangleMeshes(self): - """Get all triangleMeshes.""" - triangleMeshes = [] - for archivableObject in self.archivableObjects: - triangleMeshes += archivableObject.getTriangleMeshes() - return triangleMeshes - - def getType(self): - """Get type.""" - return self.__class__.__name__ - - def getVertexes(self): - """Get all vertexes.""" - return getAllVertexes([], self) - - def getVisible(self): - """Get visible.""" - return False - - def getXMLClassName(self): - """Get xml class name.""" - return self.__class__.__name__.lower() - - def setToXMLElement(self, xmlElement): - """Set the shape of this carvable object info.""" - self.xmlElement = xmlElement - xmlElement.parent.xmlObject.archivableObjects.append(self) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/face.py b/skeinforge/fabmetheus_utilities/geometry/geometry_tools/face.py deleted file mode 100644 index 266c378..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/face.py +++ /dev/null @@ -1,172 +0,0 @@ -""" -Face of a triangle mesh. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities.vector3index import Vector3Index -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import xml_simple_reader -from fabmetheus_utilities import xml_simple_writer -import cmath -import cStringIO -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addFaces(geometryOutput, faces): - """Add the faces.""" - if geometryOutput.__class__ == list: - for element in geometryOutput: - addFaces(element, faces) - return - if geometryOutput.__class__ != dict: - return - for geometryOutputKey in geometryOutput.keys(): - geometryOutputValue = geometryOutput[geometryOutputKey] - if geometryOutputKey == 'face': - for face in geometryOutputValue: - faces.append(face) - else: - addFaces(geometryOutputValue, faces) - -def addGeometryList( faces, xmlElement ): - """Add vertex elements to an xml element.""" - for face in faces: - faceElement = xml_simple_reader.XMLElement() - face.addToAttributeDictionary( faceElement.attributeDictionary ) - faceElement.className = 'face' - faceElement.parent = xmlElement - xmlElement.children.append( faceElement ) - -def getCommonVertexIndex( edgeFirst, edgeSecond ): - """Get the vertex index that both edges have in common.""" - for edgeFirstVertexIndex in edgeFirst.vertexIndexes: - if edgeFirstVertexIndex == edgeSecond.vertexIndexes[0] or edgeFirstVertexIndex == edgeSecond.vertexIndexes[1]: - return edgeFirstVertexIndex - print( "Inconsistent GNU Triangulated Surface" ) - print( edgeFirst ) - print( edgeSecond ) - return 0 - -def getFaces(geometryOutput): - """Get the faces.""" - faces = [] - addFaces(geometryOutput, faces) - return faces - -def processXMLElement(xmlElement): - """Process the xml element.""" - face = Face() - face.index = len(xmlElement.parent.xmlObject.faces) - for vertexIndexIndex in xrange(3): - face.vertexIndexes.append(evaluate.getEvaluatedInt(None, 'vertex' + str(vertexIndexIndex), xmlElement)) - xmlElement.parent.xmlObject.faces.append(face) - - -class Edge: - """An edge of a triangle mesh.""" - def __init__(self): - """Set the face indexes to None.""" - self.faceIndexes = [] - self.vertexIndexes = [] - self.zMaximum = None - self.zMinimum = None - - def __repr__(self): - """Get the string representation of this Edge.""" - return str( self.index ) + ' ' + str( self.faceIndexes ) + ' ' + str(self.vertexIndexes) - - def addFaceIndex( self, faceIndex ): - """Add first None face index to input face index.""" - self.faceIndexes.append( faceIndex ) - - def getFromVertexIndexes( self, edgeIndex, vertexIndexes ): - """Initialize from two vertex indices.""" - self.index = edgeIndex - self.vertexIndexes = vertexIndexes[:] - self.vertexIndexes.sort() - return self - - -class Face: - """A face of a triangle mesh.""" - def __init__(self): - """Initialize.""" - self.edgeIndexes = [] - self.index = None - self.vertexIndexes = [] - - def __repr__(self): - """Get the string representation of this object info.""" - output = cStringIO.StringIO() - self.addXML( 2, output ) - return output.getvalue() - - def addToAttributeDictionary(self, attributeDictionary): - """Add to the attribute dictionary.""" - for vertexIndexIndex in xrange(len(self.vertexIndexes)): - vertexIndex = self.vertexIndexes[vertexIndexIndex] - attributeDictionary['vertex' + str(vertexIndexIndex)] = str(vertexIndex) - - def addXML(self, depth, output): - """Add the xml for this object.""" - attributeDictionary = {} - self.addToAttributeDictionary(attributeDictionary) - xml_simple_writer.addClosedXMLTag( attributeDictionary, 'face', depth, output ) - - def copy(self): - """Get the copy of this face.""" - faceCopy = Face() - faceCopy.edgeIndexes = self.edgeIndexes[:] - faceCopy.index = self.index - faceCopy.vertexIndexes = self.vertexIndexes[:] - return faceCopy - - def getFromEdgeIndexes( self, edgeIndexes, edges, faceIndex ): - """Initialize from edge indices.""" - if len(self.vertexIndexes) > 0: - return - self.index = faceIndex - self.edgeIndexes = edgeIndexes - for edgeIndex in edgeIndexes: - edges[ edgeIndex ].addFaceIndex( faceIndex ) - for triangleIndex in xrange(3): - indexFirst = ( 3 - triangleIndex ) % 3 - indexSecond = ( 4 - triangleIndex ) % 3 - self.vertexIndexes.append( getCommonVertexIndex( edges[ edgeIndexes[ indexFirst ] ], edges[ edgeIndexes[ indexSecond ] ] ) ) - return self - - def setEdgeIndexesToVertexIndexes( self, edges, edgeTable ): - """Set the edge indexes to the vertex indexes.""" - if len(self.edgeIndexes) > 0: - return - for triangleIndex in xrange(3): - indexFirst = ( 3 - triangleIndex ) % 3 - indexSecond = ( 4 - triangleIndex ) % 3 - vertexIndexFirst = self.vertexIndexes[ indexFirst ] - vertexIndexSecond = self.vertexIndexes[ indexSecond ] - vertexIndexPair = [ vertexIndexFirst, vertexIndexSecond ] - vertexIndexPair.sort() - edgeIndex = len( edges ) - if str( vertexIndexPair ) in edgeTable: - edgeIndex = edgeTable[ str( vertexIndexPair ) ] - else: - edgeTable[ str( vertexIndexPair ) ] = edgeIndex - edge = Edge().getFromVertexIndexes( edgeIndex, vertexIndexPair ) - edges.append( edge ) - edges[ edgeIndex ].addFaceIndex( self.index ) - self.edgeIndexes.append( edgeIndex ) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/path.py b/skeinforge/fabmetheus_utilities/geometry/geometry_tools/path.py deleted file mode 100644 index 7ba3ee4..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/path.py +++ /dev/null @@ -1,208 +0,0 @@ -""" -Path. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_tools import dictionary -from fabmetheus_utilities.geometry.geometry_tools import vertex -from fabmetheus_utilities.geometry.geometry_utilities.evaluate_elements import setting -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import svg_writer -from fabmetheus_utilities import xml_simple_reader -from fabmetheus_utilities import xml_simple_writer - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def convertXMLElementByPath(geometryOutput, xmlElement): - """Convert the xml element to a path xml element.""" - createLinkPath(xmlElement) - xmlElement.xmlObject.vertexes = geometryOutput - vertex.addGeometryList(geometryOutput, xmlElement) - -def convertXMLElement(geometryOutput, xmlElement): - """Convert the xml element by geometryOutput.""" - if geometryOutput is None: - return - if len(geometryOutput) < 1: - return - if len(geometryOutput) == 1: - firstLoop = geometryOutput[0] - if firstLoop.__class__ == list: - geometryOutput = firstLoop - firstElement = geometryOutput[0] - if firstElement.__class__ == list: - if len(firstElement) > 1: - convertXMLElementRenameByPaths(geometryOutput, xmlElement) - else: - convertXMLElementByPath(firstElement, xmlElement) - else: - convertXMLElementByPath(geometryOutput, xmlElement) - -def convertXMLElementRenameByPaths(geometryOutput, xmlElement): - """Convert the xml element to a path xml element and add paths.""" - createLinkPath(xmlElement) - for geometryOutputChild in geometryOutput: - pathElement = xml_simple_reader.XMLElement() - pathElement.setParentAddToChildren(xmlElement) - convertXMLElementByPath(geometryOutputChild, pathElement) - -def createLinkPath(xmlElement): - """Create and link a path object.""" - xmlElement.className = 'path' - xmlElement.linkObject(Path()) - -def processXMLElement(xmlElement): - """Process the xml element.""" - evaluate.processArchivable(Path, xmlElement) - - -class Path(dictionary.Dictionary): - """A path.""" - def __init__(self): - """Add empty lists.""" - dictionary.Dictionary.__init__(self) - self.matrix4X4 = matrix.Matrix() - self.oldChainTetragrid = None - self.transformedPath = None - self.vertexes = [] - - def addXMLInnerSection(self, depth, output): - """Add the xml section for this object.""" - if self.matrix4X4 is not None: - self.matrix4X4.addXML(depth, output) - xml_simple_writer.addXMLFromVertexes(depth, output, self.vertexes) - - def getFabricationExtension(self): - """Get fabrication extension.""" - return 'svg' - - def getFabricationText(self, addLayerTemplate): - """Get fabrication text.""" - carving = SVGFabricationCarving(addLayerTemplate, self.xmlElement) - carving.setCarveLayerThickness(setting.getSheetThickness(self.xmlElement)) - carving.processSVGElement(self.xmlElement.getRoot().parser.fileName) - return str(carving) - - def getMatrix4X4(self): - """Get the matrix4X4.""" - return self.matrix4X4 - - def getMatrixChainTetragrid(self): - """Get the matrix chain tetragrid.""" - return matrix.getTetragridTimesOther(self.xmlElement.parent.xmlObject.getMatrixChainTetragrid(), self.matrix4X4.tetragrid) - - def getPaths(self): - """Get all paths.""" - self.transformedPath = None - if len(self.vertexes) > 0: - return dictionary.getAllPaths([self.vertexes], self) - return dictionary.getAllPaths([], self) - - def getTransformedPaths(self): - """Get all transformed paths.""" - if self.xmlElement is None: - return dictionary.getAllPaths([self.vertexes], self) - chainTetragrid = self.getMatrixChainTetragrid() - if self.oldChainTetragrid != chainTetragrid: - self.oldChainTetragrid = chainTetragrid - self.transformedPath = None - if self.transformedPath is None: - self.transformedPath = matrix.getTransformedVector3s(chainTetragrid, self.vertexes) - if len(self.transformedPath) > 0: - return dictionary.getAllTransformedPaths([self.transformedPath], self) - return dictionary.getAllTransformedPaths([], self) - - -class SVGFabricationCarving: - """An svg carving.""" - def __init__(self, addLayerTemplate, xmlElement): - """Add empty lists.""" - self.addLayerTemplate = addLayerTemplate - self.layerThickness = 1.0 - self.rotatedLoopLayers = [] - self.xmlElement = xmlElement - - def __repr__(self): - """Get the string representation of this carving.""" - return self.getCarvedSVG() - - def addXML(self, depth, output): - """Add xml for this object.""" - xml_simple_writer.addXMLFromObjects(depth, self.rotatedLoopLayers, output) - - def getCarveCornerMaximum(self): - """Get the corner maximum of the vertexes.""" - return self.cornerMaximum - - def getCarveCornerMinimum(self): - """Get the corner minimum of the vertexes.""" - return self.cornerMinimum - - def getCarvedSVG(self): - """Get the carved svg text.""" - return svg_writer.getSVGByLoopLayers(self.addLayerTemplate, self, self.rotatedLoopLayers) - - def getCarveLayerThickness(self): - """Get the layer thickness.""" - return self.layerThickness - - def getCarveRotatedBoundaryLayers(self): - """Get the rotated boundary layers.""" - return self.rotatedLoopLayers - - def getFabmetheusXML(self): - """Return the fabmetheus XML.""" - return self.xmlElement.getParser().getOriginalRoot() - - def getInterpretationSuffix(self): - """Return the suffix for a carving.""" - return 'svg' - - def processSVGElement(self, fileName): - """Parse SVG element and store the layers.""" - self.fileName = fileName - paths = self.xmlElement.xmlObject.getPaths() - oldZ = None - self.rotatedLoopLayers = [] - rotatedLoopLayer = None - for path in paths: - if len(path) > 0: - z = path[0].z - if z != oldZ: - rotatedLoopLayer = euclidean.RotatedLoopLayer(z) - self.rotatedLoopLayers.append(rotatedLoopLayer) - oldZ = z - rotatedLoopLayer.loops.append(euclidean.getComplexPath(path)) - if len(self.rotatedLoopLayers) < 1: - return - self.cornerMaximum = Vector3(-987654321.0, -987654321.0, -987654321.0) - self.cornerMinimum = Vector3(987654321.0, 987654321.0, 987654321.0) - svg_writer.setSVGCarvingCorners(self.cornerMaximum, self.cornerMinimum, self.layerThickness, self.rotatedLoopLayers) - - def setCarveInfillInDirectionOfBridge( self, infillInDirectionOfBridge ): - """Set the infill in direction of bridge.""" - pass - - def setCarveLayerThickness( self, layerThickness ): - """Set the layer thickness.""" - self.layerThickness = layerThickness - - def setCarveImportRadius( self, importRadius ): - """Set the import radius.""" - pass - - def setCarveIsCorrectMesh( self, isCorrectMesh ): - """Set the is correct mesh flag.""" - pass diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/path_elements/__init__.py b/skeinforge/fabmetheus_utilities/geometry/geometry_tools/path_elements/__init__.py deleted file mode 100644 index 58ec332..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/path_elements/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 4 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/path_elements/arc.py b/skeinforge/fabmetheus_utilities/geometry/geometry_tools/path_elements/arc.py deleted file mode 100644 index d49f5cf..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/path_elements/arc.py +++ /dev/null @@ -1,51 +0,0 @@ -""" -Arc vertexes. - -From: -http://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import svg_reader -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getArcPath(xmlElement): - """Get the arc path.rx ry x-axis-rotation large-arc-flag sweep-flag""" - begin = xmlElement.getPreviousVertex(Vector3()) - end = evaluate.getVector3FromXMLElement(xmlElement) - largeArcFlag = evaluate.getEvaluatedBoolean(True, 'largeArcFlag', xmlElement) - radius = lineation.getComplexByPrefix('radius', complex(1.0, 1.0), xmlElement ) - sweepFlag = evaluate.getEvaluatedBoolean(True, 'sweepFlag', xmlElement) - xAxisRotation = math.radians(evaluate.getEvaluatedFloat(0.0, 'xAxisRotation', xmlElement )) - arcComplexes = svg_reader.getArcComplexes(begin.dropAxis(), end.dropAxis(), largeArcFlag, radius, sweepFlag, xAxisRotation) - path = [] - if len(arcComplexes) < 1: - return [] - incrementZ = (end.z - begin.z) / float(len(arcComplexes)) - z = begin.z - for pointIndex in xrange(len(arcComplexes)): - pointComplex = arcComplexes[pointIndex] - z += incrementZ - path.append(Vector3(pointComplex.real, pointComplex.imag, z)) - if len(path) > 0: - path[-1] = end - return path - -def processXMLElement(xmlElement): - """Process the xml element.""" - xmlElement.parent.xmlObject.vertexes += getArcPath(xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/path_elements/cubic.py b/skeinforge/fabmetheus_utilities/geometry/geometry_tools/path_elements/cubic.py deleted file mode 100644 index f08c2f3..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/path_elements/cubic.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -Cubic vertexes. - -From: -http://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import svg_reader - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCubicPath(xmlElement): - """Get the cubic path.""" - end = evaluate.getVector3FromXMLElement(xmlElement) - previousXMLElement = xmlElement.getPreviousXMLElement() - if previousXMLElement is None: - print('Warning, can not get previousXMLElement in getCubicPath in cubic for:') - print(xmlElement) - return [end] - begin = xmlElement.getPreviousVertex(Vector3()) - evaluatedControlPoints = evaluate.getTransformedPathByKey([], 'controlPoints', xmlElement) - if len(evaluatedControlPoints) > 1: - return getCubicPathByBeginEnd(begin, evaluatedControlPoints, end, xmlElement) - controlPoint0 = evaluate.getVector3ByPrefix(None, 'controlPoint0', xmlElement) - controlPoint1 = evaluate.getVector3ByPrefix(None, 'controlPoint1', xmlElement) - if len(evaluatedControlPoints) == 1: - controlPoint1 = evaluatedControlPoints[0] - if controlPoint0 is None: - oldControlPoint = evaluate.getVector3ByPrefixes(['controlPoint','controlPoint1'], None, previousXMLElement) - if oldControlPoint is None: - oldControlPoints = evaluate.getTransformedPathByKey([], 'controlPoints', previousXMLElement) - if len(oldControlPoints) > 0: - oldControlPoint = oldControlPoints[-1] - if oldControlPoint is None: - oldControlPoint = end - controlPoint0 = begin + begin - oldControlPoint - return getCubicPathByBeginEnd(begin, [controlPoint0, controlPoint1], end, xmlElement) - -def getCubicPathByBeginEnd(begin, controlPoints, end, xmlElement): - """Get the cubic path by begin and end.""" - return svg_reader.getCubicPoints(begin, controlPoints, end, lineation.getNumberOfBezierPoints(begin, end, xmlElement)) - -def processXMLElement(xmlElement): - """Process the xml element.""" - xmlElement.parent.xmlObject.vertexes += getCubicPath(xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/path_elements/quadratic.py b/skeinforge/fabmetheus_utilities/geometry/geometry_tools/path_elements/quadratic.py deleted file mode 100644 index 3647e19..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/path_elements/quadratic.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Quadratic vertexes. - -From: -http://www.w3.org/TR/SVG/paths.html#PathDataQuadraticBezierCommands - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import svg_reader - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getQuadraticPath(xmlElement): - """Get the quadratic path.""" - end = evaluate.getVector3FromXMLElement(xmlElement) - previousXMLElement = xmlElement.getPreviousXMLElement() - if previousXMLElement is None: - print('Warning, can not get previousXMLElement in getQuadraticPath in quadratic for:') - print(xmlElement) - return [end] - begin = xmlElement.getPreviousVertex(Vector3()) - controlPoint = evaluate.getVector3ByPrefix(None, 'controlPoint', xmlElement) - if controlPoint is None: - oldControlPoint = evaluate.getVector3ByPrefixes(['controlPoint','controlPoint1'], None, previousXMLElement) - if oldControlPoint is None: - oldControlPoint = end - controlPoint = begin + begin - oldControlPoint - evaluate.addVector3ToXMLElement('controlPoint', controlPoint, xmlElement) - return svg_reader.getQuadraticPoints(begin, controlPoint, end, lineation.getNumberOfBezierPoints(begin, end, xmlElement)) - -def processXMLElement(xmlElement): - """Process the xml element.""" - xmlElement.parent.xmlObject.vertexes += getQuadraticPath(xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/vertex.py b/skeinforge/fabmetheus_utilities/geometry/geometry_tools/vertex.py deleted file mode 100644 index 4d34c23..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_tools/vertex.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Vertex of a triangle mesh. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities import xml_simple_reader - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addGeometryList( vertexes, xmlElement ): - """Add vertex elements to an xml element.""" - for vertex in vertexes: - vertexElement = getUnboundVertexElement(vertex) - vertexElement.parent = xmlElement - xmlElement.children.append( vertexElement ) - -def addVertexToAttributeDictionary(attributeDictionary, vertex): - """Add to the attribute dictionary.""" - if vertex.x != 0.0: - attributeDictionary['x'] = str(vertex.x) - if vertex.y != 0.0: - attributeDictionary['y'] = str(vertex.y) - if vertex.z != 0.0: - attributeDictionary['z'] = str(vertex.z) - -def getUnboundVertexElement(vertex): - """Add vertex element to an xml element.""" - vertexElement = xml_simple_reader.XMLElement() - addVertexToAttributeDictionary(vertexElement.attributeDictionary, vertex) - vertexElement.className = 'vertex' - return vertexElement - -def processXMLElement(xmlElement): - """Process the xml element.""" - xmlElement.parent.xmlObject.vertexes.append(evaluate.getVector3FromXMLElement(xmlElement)) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/__init__.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/__init__.py deleted file mode 100644 index cefa3e7..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -This page is in the table of contents. -This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -""" -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/boolean_geometry.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/boolean_geometry.py deleted file mode 100644 index 371ee68..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/boolean_geometry.py +++ /dev/null @@ -1,203 +0,0 @@ -""" -This page is in the table of contents. -The xml.py script is an import translator plugin to get a carving from an Art of Illusion xml file. - -An import plugin is a script in the interpret_plugins folder which has the function getCarving. It is meant to be run from the interpret tool. To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name. - -The getCarving function takes the file name of an xml file and returns the carving. - -An xml file can be exported from Art of Illusion by going to the "File" menu, then going into the "Export" menu item, then picking the XML choice. This will bring up the XML file chooser window, choose a place to save the file then click "OK". Leave the "compressFile" checkbox unchecked. All the objects from the scene will be exported, this plugin will ignore the light and camera. If you want to fabricate more than one object at a time, you can have multiple objects in the Art of Illusion scene and they will all be carved, then fabricated together. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities.evaluate_elements import setting -from fabmetheus_utilities.geometry.geometry_utilities import boolean_solid -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import settings -from fabmetheus_utilities import xml_simple_writer -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getEmptyZLoops(archivableObjects, importRadius, shouldPrintWarning, z, zoneArrangement): - """Get loops at empty z level.""" - emptyZ = zoneArrangement.getEmptyZ(z) - visibleObjects = evaluate.getVisibleObjects(archivableObjects) - visibleObjectLoopsList = boolean_solid.getVisibleObjectLoopsList(importRadius, visibleObjects, emptyZ) - loops = euclidean.getConcatenatedList(visibleObjectLoopsList) - if euclidean.isLoopListIntersecting(loops): - loops = boolean_solid.getLoopsUnified(importRadius, visibleObjectLoopsList) - if shouldPrintWarning: - print('Warning, the triangle mesh slice intersects itself in getExtruderPaths in boolean_geometry.') - print( 'Something will still be printed, but there is no guarantee that it will be the correct shape.' ) - print('Once the gcode is saved, you should check over the layer with a z of:') - print(z) - return loops - -def getMinimumZ(geometryObject): - """Get the minimum of the minimum z of the archivableObjects and the object.""" - booleanGeometry = BooleanGeometry() - booleanGeometry.archivableObjects = geometryObject.archivableObjects - booleanGeometry.importRadius = setting.getImportRadius(geometryObject.xmlElement) - booleanGeometry.layerThickness = setting.getLayerThickness(geometryObject.xmlElement) - archivableMinimumZ = booleanGeometry.getMinimumZ() - geometryMinimumZ = geometryObject.getMinimumZ() - if archivableMinimumZ is None and geometryMinimumZ is None: - return None - if archivableMinimumZ is None: - return geometryMinimumZ - if geometryMinimumZ is None: - return archivableMinimumZ - return min(archivableMinimumZ, geometryMinimumZ) - - -class BooleanGeometry: - """A boolean geometry scene.""" - def __init__(self): - """Add empty lists.""" - self.archivableObjects = [] - self.belowLoops = [] - self.infillInDirectionOfBridge = False - self.importRadius = 0.6 - self.layerThickness = 0.4 - self.rotatedLoopLayers = [] - - def __repr__(self): - """Get the string representation of this carving.""" - xmlElement = None - if len(self.archivableObjects) > 0: - xmlElement = self.archivableObjects[0].xmlElement - output = xml_simple_writer.getBeginGeometryXMLOutput(xmlElement) - self.addXML( 1, output ) - return xml_simple_writer.getEndGeometryXMLString(output) - - def addXML(self, depth, output): - """Add xml for this object.""" - xml_simple_writer.addXMLFromObjects( depth, self.archivableObjects, output ) - - def getCarveCornerMaximum(self): - """Get the corner maximum of the vertexes.""" - return self.cornerMaximum - - def getCarveCornerMinimum(self): - """Get the corner minimum of the vertexes.""" - return self.cornerMinimum - - def getCarveLayerThickness(self): - """Get the layer thickness.""" - return self.layerThickness - - def getCarveRotatedBoundaryLayers(self): - """Get the rotated boundary layers.""" - if self.getMinimumZ() is None: - return [] - z = self.minimumZ + self.halfHeight - while z < self.maximumZ: - z = self.getZAddExtruderPaths(z) - self.cornerMaximum = Vector3(-912345678.0, -912345678.0, -912345678.0) - self.cornerMinimum = Vector3(912345678.0, 912345678.0, 912345678.0) - for rotatedLoopLayer in self.rotatedLoopLayers: - for loop in rotatedLoopLayer.loops: - for point in loop: - pointVector3 = Vector3(point.real, point.imag, rotatedLoopLayer.z) - self.cornerMaximum.maximize(pointVector3) - self.cornerMinimum.minimize(pointVector3) - self.cornerMaximum.z += self.halfHeight - self.cornerMinimum.z -= self.halfHeight - for rotatedLoopLayerIndex in xrange(len(self.rotatedLoopLayers) -1, -1, -1): - rotatedLoopLayer = self.rotatedLoopLayers[rotatedLoopLayerIndex] - if len(rotatedLoopLayer.loops) > 0: - return self.rotatedLoopLayers[: rotatedLoopLayerIndex + 1] - return [] - - def getFabmetheusXML(self): - """Return the fabmetheus XML.""" - if len(self.archivableObjects) > 0: - return self.archivableObjects[0].xmlElement.getParser().getOriginalRoot() - return None - - def getInterpretationSuffix(self): - """Return the suffix for a boolean carving.""" - return 'xml' - - def getMatrix4X4(self): - """Get the matrix4X4.""" - return None - - def getMatrixChainTetragrid(self): - """Get the matrix chain tetragrid.""" - return None - - def getMinimumZ(self): - """Get the minimum z.""" - vertexes = [] - for visibleObject in evaluate.getVisibleObjects(self.archivableObjects): - vertexes += visibleObject.getTransformedVertexes() - if len(vertexes) < 1: - return None - self.maximumZ = -912345678.0 - self.minimumZ = 912345678.0 - for vertex in vertexes: - self.maximumZ = max(self.maximumZ, vertex.z) - self.minimumZ = min(self.minimumZ, vertex.z) - self.zoneArrangement = triangle_mesh.ZoneArrangement(self.layerThickness, vertexes) - self.halfHeight = 0.5 * self.layerThickness - self.setActualMinimumZ() - return self.minimumZ - - def getNumberOfEmptyZLoops(self, z): - """Get number of empty z loops.""" - return len(getEmptyZLoops(self.archivableObjects, self.importRadius, False, z, self.zoneArrangement)) - - def getZAddExtruderPaths(self, z): - """Get next z and add extruder loops.""" - settings.printProgress(len(self.rotatedLoopLayers), 'slice') - rotatedLoopLayer = euclidean.RotatedLoopLayer(z) - rotatedLoopLayer.loops = getEmptyZLoops(self.archivableObjects, self.importRadius, True, z, self.zoneArrangement) - return triangle_mesh.getZAddExtruderPathsBySolidCarving(rotatedLoopLayer, self, z) - - def setActualMinimumZ(self): - """Get the actual minimum z at the lowest rotated boundary layer.""" - halfHeightOverMyriad = 0.0001 * self.halfHeight - while self.minimumZ < self.maximumZ: - if self.getNumberOfEmptyZLoops(self.minimumZ + halfHeightOverMyriad) > 0: - if self.getNumberOfEmptyZLoops(self.minimumZ - halfHeightOverMyriad) < 1: - return - increment = -self.halfHeight - while abs(increment) > halfHeightOverMyriad: - self.minimumZ += increment - increment = 0.5 * abs(increment) - if self.getNumberOfEmptyZLoops(self.minimumZ) > 0: - increment = -increment - self.minimumZ = round(self.minimumZ, -int(round(math.log10(halfHeightOverMyriad) + 1.5))) - return - self.minimumZ += self.layerThickness - - def setCarveInfillInDirectionOfBridge( self, infillInDirectionOfBridge ): - """Set the infill in direction of bridge.""" - self.infillInDirectionOfBridge = infillInDirectionOfBridge - - def setCarveLayerThickness( self, layerThickness ): - """Set the layer thickness.""" - self.layerThickness = layerThickness - - def setCarveImportRadius( self, importRadius ): - """Set the import radius.""" - self.importRadius = importRadius - - def setCarveIsCorrectMesh( self, isCorrectMesh ): - """Set the is correct mesh flag.""" - self.isCorrectMesh = isCorrectMesh diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/boolean_solid.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/boolean_solid.py deleted file mode 100644 index 2cc4a76..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/boolean_solid.py +++ /dev/null @@ -1,236 +0,0 @@ -""" -This page is in the table of contents. -The xml.py script is an import translator plugin to get a carving from an Art of Illusion xml file. - -An import plugin is a script in the interpret_plugins folder which has the function getCarving. It is meant to be run from the interpret tool. To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name. - -The getCarving function takes the file name of an xml file and returns the carving. - -An xml file can be exported from Art of Illusion by going to the "File" menu, then going into the "Export" menu item, then picking the XML choice. This will bring up the XML file chooser window, choose a place to save the file then click "OK". Leave the "compressFile" checkbox unchecked. All the objects from the scene will be exported, this plugin will ignore the light and camera. If you want to fabricate more than one object at a time, you can have multiple objects in the Art of Illusion scene and they will all be carved, then fabricated together. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities.evaluate_elements import setting -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.solids import group -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addLineLoopsIntersections( loopLoopsIntersections, loops, pointBegin, pointEnd ): - """Add intersections of the line with the loops.""" - normalizedSegment = pointEnd - pointBegin - normalizedSegmentLength = abs( normalizedSegment ) - if normalizedSegmentLength <= 0.0: - return - lineLoopsIntersections = [] - normalizedSegment /= normalizedSegmentLength - segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) - pointBeginRotated = segmentYMirror * pointBegin - pointEndRotated = segmentYMirror * pointEnd - addLoopsXSegmentIntersections( lineLoopsIntersections, loops, pointBeginRotated.real, pointEndRotated.real, segmentYMirror, pointBeginRotated.imag ) - for lineLoopsIntersection in lineLoopsIntersections: - point = complex( lineLoopsIntersection, pointBeginRotated.imag ) * normalizedSegment - loopLoopsIntersections.append(point) - -def addLineXSegmentIntersection( lineLoopsIntersections, segmentFirstX, segmentSecondX, vector3First, vector3Second, y ): - """Add intersections of the line with the x segment.""" - xIntersection = euclidean.getXIntersectionIfExists( vector3First, vector3Second, y ) - if xIntersection is None: - return - if xIntersection < min( segmentFirstX, segmentSecondX ): - return - if xIntersection <= max( segmentFirstX, segmentSecondX ): - lineLoopsIntersections.append( xIntersection ) - -def addLoopLoopsIntersections( loop, loopsLoopsIntersections, otherLoops ): - """Add intersections of the loop with the other loops.""" - for pointIndex in xrange(len(loop)): - pointBegin = loop[pointIndex] - pointEnd = loop[(pointIndex + 1) % len(loop)] - addLineLoopsIntersections( loopsLoopsIntersections, otherLoops, pointBegin, pointEnd ) - -def addLoopsXSegmentIntersections( lineLoopsIntersections, loops, segmentFirstX, segmentSecondX, segmentYMirror, y ): - """Add intersections of the loops with the x segment.""" - for loop in loops: - addLoopXSegmentIntersections( lineLoopsIntersections, loop, segmentFirstX, segmentSecondX, segmentYMirror, y ) - -def addLoopXSegmentIntersections( lineLoopsIntersections, loop, segmentFirstX, segmentSecondX, segmentYMirror, y ): - """Add intersections of the loop with the x segment.""" - rotatedLoop = euclidean.getPointsRoundZAxis( segmentYMirror, loop ) - for pointIndex in xrange( len( rotatedLoop ) ): - pointFirst = rotatedLoop[pointIndex] - pointSecond = rotatedLoop[ (pointIndex + 1) % len( rotatedLoop ) ] - addLineXSegmentIntersection( lineLoopsIntersections, segmentFirstX, segmentSecondX, pointFirst, pointSecond, y ) - -def getInBetweenLoopsFromLoops(loops, radius): - """Get the in between loops from loops.""" - inBetweenLoops = [] - for loop in loops: - inBetweenLoop = [] - for pointIndex in xrange(len(loop)): - pointBegin = loop[pointIndex] - pointEnd = loop[(pointIndex + 1) % len(loop)] - intercircle.addPointsFromSegment(pointBegin, pointEnd, inBetweenLoop, radius) - inBetweenLoops.append(inBetweenLoop) - return inBetweenLoops - -def getInsetPointsByInsetLoop( insetLoop, inside, loops, radius ): - """Get the inset points of the inset loop inside the loops.""" - insetPointsByInsetLoop = [] - for pointIndex in xrange( len( insetLoop ) ): - pointBegin = insetLoop[ ( pointIndex + len( insetLoop ) - 1 ) % len( insetLoop ) ] - pointCenter = insetLoop[pointIndex] - pointEnd = insetLoop[ (pointIndex + 1) % len( insetLoop ) ] - if getIsInsetPointInsideLoops( inside, loops, pointBegin, pointCenter, pointEnd, radius ): - insetPointsByInsetLoop.append( pointCenter ) - return insetPointsByInsetLoop - -def getInsetPointsByInsetLoops( insetLoops, inside, loops, radius ): - """Get the inset points of the inset loops inside the loops.""" - insetPointsByInsetLoops = [] - for insetLoop in insetLoops: - insetPointsByInsetLoops += getInsetPointsByInsetLoop( insetLoop, inside, loops, radius ) - return insetPointsByInsetLoops - -def getIsInsetPointInsideLoops( inside, loops, pointBegin, pointCenter, pointEnd, radius ): - """Determine if the inset point is inside the loops.""" - centerMinusBegin = euclidean.getNormalized( pointCenter - pointBegin ) - centerMinusBeginWiddershins = complex( - centerMinusBegin.imag, centerMinusBegin.real ) - endMinusCenter = euclidean.getNormalized( pointEnd - pointCenter ) - endMinusCenterWiddershins = complex( - endMinusCenter.imag, endMinusCenter.real ) - widdershinsNormalized = euclidean.getNormalized( centerMinusBeginWiddershins + endMinusCenterWiddershins ) * radius - return euclidean.getIsInFilledRegion( loops, pointCenter + widdershinsNormalized ) == inside - -def getLoopsDifference(importRadius, loopLists): - """Get difference loops.""" - halfImportRadius = 0.5 * importRadius # so that there are no misses on shallow angles - radiusSide = 0.01 * importRadius - negativeLoops = getLoopsUnified(importRadius, loopLists[1 :]) - intercircle.directLoops(False, negativeLoops) - positiveLoops = loopLists[0] - intercircle.directLoops(True, positiveLoops) - corners = getInsetPointsByInsetLoops(negativeLoops, True, positiveLoops, radiusSide) - corners += getInsetPointsByInsetLoops(positiveLoops, False, negativeLoops, radiusSide) - allPoints = corners[:] - allPoints += getInsetPointsByInsetLoops(getInBetweenLoopsFromLoops(negativeLoops, halfImportRadius), True, positiveLoops, radiusSide) - allPoints += getInsetPointsByInsetLoops(getInBetweenLoopsFromLoops(positiveLoops, halfImportRadius), False, negativeLoops, radiusSide) - return triangle_mesh.getDescendingAreaOrientedLoops(allPoints, corners, importRadius) - -def getLoopsIntersection(importRadius, loopLists): - """Get intersection loops.""" - intercircle.directLoopLists( True, loopLists ) - if len(loopLists) < 1: - return [] - if len(loopLists) < 2: - return loopLists[0] - intercircle.directLoopLists(True, loopLists) - loopsIntersection = loopLists[0] - for loopList in loopLists[1 :]: - loopsIntersection = getLoopsIntersectionByPair( importRadius, loopsIntersection, loopList ) - return loopsIntersection - -def getLoopsIntersectionByPair(importRadius, loopsFirst, loopsLast): - """Get intersection loops for a pair of loop lists.""" - halfImportRadius = 0.5 * importRadius # so that there are no misses on shallow angles - radiusSide = 0.01 * importRadius - corners = [] - corners += getInsetPointsByInsetLoops(loopsFirst, True, loopsLast, radiusSide) - corners += getInsetPointsByInsetLoops(loopsLast, True, loopsFirst, radiusSide) - allPoints = corners[:] - allPoints += getInsetPointsByInsetLoops(getInBetweenLoopsFromLoops(loopsFirst, halfImportRadius), True, loopsLast, radiusSide) - allPoints += getInsetPointsByInsetLoops(getInBetweenLoopsFromLoops(loopsLast, halfImportRadius), True, loopsFirst, radiusSide) - return triangle_mesh.getDescendingAreaOrientedLoops(allPoints, corners, importRadius) - -def getLoopsListsIntersections( loopsList ): - """Get intersections betweens the loops lists.""" - loopsListsIntersections = [] - for loopsIndex in xrange( len( loopsList ) ): - loops = loopsList[ loopsIndex ] - for otherLoops in loopsList[ : loopsIndex ]: - loopsListsIntersections += getLoopsLoopsIntersections( loops, otherLoops ) - return loopsListsIntersections - -def getLoopsLoopsIntersections( loops, otherLoops ): - """Get all the intersections of the loops with the other loops.""" - loopsLoopsIntersections = [] - for loop in loops: - addLoopLoopsIntersections( loop, loopsLoopsIntersections, otherLoops ) - return loopsLoopsIntersections - -def getLoopsUnified(importRadius, loopLists): - """Get joined loops sliced through shape.""" - allPoints = [] - corners = getLoopsListsIntersections(loopLists) - radiusSide = 0.01 * importRadius - radiusSideNegative = -radiusSide - intercircle.directLoopLists(True, loopLists) - for loopListIndex in xrange(len(loopLists)): - insetLoops = loopLists[ loopListIndex ] - inBetweenInsetLoops = getInBetweenLoopsFromLoops(insetLoops, importRadius) - otherLoops = euclidean.getConcatenatedList(loopLists[: loopListIndex] + loopLists[loopListIndex + 1 :]) - corners += getInsetPointsByInsetLoops(insetLoops, False, otherLoops, radiusSide) - allPoints += getInsetPointsByInsetLoops(inBetweenInsetLoops, False, otherLoops, radiusSideNegative) - allPoints += corners[:] - return triangle_mesh.getDescendingAreaOrientedLoops(allPoints, corners, importRadius) - -def getVisibleObjectLoopsList( importRadius, visibleObjects, z ): - """Get visible object loops list.""" - visibleObjectLoopsList = [] - for visibleObject in visibleObjects: - visibleObjectLoops = visibleObject.getLoops(importRadius, z) - visibleObjectLoopsList.append( visibleObjectLoops ) - return visibleObjectLoopsList - - -class BooleanSolid( group.Group ): - """A boolean solid object.""" - def getDifference(self, importRadius, visibleObjectLoopsList): - """Get subtracted loops sliced through shape.""" - return getLoopsDifference(importRadius, visibleObjectLoopsList) - - def getIntersection(self, importRadius, visibleObjectLoopsList): - """Get intersected loops sliced through shape.""" - return getLoopsIntersection(importRadius, visibleObjectLoopsList) - - def getLoops(self, importRadius, z): - """Get loops sliced through shape.""" - visibleObjects = evaluate.getVisibleObjects(self.archivableObjects) - if len( visibleObjects ) < 1: - return [] - visibleObjectLoopsList = getVisibleObjectLoopsList( importRadius, visibleObjects, z ) - loops = self.getLoopsFromObjectLoopsList(importRadius, visibleObjectLoopsList) - return euclidean.getSimplifiedLoops( loops, importRadius ) - - def getLoopsFromObjectLoopsList(self, importRadius, visibleObjectLoopsList): - """Get loops from visible object loops list.""" - return self.operationFunction(importRadius, visibleObjectLoopsList) - - def getTransformedPaths(self): - """Get all transformed paths.""" - importRadius = setting.getImportRadius(self.xmlElement) - loopsFromObjectLoopsList = self.getLoopsFromObjectLoopsList(importRadius, self.getComplexTransformedPathLists()) - return euclidean.getVector3Paths(loopsFromObjectLoopsList) - - def getUnion(self, importRadius, visibleObjectLoopsList): - """Get joined loops sliced through shape.""" - return getLoopsUnified(importRadius, visibleObjectLoopsList) - - def getXMLClassName(self): - """Get xml class name.""" - return self.operationFunction.__name__.lower()[ len('get') : ] diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate.py deleted file mode 100644 index c193206..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate.py +++ /dev/null @@ -1,1937 +0,0 @@ -""" -Boolean geometry utilities. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities.evaluate_elements import setting -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -import math -import os -import sys -import traceback - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalModuleFunctionsDictionary = {} - - -def addQuoteWord(evaluatorWords, word): - """Add quote word and remainder if the word starts with a quote character or dollar sign, otherwise add the word.""" - if len(word) < 2: - evaluatorWords.append(word) - return - firstCharacter = word[0] - if firstCharacter == '$': - dotIndex = word.find('.', 1) - if dotIndex > -1: - evaluatorWords.append(word[: dotIndex]) - evaluatorWords.append(word[dotIndex :]) - return - if firstCharacter != '"' and firstCharacter != "'": - evaluatorWords.append(word) - return - nextQuoteIndex = word.find(firstCharacter, 1) - if nextQuoteIndex < 0 or nextQuoteIndex == len(word) - 1: - evaluatorWords.append(word) - return - nextQuoteIndex += 1 - evaluatorWords.append(word[: nextQuoteIndex]) - evaluatorWords.append(word[nextQuoteIndex :]) - -def addPrefixDictionary(dictionary, keys, value): - """Add prefixed key values to dictionary.""" - for key in keys: - dictionary[key.lstrip('_')] = value - -def addToPathsRecursively(paths, vector3Lists): - """Add to vector3 paths recursively.""" - if vector3Lists.__class__ == Vector3 or vector3Lists.__class__ .__name__ == 'Vector3Index': - paths.append([ vector3Lists ]) - return - path = [] - for vector3List in vector3Lists: - if vector3List.__class__ == list: - addToPathsRecursively(paths, vector3List) - elif vector3List.__class__ == Vector3: - path.append(vector3List) - if len(path) > 0: - paths.append(path) - -def addValueToEvaluatedDictionary(evaluatedDictionary, key, xmlElement): - """Get the evaluated dictionary.""" - value = getEvaluatedValueObliviously(key, xmlElement) - if value is None: - valueString = str(xmlElement.attributeDictionary[key]) - print('Warning, addValueToEvaluatedDictionary in evaluate can not get a value for:') - print(valueString) - evaluatedDictionary[key + '__Warning__'] = 'Can not evaluate: ' + valueString.replace('"', ' ').replace( "'", ' ') - else: - evaluatedDictionary[key] = value - -def addVector3ToXMLElement(key, vector3, xmlElement): - """Add vector3 to xml element.""" - xmlElement.attributeDictionary[key] = '[%s,%s,%s]' % (vector3.x, vector3.y, vector3.z) - -def compareExecutionOrderAscending(module, otherModule): - """Get comparison in order to sort modules in ascending execution order.""" - if module.globalExecutionOrder < otherModule.globalExecutionOrder: - return -1 - if module.globalExecutionOrder > otherModule.globalExecutionOrder: - return 1 - if module.__name__ < otherModule.__name__: - return -1 - return int(module.__name__ > otherModule.__name__) - -def convertToPaths(dictionary): - """Recursively convert any XMLElements to paths.""" - if dictionary.__class__ == Vector3 or dictionary.__class__.__name__ == 'Vector3Index': - return - keys = getKeys(dictionary) - if keys is None: - return - for key in keys: - value = dictionary[key] - if value.__class__.__name__ == 'XMLElement': - if value.xmlObject is not None: - dictionary[key] = getFloatListListsByPaths(value.xmlObject.getPaths()) - else: - convertToPaths(dictionary[key]) - -def convertToTransformedPaths(dictionary): - """Recursively convert any XMLElements to paths.""" - if dictionary.__class__ == Vector3 or dictionary.__class__.__name__ == 'Vector3Index': - return - keys = getKeys(dictionary) - if keys is None: - return - for key in keys: - value = dictionary[key] - if value.__class__.__name__ == 'XMLElement': - if value.xmlObject is not None: - dictionary[key] = value.xmlObject.getTransformedPaths() - else: - convertToTransformedPaths(dictionary[key]) - -def executeLeftOperations( evaluators, operationLevel ): - """Evaluate the expression value from the numeric and operation evaluators.""" - for negativeIndex in xrange( - len(evaluators), - 1 ): - evaluatorIndex = negativeIndex + len(evaluators) - evaluators[evaluatorIndex].executeLeftOperation( evaluators, evaluatorIndex, operationLevel ) - -def executeNextEvaluatorArguments(evaluator, evaluators, evaluatorIndex, nextEvaluator): - """Execute the nextEvaluator arguments.""" - if evaluator.value is None: - print('Warning, executeNextEvaluatorArguments in evaluate can not get a evaluator.value for:') - print(evaluatorIndex) - print(evaluators) - print(evaluator) - return - nextEvaluator.value = evaluator.value(*nextEvaluator.arguments) - del evaluators[evaluatorIndex] - -def executePairOperations(evaluators, operationLevel): - """Evaluate the expression value from the numeric and operation evaluators.""" - for negativeIndex in xrange(1 - len(evaluators), - 1): - evaluatorIndex = negativeIndex + len(evaluators) - evaluators[evaluatorIndex].executePairOperation(evaluators, evaluatorIndex, operationLevel) - -def getBracketEvaluators(bracketBeginIndex, bracketEndIndex, evaluators): - """Get the bracket evaluators.""" - return getEvaluatedExpressionValueEvaluators(evaluators[bracketBeginIndex + 1 : bracketEndIndex]) - -def getBracketsExist(evaluators): - """Evaluate the expression value.""" - bracketBeginIndex = None - for negativeIndex in xrange( - len(evaluators), 0 ): - bracketEndIndex = negativeIndex + len(evaluators) - evaluatorEnd = evaluators[ bracketEndIndex ] - evaluatorWord = evaluatorEnd.word - if evaluatorWord in ['(', '[', '{']: - bracketBeginIndex = bracketEndIndex - elif evaluatorWord in [')', ']', '}']: - if bracketBeginIndex is None: - print('Warning, bracketBeginIndex in evaluateBrackets in evaluate is None.') - print('This may be because the brackets are not balanced.') - print(evaluators) - del evaluators[ bracketEndIndex ] - return - evaluators[ bracketBeginIndex ].executeBracket(bracketBeginIndex, bracketEndIndex, evaluators) - evaluators[ bracketBeginIndex ].word = None - return True - return False - -def getBracketValuesDeleteEvaluator(bracketBeginIndex, bracketEndIndex, evaluators): - """Get the bracket values and delete the evaluator.""" - evaluatedExpressionValueEvaluators = getBracketEvaluators(bracketBeginIndex, bracketEndIndex, evaluators) - bracketValues = [] - for evaluatedExpressionValueEvaluator in evaluatedExpressionValueEvaluators: - bracketValues.append( evaluatedExpressionValueEvaluator.value ) - del evaluators[ bracketBeginIndex + 1: bracketEndIndex + 1 ] - return bracketValues - -def getCapitalizedSuffixKey(prefix, suffix): - """Get key with capitalized suffix.""" - if prefix == '' or prefix.endswith('.'): - return prefix + suffix - return prefix + suffix[:1].upper()+suffix[1:] - -def getDictionarySplitWords(dictionary, value): - """Get split line for evaluators.""" - if getIsQuoted(value): - return [value] - for dictionaryKey in dictionary.keys(): - value = value.replace(dictionaryKey, ' ' + dictionaryKey + ' ') - dictionarySplitWords = [] - for word in value.split(): - dictionarySplitWords.append(word) - return dictionarySplitWords - -def getEndIndexConvertEquationValue( bracketEndIndex, evaluatorIndex, evaluators ): - """Get the bracket end index and convert the equation value evaluators into a string.""" - evaluator = evaluators[evaluatorIndex] - if evaluator.__class__ != EvaluatorValue: - return bracketEndIndex - if not evaluator.word.startswith('equation.'): - return bracketEndIndex - if evaluators[ evaluatorIndex + 1 ].word != ':': - return bracketEndIndex - valueBeginIndex = evaluatorIndex + 2 - equationValueString = '' - for valueEvaluatorIndex in xrange( valueBeginIndex, len(evaluators) ): - valueEvaluator = evaluators[ valueEvaluatorIndex ] - if valueEvaluator.word == ',' or valueEvaluator.word == '}': - if equationValueString == '': - return bracketEndIndex - else: - evaluators[ valueBeginIndex ] = EvaluatorValue( equationValueString ) - valueDeleteIndex = valueBeginIndex + 1 - del evaluators[ valueDeleteIndex : valueEvaluatorIndex ] - return bracketEndIndex - valueEvaluatorIndex + valueDeleteIndex - equationValueString += valueEvaluator.word - return bracketEndIndex - -def getEvaluatedBoolean(defaultValue, key, xmlElement): - """Get the evaluated boolean.""" - if xmlElement is None: - return defaultValue - if key in xmlElement.attributeDictionary: - return euclidean.getBooleanFromValue(getEvaluatedValueObliviously(key, xmlElement)) - return defaultValue - -def getEvaluatedDictionaryByCopyKeys(copyKeys, xmlElement): - """Get the evaluated dictionary by copyKeys.""" - evaluatedDictionary = {} - for key in xmlElement.attributeDictionary.keys(): - if key in copyKeys: - evaluatedDictionary[key] = xmlElement.attributeDictionary[key] - else: - addValueToEvaluatedDictionary(evaluatedDictionary, key, xmlElement) - return evaluatedDictionary - -def getEvaluatedDictionaryByEvaluationKeys(evaluationKeys, xmlElement): - """Get the evaluated dictionary.""" - evaluatedDictionary = {} - for key in xmlElement.attributeDictionary.keys(): - if key in evaluationKeys: - addValueToEvaluatedDictionary(evaluatedDictionary, key, xmlElement) - return evaluatedDictionary - -def getEvaluatedExpressionValue(value, xmlElement): - """Evaluate the expression value.""" - try: - return getEvaluatedExpressionValueBySplitLine( getEvaluatorSplitWords(value), xmlElement ) - except: - print('Warning, in getEvaluatedExpressionValue in evaluate could not get a value for:') - print(value) - traceback.print_exc(file=sys.stdout) - return None - -def getEvaluatedExpressionValueBySplitLine(words, xmlElement): - """Evaluate the expression value.""" - evaluators = [] - for wordIndex, word in enumerate(words): - nextWord = '' - nextWordIndex = wordIndex + 1 - if nextWordIndex < len(words): - nextWord = words[nextWordIndex] - evaluator = getEvaluator(evaluators, nextWord, word, xmlElement) - if evaluator is not None: - evaluators.append(evaluator) - while getBracketsExist(evaluators): - pass - evaluatedExpressionValueEvaluators = getEvaluatedExpressionValueEvaluators(evaluators) - if len( evaluatedExpressionValueEvaluators ) > 0: - return evaluatedExpressionValueEvaluators[0].value - return None - -def getEvaluatedExpressionValueEvaluators(evaluators): - """Evaluate the expression value from the numeric and operation evaluators.""" - for evaluatorIndex, evaluator in enumerate(evaluators): - evaluator.executeCenterOperation(evaluators, evaluatorIndex) - for negativeIndex in xrange(1 - len(evaluators), 0): - evaluatorIndex = negativeIndex + len(evaluators) - evaluators[evaluatorIndex].executeRightOperation(evaluators, evaluatorIndex) - executeLeftOperations(evaluators, 200) - for operationLevel in [80, 60, 40, 20, 15]: - executePairOperations(evaluators, operationLevel) - executeLeftOperations(evaluators, 13) - executePairOperations(evaluators, 12) - for negativeIndex in xrange(-len(evaluators), 0): - evaluatorIndex = negativeIndex + len(evaluators) - evaluators[evaluatorIndex].executePairOperation(evaluators, evaluatorIndex, 10) - for evaluatorIndex in xrange(len(evaluators) - 1, -1, -1): - evaluators[evaluatorIndex].executePairOperation(evaluators, evaluatorIndex, 0) - return evaluators - -def getEvaluatedFloat(defaultValue, key, xmlElement): - """Get the evaluated float.""" - if xmlElement is None: - return defaultValue - if key in xmlElement.attributeDictionary: - return euclidean.getFloatFromValue(getEvaluatedValueObliviously(key, xmlElement)) - return defaultValue - -def getEvaluatedFloatByKeys(defaultValue, keys, xmlElement): - """Get the evaluated float by keys.""" - for key in keys: - defaultValue = getEvaluatedFloat(defaultValue, key, xmlElement) - return defaultValue - -def getEvaluatedInt(defaultValue, key, xmlElement): - """Get the evaluated int.""" - if xmlElement is None: - return None - if key in xmlElement.attributeDictionary: - try: - return getIntFromFloatString(getEvaluatedValueObliviously(key, xmlElement)) - except: - print('Warning, could not evaluate the int.') - print(key) - print(xmlElement.attributeDictionary[key]) - return defaultValue - -def getEvaluatedIntByKeys(defaultValue, keys, xmlElement): - """Get the evaluated int by keys.""" - for key in keys: - defaultValue = getEvaluatedInt(defaultValue, key, xmlElement) - return defaultValue - -def getEvaluatedLinkValue(word, xmlElement): - """Get the evaluated link value.""" - if word == '': - return '' - if getStartsWithCurlyEqualRoundSquare(word): - return getEvaluatedExpressionValue(word, xmlElement) - return word - -def getEvaluatedString(defaultValue, key, xmlElement): - """Get the evaluated string.""" - if xmlElement is None: - return defaultValue - if key in xmlElement.attributeDictionary: - return str(getEvaluatedValueObliviously(key, xmlElement)) - return defaultValue - -def getEvaluatedValue(defaultValue, key, xmlElement): - """Get the evaluated value.""" - if xmlElement is None: - return defaultValue - if key in xmlElement.attributeDictionary: - return getEvaluatedValueObliviously(key, xmlElement) - return defaultValue - -def getEvaluatedValueObliviously(key, xmlElement): - """Get the evaluated value.""" - value = str(xmlElement.attributeDictionary[key]).strip() - if key == 'id' or key == 'name' or key == 'tags': - return value - return getEvaluatedLinkValue(value, xmlElement) - -def getEvaluator(evaluators, nextWord, word, xmlElement): - """Get the evaluator.""" - if word in globalSplitDictionary: - return globalSplitDictionary[word](word, xmlElement) - firstCharacter = word[: 1] - if firstCharacter == "'" or firstCharacter == '"': - if len(word) > 1: - if firstCharacter == word[-1]: - return EvaluatorValue(word[1 : -1]) - if firstCharacter == '$': - return EvaluatorValue(word[1 :]) - dotIndex = word.find('.') - functions = xmlElement.getXMLProcessor().functions - if dotIndex > -1 and len(word) > 1: - if dotIndex == 0 and word[1].isalpha(): - return EvaluatorAttribute(word, xmlElement) - if dotIndex > 0: - untilDot = word[: dotIndex] - if untilDot in globalModuleEvaluatorDictionary: - return globalModuleEvaluatorDictionary[untilDot](word, xmlElement) - if len(functions) > 0: - if untilDot in functions[-1].localDictionary: - return EvaluatorLocal(word, xmlElement) - if firstCharacter.isalpha() or firstCharacter == '_': - if len(functions) > 0: - if word in functions[-1].localDictionary: - return EvaluatorLocal(word, xmlElement) - wordElement = xmlElement.getXMLElementByImportID(word) - if wordElement is not None: - if wordElement.className == 'class': - return EvaluatorClass(word, wordElement) - if wordElement.className == 'function': - return EvaluatorFunction(word, wordElement) - return EvaluatorValue(word) - return EvaluatorNumeric(word, xmlElement) - -def getEvaluatorSplitWords(value): - """Get split words for evaluators.""" - if value.startswith('='): - value = value[len('=') :] - if len(value) < 1: - return [] - global globalDictionaryOperatorBegin - uniqueQuoteIndex = 0 - word = '' - quoteString = None - quoteDictionary = {} - for characterIndex in xrange(len(value)): - character = value[characterIndex] - if character == '"' or character == "'": - if quoteString is None: - quoteString = '' - elif quoteString is not None: - if character == quoteString[: 1]: - uniqueQuoteIndex = getUniqueQuoteIndex(uniqueQuoteIndex, value) - uniqueToken = getTokenByNumber(uniqueQuoteIndex) - quoteDictionary[uniqueToken] = quoteString + character - character = uniqueToken - quoteString = None - if quoteString is None: - word += character - else: - quoteString += character - beginSplitWords = getDictionarySplitWords(globalDictionaryOperatorBegin, word) - global globalSplitDictionaryOperator - evaluatorSplitWords = [] - for beginSplitWord in beginSplitWords: - if beginSplitWord in globalDictionaryOperatorBegin: - evaluatorSplitWords.append(beginSplitWord) - else: - evaluatorSplitWords += getDictionarySplitWords(globalSplitDictionaryOperator, beginSplitWord) - for evaluatorSplitWordIndex, evaluatorSplitWord in enumerate(evaluatorSplitWords): - for quoteDictionaryKey in quoteDictionary.keys(): - if quoteDictionaryKey in evaluatorSplitWord: - evaluatorSplitWords[evaluatorSplitWordIndex] = evaluatorSplitWord.replace(quoteDictionaryKey, quoteDictionary[quoteDictionaryKey]) - evaluatorTransitionWords = [] - for evaluatorSplitWord in evaluatorSplitWords: - addQuoteWord(evaluatorTransitionWords, evaluatorSplitWord) - return evaluatorTransitionWords - -def getFloatListFromBracketedString( bracketedString ): - """Get list from a bracketed string.""" - if not getIsBracketed( bracketedString ): - return None - bracketedString = bracketedString.strip().replace('[', '').replace(']', '').replace('(', '').replace(')', '') - if len( bracketedString ) < 1: - return [] - splitLine = bracketedString.split(',') - floatList = [] - for word in splitLine: - evaluatedFloat = euclidean.getFloatFromValue(word) - if evaluatedFloat is not None: - floatList.append( evaluatedFloat ) - return floatList - -def getFloatListListsByPaths(paths): - """Get float lists by paths.""" - floatListLists = [] - for path in paths: - floatListList = [] - for point in path: - floatListList.append( point.getFloatList() ) - return floatListLists - -def getFromCreationEvaluatorPlugins( namePathDictionary, xmlElement ): - """Get the creation evaluator plugins if the xmlElement is from the creation evaluator.""" - if getEvaluatedBoolean( False, '_fromCreationEvaluator', xmlElement ): - return getMatchingPlugins( namePathDictionary, xmlElement ) - return [] - -def getKeys(repository): - """Get keys for repository.""" - repositoryClass = repository.__class__ - if repositoryClass == list or repositoryClass == tuple: - return range(len(repository)) - if repositoryClass == dict: - return repository.keys() - return None - -def getIntFromFloatString(value): - """Get the int from the string.""" - floatString = str(value).strip() - if floatString == '': - return None - dotIndex = floatString.find('.') - if dotIndex < 0: - return int(value) - return int( round( float(floatString) ) ) - -def getIsBracketed(word): - """Determine if the word is bracketed.""" - if len(word) < 2: - return False - firstCharacter = word[0] - lastCharacter = word[-1] - if firstCharacter == '(' and lastCharacter == ')': - return True - return firstCharacter == '[' and lastCharacter == ']' - -def getIsQuoted(word): - """Determine if the word is quoted.""" - if len(word) < 2: - return False - firstCharacter = word[0] - lastCharacter = word[-1] - if firstCharacter == '"' and lastCharacter == '"': - return True - return firstCharacter == "'" and lastCharacter == "'" - -def getLocalAttributeValueString(key, valueString): - """Get the local attribute value string with augmented assignment.""" - augmentedStatements = '+= -= *= /= %= **='.split() - for augmentedStatement in augmentedStatements: - if valueString.startswith(augmentedStatement): - return key + augmentedStatement[: -1] + valueString[len(augmentedStatement) :] - return valueString - -def getMatchingPlugins( namePathDictionary, xmlElement ): - """Get the plugins whose names are in the attribute dictionary.""" - matchingPlugins = [] - namePathDictionaryCopy = namePathDictionary.copy() - for key in xmlElement.attributeDictionary: - dotIndex = key.find('.') - if dotIndex > - 1: - keyUntilDot = key[: dotIndex] - if keyUntilDot in namePathDictionaryCopy: - pluginModule = archive.getModuleWithPath( namePathDictionaryCopy[ keyUntilDot ] ) - del namePathDictionaryCopy[ keyUntilDot ] - if pluginModule is not None: - matchingPlugins.append( pluginModule ) - return matchingPlugins - -def getNextChildIndex(xmlElement): - """Get the next child index.""" - for childIndex, child in enumerate( xmlElement.parent.children ): - if child == xmlElement: - return childIndex + 1 - return len( xmlElement.parent.children ) - -def getPathByKey(defaultPath, key, xmlElement): - """Get path from prefix and xml element.""" - if key not in xmlElement.attributeDictionary: - return defaultPath - word = str(xmlElement.attributeDictionary[key]).strip() - evaluatedLinkValue = getEvaluatedLinkValue(word, xmlElement) - if evaluatedLinkValue.__class__ == list: - return getPathByList(evaluatedLinkValue) - xmlElementObject = getXMLElementObject(evaluatedLinkValue) - if xmlElementObject is None: - return defaultPath - return xmlElementObject.getPaths()[0] - -def getPathByList(vertexList): - """Get the paths by list.""" - if len(vertexList) < 1: - return Vector3() - if vertexList[0].__class__ != list: - vertexList = [vertexList] - path = [] - for floatList in vertexList: - vector3 = getVector3ByFloatList(floatList, Vector3()) - path.append(vector3) - return path - -def getPathByPrefix(path, prefix, xmlElement): - """Get path from prefix and xml element.""" - if len(path) < 2: - print('Warning, bug, path is too small in evaluate in setPathByPrefix.') - return - pathByKey = getPathByKey([], getCapitalizedSuffixKey(prefix, 'path'), xmlElement) - if len( pathByKey ) < len(path): - for pointIndex in xrange( len( pathByKey ) ): - path[pointIndex] = pathByKey[pointIndex] - else: - path = pathByKey - path[0] = getVector3ByPrefix(path[0], getCapitalizedSuffixKey(prefix, 'pathStart'), xmlElement) - path[-1] = getVector3ByPrefix(path[-1], getCapitalizedSuffixKey(prefix, 'pathEnd'), xmlElement) - return path - -def getPathsByKey(defaultPaths, key, xmlElement): - """Get paths by key.""" - if key not in xmlElement.attributeDictionary: - return defaultPaths - word = str(xmlElement.attributeDictionary[key]).strip() - evaluatedLinkValue = getEvaluatedLinkValue(word, xmlElement) - if evaluatedLinkValue.__class__ == dict or evaluatedLinkValue.__class__ == list: - convertToPaths(evaluatedLinkValue) - return getPathsByLists(evaluatedLinkValue) - xmlElementObject = getXMLElementObject(evaluatedLinkValue) - if xmlElementObject is None: - return defaultPaths - return xmlElementObject.getPaths() - -def getPathsByLists(vertexLists): - """Get paths by lists.""" - vector3Lists = getVector3ListsRecursively(vertexLists) - paths = [] - addToPathsRecursively(paths, vector3Lists) - return paths - -def getSidesBasedOnPrecision(radius, xmlElement): - """Get the number of poygon sides.""" - return int(math.ceil(math.sqrt(0.5 * radius * math.pi * math.pi / setting.getPrecision(xmlElement)))) - -def getSidesMinimumThreeBasedOnPrecision(radius, xmlElement): - """Get the number of poygon sides, with a minimum of three.""" - return max(getSidesBasedOnPrecision(radius, xmlElement), 3) - -def getSidesMinimumThreeBasedOnPrecisionSides(radius, xmlElement): - """Get the number of poygon sides, with a minimum of three.""" - sides = getSidesMinimumThreeBasedOnPrecision(radius, xmlElement) - return getEvaluatedFloat(sides, 'sides', xmlElement) - -def getSplitDictionary(): - """Get split dictionary.""" - global globalSplitDictionaryOperator - splitDictionary = globalSplitDictionaryOperator.copy() - global globalDictionaryOperatorBegin - splitDictionary.update( globalDictionaryOperatorBegin ) - splitDictionary['and'] = EvaluatorAnd - splitDictionary['false'] = EvaluatorFalse - splitDictionary['False'] = EvaluatorFalse - splitDictionary['or'] = EvaluatorOr - splitDictionary['not'] = EvaluatorNot - splitDictionary['true'] = EvaluatorTrue - splitDictionary['True'] = EvaluatorTrue - splitDictionary['none'] = EvaluatorNone - splitDictionary['None'] = EvaluatorNone - return splitDictionary - -def getStartsWithCurlyEqualRoundSquare(word): - """Determine if the word starts with round or square brackets.""" - return word.startswith('{') or word.startswith('=') or word.startswith('(') or word.startswith('[') - -def getTokenByNumber(number): - """Get token by number.""" - return '_%s_' % number - -def getTransformedPathByKey(defaultTransformedPath, key, xmlElement): - """Get transformed path from prefix and xml element.""" - if key not in xmlElement.attributeDictionary: - return defaultTransformedPath - value = xmlElement.attributeDictionary[key] - if value.__class__ == list: - return value - word = str(value).strip() - evaluatedLinkValue = getEvaluatedLinkValue(word, xmlElement) - if evaluatedLinkValue.__class__ == list: - return getPathByList(evaluatedLinkValue) - xmlElementObject = getXMLElementObject(evaluatedLinkValueClass) - if xmlElementObject is None: - return defaultTransformedPath - return xmlElementObject.getTransformedPaths()[0] - -def getTransformedPathByPrefix(path, prefix, xmlElement): - """Get path from prefix and xml element.""" - if len(path) < 2: - print('Warning, bug, path is too small in evaluate in setPathByPrefix.') - return - pathByKey = getTransformedPathByKey([], getCapitalizedSuffixKey(prefix, 'path'), xmlElement) - if len( pathByKey ) < len(path): - for pointIndex in xrange( len( pathByKey ) ): - path[pointIndex] = pathByKey[pointIndex] - else: - path = pathByKey - path[0] = getVector3ByPrefix(path[0], getCapitalizedSuffixKey(prefix, 'pathStart'), xmlElement) - path[-1] = getVector3ByPrefix(path[-1], getCapitalizedSuffixKey(prefix, 'pathEnd'), xmlElement) - return path - -def getTransformedPathsByKey(defaultTransformedPaths, key, xmlElement): - """Get transformed paths by key.""" - if key not in xmlElement.attributeDictionary: - return defaultTransformedPaths - value = xmlElement.attributeDictionary[key] - if value.__class__ == list: - return getPathsByLists(value) - word = str(value).strip() - evaluatedLinkValue = getEvaluatedLinkValue(word, xmlElement) - if evaluatedLinkValue.__class__ == dict or evaluatedLinkValue.__class__ == list: - convertToTransformedPaths(evaluatedLinkValue) - return getPathsByLists(evaluatedLinkValue) - xmlElementObject = getXMLElementObject(evaluatedLinkValue) - if xmlElementObject is None: - return defaultTransformedPaths - return xmlElementObject.getTransformedPaths() - -def getUniqueQuoteIndex( uniqueQuoteIndex, word ): - """Get uniqueQuoteIndex.""" - uniqueQuoteIndex += 1 - while getTokenByNumber(uniqueQuoteIndex) in word: - uniqueQuoteIndex += 1 - return uniqueQuoteIndex - -def getUniqueToken(word): - """Get unique token.""" - uniqueString = '@#!' - for character in uniqueString: - if character not in word: - return character - uniqueNumber = 0 - while True: - for character in uniqueString: - uniqueToken = character + str(uniqueNumber) - if uniqueToken not in word: - return uniqueToken - uniqueNumber += 1 - -def getVector3ByDictionary( dictionary, vector3 ): - """Get vector3 by dictionary.""" - if 'x' in dictionary: - vector3 = getVector3IfNone(vector3) - vector3.x = euclidean.getFloatFromValue(dictionary['x']) - if 'y' in dictionary: - vector3 = getVector3IfNone(vector3) - vector3.y = euclidean.getFloatFromValue(dictionary['y']) - if 'z' in dictionary: - vector3 = getVector3IfNone(vector3) - vector3.z = euclidean.getFloatFromValue( dictionary['z'] ) - return vector3 - -def getVector3ByDictionaryListValue(value, vector3): - """Get vector3 by dictionary, list or value.""" - if value.__class__ == Vector3 or value.__class__.__name__ == 'Vector3Index': - return value - if value.__class__ == dict: - return getVector3ByDictionary(value, vector3) - if value.__class__ == list: - return getVector3ByFloatList(value, vector3) - floatFromValue = euclidean.getFloatFromValue(value) - if floatFromValue is None: - return vector3 - vector3.setToXYZ(floatFromValue, floatFromValue, floatFromValue) - return vector3 - -def getVector3ByFloatList(floatList, vector3): - """Get vector3 by float list.""" - if len(floatList) > 0: - vector3 = getVector3IfNone(vector3) - vector3.x = euclidean.getFloatFromValue(floatList[0]) - if len(floatList) > 1: - vector3 = getVector3IfNone(vector3) - vector3.y = euclidean.getFloatFromValue(floatList[1]) - if len(floatList) > 2: - vector3 = getVector3IfNone(vector3) - vector3.z = euclidean.getFloatFromValue(floatList[2]) - return vector3 - -def getVector3ByMultiplierPrefix( multiplier, prefix, vector3, xmlElement ): - """Get vector3 from multiplier, prefix and xml element.""" - if multiplier == 0.0: - return vector3 - oldMultipliedValueVector3 = vector3 * multiplier - vector3ByPrefix = getVector3ByPrefix(oldMultipliedValueVector3.copy(), prefix, xmlElement) - if vector3ByPrefix == oldMultipliedValueVector3: - return vector3 - return vector3ByPrefix / multiplier - -def getVector3ByMultiplierPrefixes( multiplier, prefixes, vector3, xmlElement ): - """Get vector3 from multiplier, prefixes and xml element.""" - for prefix in prefixes: - vector3 = getVector3ByMultiplierPrefix( multiplier, prefix, vector3, xmlElement ) - return vector3 - -def getVector3ByPrefix(defaultVector3, prefix, xmlElement): - """Get vector3 from prefix and xml element.""" - value = getEvaluatedValue(None, prefix, xmlElement) - if value is not None: - defaultVector3 = getVector3ByDictionaryListValue(value, defaultVector3) - prefix = archive.getUntilDot(prefix) - x = getEvaluatedFloat(None, prefix + '.x', xmlElement) - if x is not None: - defaultVector3 = getVector3IfNone(defaultVector3) - defaultVector3.x = x - y = getEvaluatedFloat(None, prefix + '.y', xmlElement) - if y is not None: - defaultVector3 = getVector3IfNone(defaultVector3) - defaultVector3.y = y - z = getEvaluatedFloat(None, prefix + '.z', xmlElement) - if z is not None: - defaultVector3 = getVector3IfNone(defaultVector3) - defaultVector3.z = z - return defaultVector3 - -def getVector3ByPrefixes( prefixes, vector3, xmlElement ): - """Get vector3 from prefixes and xml element.""" - for prefix in prefixes: - vector3 = getVector3ByPrefix(vector3, prefix, xmlElement) - return vector3 - -def getVector3FromXMLElement(xmlElement): - """Get vector3 from xml element.""" - vector3 = Vector3( - getEvaluatedFloat(0.0, 'x', xmlElement), - getEvaluatedFloat(0.0, 'y', xmlElement), - getEvaluatedFloat(0.0, 'z', xmlElement)) - return getVector3ByPrefix(vector3, 'cartesian', xmlElement) - -def getVector3IfNone(vector3): - """Get new vector3 if the original vector3 is none.""" - if vector3 is None: - return Vector3() - return vector3 - -def getVector3ListsRecursively(floatLists): - """Get vector3 lists recursively.""" - if len(floatLists) < 1: - return Vector3() - firstElement = floatLists[0] - if firstElement.__class__ == Vector3: - return floatLists - if firstElement.__class__ != list: - return getVector3ByFloatList(floatLists, Vector3()) - vector3ListsRecursively = [] - for floatList in floatLists: - vector3ListsRecursively.append(getVector3ListsRecursively(floatList)) - return vector3ListsRecursively - -def getVisibleObjects(archivableObjects): - """Get the visible objects.""" - visibleObjects = [] - for archivableObject in archivableObjects: - if archivableObject.getVisible(): - visibleObjects.append(archivableObject) - return visibleObjects - -def getXMLElementByKey(key, xmlElement): - """Get the xml element by key.""" - if key not in xmlElement.attributeDictionary: - return None - word = str(xmlElement.attributeDictionary[key]).strip() - evaluatedLinkValue = getEvaluatedLinkValue(word, xmlElement) - if evaluatedLinkValue.__class__.__name__ == 'XMLElement': - return evaluatedLinkValue - print('Warning, could not get XMLElement in getXMLElementByKey in evaluate for:') - print(key) - print(evaluatedLinkValue) - print(xmlElement) - return None - -def getXMLElementObject(evaluatedLinkValue): - """Get XMLElementObject.""" - if evaluatedLinkValue.__class__.__name__ != 'XMLElement': - print('Warning, could not get XMLElement in getXMLElementObject in evaluate for:') - print(evaluatedLinkValue) - return None - if evaluatedLinkValue.xmlObject is None: - print('Warning, evaluatedLinkValue.xmlObject is None in getXMLElementObject in evaluate for:') - print(evaluatedLinkValue) - return None - return evaluatedLinkValue.xmlObject - -def getXMLElementsByKey(key, xmlElement): - """Get the xml elements by key.""" - if key not in xmlElement.attributeDictionary: - return [] - word = str(xmlElement.attributeDictionary[key]).strip() - evaluatedLinkValue = getEvaluatedLinkValue(word, xmlElement) - if evaluatedLinkValue.__class__.__name__ == 'XMLElement': - return [evaluatedLinkValue] - if evaluatedLinkValue.__class__ == list: - return evaluatedLinkValue - print('Warning, could not get XMLElements in getXMLElementsByKey in evaluate for:') - print(key) - print(evaluatedLinkValue) - print(xmlElement) - return [] - -def processArchivable(archivableClass, xmlElement): - """Get any new elements and process the archivable.""" - if xmlElement is None: - return - xmlElement.xmlObject = archivableClass() - xmlElement.xmlObject.setToXMLElement(xmlElement) - xmlElement.getXMLProcessor().processChildren(xmlElement) - -def processCondition(xmlElement): - """Process the xml element condition.""" - xmlProcessor = xmlElement.getXMLProcessor() - if xmlElement.xmlObject is None: - xmlElement.xmlObject = ModuleXMLElement(xmlElement) - if xmlElement.xmlObject.conditionSplitWords is None: - return - if len(xmlProcessor.functions ) < 1: - print('Warning, the (in) element is not in a function in processCondition in evaluate for:') - print(xmlElement) - return - if int( getEvaluatedExpressionValueBySplitLine( xmlElement.xmlObject.conditionSplitWords, xmlElement ) ) > 0: - xmlProcessor.functions[-1].processChildren(xmlElement) - else: - xmlElement.xmlObject.processElse(xmlElement) - -def removeIdentifiersFromDictionary(dictionary): - """Remove the identifier elements from a dictionary.""" - euclidean.removeElementsFromDictionary(dictionary, ['id', 'name', 'tags']) - -def setAttributeDictionaryByArguments(argumentNames, arguments, xmlElement): - """Set the attribute dictionary to the arguments.""" - for argumentIndex, argument in enumerate(arguments): - xmlElement.attributeDictionary[argumentNames[argumentIndex]] = argument - -def setFunctionLocalDictionary(arguments, function): - """Evaluate the function statement and delete the evaluators.""" - function.localDictionary = {'_arguments' : arguments} - if len(arguments) > 0: - firstArgument = arguments[0] - if firstArgument.__class__ == dict: - function.localDictionary = firstArgument - return - if 'parameters' not in function.xmlElement.attributeDictionary: - return - parameters = function.xmlElement.attributeDictionary['parameters'].strip() - if parameters == '': - return - parameterWords = parameters.split(',') - for parameterWordIndex, parameterWord in enumerate(parameterWords): - strippedWord = parameterWord.strip() - keyValue = KeyValue().getByEqual(strippedWord) - if parameterWordIndex < len(arguments): - function.localDictionary[keyValue.key] = arguments[parameterWordIndex] - else: - strippedValue = keyValue.value - if strippedValue is None: - print('Warning there is no default parameter in getParameterValue for:') - print(strippedWord) - print(parameterWords) - print(arguments) - print( function.xmlElement.attributeDictionary ) - else: - strippedValue = strippedValue.strip() - function.localDictionary[keyValue.key.strip()] = strippedValue - if len(arguments) > len(parameterWords): - print('Warning there are too many initializeFunction parameters for:') - print( function.xmlElement.attributeDictionary ) - print(parameterWords) - print(arguments) - -def setLocalAttribute(xmlElement): - """Set the local attribute if any.""" - if xmlElement.xmlObject is not None: - return - for key in xmlElement.attributeDictionary: - if key[: 1].isalpha(): - value = getEvaluatorSplitWords(getLocalAttributeValueString(key, xmlElement.attributeDictionary[key].strip())) - xmlElement.xmlObject = KeyValue(key, value) - return - xmlElement.xmlObject = KeyValue() - - -class BaseFunction: - """Class to get equation results.""" - def __init__(self, xmlElement): - """Initialize.""" - self.localDictionary = {} - self.xmlElement = xmlElement - self.xmlProcessor = xmlElement.getXMLProcessor() - - def __repr__(self): - """Get the string representation of this Class.""" - return str(self.__dict__) - - def getReturnValue(self): - """Get return value.""" - self.getReturnValueWithoutDeletion() - del self.xmlProcessor.functions[-1] - return self.returnValue - - def processChildren(self, xmlElement): - """Process children if shouldReturn is false.""" - for child in xmlElement.children: - if self.shouldReturn: - return - self.xmlProcessor.processXMLElement(child) - - -class ClassFunction(BaseFunction): - """Class to get class results.""" - def getReturnValueByArguments(self, *arguments): - """Get return value by arguments.""" - setFunctionLocalDictionary(arguments, self) - return self.getReturnValue() - - def getReturnValueWithoutDeletion(self): - """Get return value without deleting last function.""" - self.returnValue = None - self.shouldReturn = False - self.xmlProcessor.functions.append(self) - self.processChildren(self.xmlElement) - return self.returnValue - - -class ClassObject: - """Class to hold class attributes and functions.""" - def __init__(self, xmlElement): - """Initialize.""" - self.functionDictionary = xmlElement.xmlObject.functionDictionary - self.selfDictionary = {} - for variable in xmlElement.xmlObject.variables: - self.selfDictionary[variable] = None - - def _getAccessibleAttribute(self, attributeName): - """Get the accessible attribute.""" - if attributeName in self.selfDictionary: - return self.selfDictionary[attributeName] - if attributeName in self.functionDictionary: - function = self.functionDictionary[attributeName] - function.classObject = self - return function.getReturnValueByArguments - return None - - def __repr__(self): - """Get the string representation of this Class.""" - return str(self.__dict__) - - def _setAccessibleAttribute(self, attributeName, value): - """Set the accessible attribute.""" - if attributeName in self.selfDictionary: - self.selfDictionary[attributeName] = value - - -class Evaluator: - """Base evaluator class.""" - def __init__(self, word, xmlElement): - """Set value to none.""" - self.value = None - self.word = word - - def __repr__(self): - """Get the string representation of this Class.""" - return str(self.__dict__) - - def executeBracket( self, bracketBeginIndex, bracketEndIndex, evaluators ): - """Execute the bracket.""" - pass - - def executeCenterOperation(self, evaluators, evaluatorIndex): - """Execute operator which acts on the center.""" - pass - - def executeDictionary(self, dictionary, evaluators, keys, evaluatorIndex, nextEvaluator): - """Execute the dictionary.""" - del evaluators[evaluatorIndex] - enumeratorKeys = euclidean.getEnumeratorKeys(dictionary, keys) - if enumeratorKeys.__class__ == list: - nextEvaluator.value = [] - for enumeratorKey in enumeratorKeys: - if enumeratorKey in dictionary: - nextEvaluator.value.append(dictionary[enumeratorKey]) - else: - print('Warning, key in executeKey in Evaluator in evaluate is not in for:') - print(enumeratorKey) - print(dictionary) - return - if enumeratorKeys in dictionary: - nextEvaluator.value = dictionary[enumeratorKeys] - else: - print('Warning, key in executeKey in Evaluator in evaluate is not in for:') - print(enumeratorKeys) - print(dictionary) - - def executeFunction(self, evaluators, evaluatorIndex, nextEvaluator): - """Execute the function.""" - pass - - def executeKey(self, evaluators, keys, evaluatorIndex, nextEvaluator): - """Execute the key index.""" - if self.value.__class__ == str: - self.executeString(evaluators, keys, evaluatorIndex, nextEvaluator) - return - if self.value.__class__ == list: - self.executeList(evaluators, keys, evaluatorIndex, nextEvaluator) - return - if self.value.__class__ == dict: - self.executeDictionary(self.value, evaluators, keys, evaluatorIndex, nextEvaluator) - return - getAccessibleDictionaryFunction = getattr(self.value, '_getAccessibleDictionary', None) - if getAccessibleDictionaryFunction is not None: - self.executeDictionary(getAccessibleDictionaryFunction(), evaluators, keys, evaluatorIndex, nextEvaluator) - return - if self.value.__class__.__name__ != 'XMLElement': - return - del evaluators[evaluatorIndex] - enumeratorKeys = euclidean.getEnumeratorKeys(self.value.attributeDictionary, keys) - if enumeratorKeys.__class__ == list: - nextEvaluator.value = [] - for enumeratorKey in enumeratorKeys: - if enumeratorKey in self.value.attributeDictionary: - nextEvaluator.value.append(getEvaluatedExpressionValue(self.value.attributeDictionary[enumeratorKey], self.value)) - else: - print('Warning, key in executeKey in Evaluator in evaluate is not in for:') - print(enumeratorKey) - print(self.value.attributeDictionary) - return - if enumeratorKeys in self.value.attributeDictionary: - nextEvaluator.value = getEvaluatedExpressionValue(self.value.attributeDictionary[enumeratorKeys], self.value) - else: - print('Warning, key in executeKey in Evaluator in evaluate is not in for:') - print(enumeratorKeys) - print(self.value.attributeDictionary) - - def executeLeftOperation(self, evaluators, evaluatorIndex, operationLevel): - """Execute operator which acts from the left.""" - pass - - def executeList(self, evaluators, keys, evaluatorIndex, nextEvaluator): - """Execute the key index.""" - del evaluators[evaluatorIndex] - enumeratorKeys = euclidean.getEnumeratorKeys(self.value, keys) - if enumeratorKeys.__class__ == list: - nextEvaluator.value = [] - for enumeratorKey in enumeratorKeys: - intKey = euclidean.getIntFromValue(enumeratorKey) - if self.getIsInRange(intKey): - nextEvaluator.value.append(self.value[intKey]) - else: - print('Warning, key in executeList in Evaluator in evaluate is not in for:') - print(enumeratorKey) - print(self.value) - return - intKey = euclidean.getIntFromValue(enumeratorKeys) - if self.getIsInRange(intKey): - nextEvaluator.value = self.value[intKey] - else: - print('Warning, key in executeList in Evaluator in evaluate is not in for:') - print(enumeratorKeys) - print(self.value) - - def executePairOperation(self, evaluators, evaluatorIndex, operationLevel): - """Operate on two evaluators.""" - pass - - def executeRightOperation( self, evaluators, evaluatorIndex ): - """Execute operator which acts from the right.""" - pass - - def executeString(self, evaluators, keys, evaluatorIndex, nextEvaluator): - """Execute the string.""" - del evaluators[evaluatorIndex] - enumeratorKeys = euclidean.getEnumeratorKeys(self.value, keys) - if enumeratorKeys.__class__ == list: - nextEvaluator.value = '' - for enumeratorKey in enumeratorKeys: - intKey = euclidean.getIntFromValue(enumeratorKey) - if self.getIsInRange(intKey): - nextEvaluator.value += self.value[intKey] - else: - print('Warning, key in executeString in Evaluator in evaluate is not in for:') - print(enumeratorKey) - print(self.value) - return - intKey = euclidean.getIntFromValue(enumeratorKeys) - if self.getIsInRange(intKey): - nextEvaluator.value = self.value[intKey] - else: - print('Warning, key in executeString in Evaluator in evaluate is not in for:') - print(enumeratorKeys) - print(self.value) - - def getIsInRange(self, keyIndex): - """Determine if the keyIndex is in range.""" - if keyIndex is None: - return False - return keyIndex >= -len(self.value) and keyIndex < len(self.value) - - -class EvaluatorAddition(Evaluator): - """Class to add two evaluators.""" - def executePairOperation(self, evaluators, evaluatorIndex, operationLevel): - """Operate on two evaluators.""" - if operationLevel == 20: - self.executePair(evaluators, evaluatorIndex) - - def executePair( self, evaluators, evaluatorIndex ): - """Add two evaluators.""" - leftIndex = evaluatorIndex - 1 - rightIndex = evaluatorIndex + 1 - if leftIndex < 0: - print('Warning, no leftKey in executePair in EvaluatorAddition for:') - print(evaluators) - print(evaluatorIndex) - print(self) - del evaluators[evaluatorIndex] - return - if rightIndex >= len(evaluators): - print('Warning, no rightKey in executePair in EvaluatorAddition for:') - print(evaluators) - print(evaluatorIndex) - print(self) - del evaluators[evaluatorIndex] - return - rightValue = evaluators[rightIndex].value - evaluators[leftIndex].value = self.getOperationValue(evaluators[leftIndex].value, evaluators[rightIndex].value) - del evaluators[ evaluatorIndex : evaluatorIndex + 2 ] - - def getEvaluatedValues(self, enumerable, keys, value): - """Get evaluatedValues.""" - if enumerable.__class__ == dict: - evaluatedValues = {} - for key in keys: - evaluatedValues[key] = self.getOperationValue(value, enumerable[key]) - return evaluatedValues - evaluatedValues = [] - for key in keys: - evaluatedValues.append(self.getOperationValue(value, enumerable[key])) - return evaluatedValues - - def getOperationValue(self, leftValue, rightValue): - """Get operation value.""" - leftKeys = getKeys(leftValue) - rightKeys = getKeys(rightValue) - if leftKeys is None and rightKeys is None: - return self.getValueFromValuePair(leftValue, rightValue) - if leftKeys is None: - return self.getEvaluatedValues(rightValue, rightKeys, leftValue) - if rightKeys is None: - return self.getEvaluatedValues(leftValue, leftKeys, rightValue) - leftKeys.sort(reverse=True) - rightKeys.sort(reverse=True) - if leftKeys != rightKeys: - print('Warning, the leftKeys are different from the rightKeys in getOperationValue in EvaluatorAddition for:') - print('leftValue') - print(leftValue) - print(leftKeys) - print('rightValue') - print(rightValue) - print(rightKeys) - print(self) - return None - if leftValue.__class__ == dict or rightValue.__class__ == dict: - evaluatedValues = {} - for leftKey in leftKeys: - evaluatedValues[leftKey] = self.getOperationValue(leftValue[leftKey], rightValue[leftKey]) - return evaluatedValues - evaluatedValues = [] - for leftKey in leftKeys: - evaluatedValues.append(self.getOperationValue(leftValue[leftKey], rightValue[leftKey])) - return evaluatedValues - - def getValueFromValuePair(self, leftValue, rightValue): - """Add two values.""" - return leftValue + rightValue - - -class EvaluatorEqual(EvaluatorAddition): - """Class to compare two evaluators.""" - def executePairOperation(self, evaluators, evaluatorIndex, operationLevel): - """Operate on two evaluators.""" - if operationLevel == 15: - self.executePair(evaluators, evaluatorIndex) - - def getBooleanFromValuePair(self, leftValue, rightValue): - """Compare two values.""" - return leftValue == rightValue - - def getValueFromValuePair(self, leftValue, rightValue): - """Get value from comparison.""" - return self.getBooleanFromValuePair(leftValue, rightValue) - - -class EvaluatorSubtraction(EvaluatorAddition): - """Class to subtract two evaluators.""" - def executeLeft( self, evaluators, evaluatorIndex ): - """Minus the value to the right.""" - leftIndex = evaluatorIndex - 1 - rightIndex = evaluatorIndex + 1 - leftValue = None - if leftIndex >= 0: - leftValue = evaluators[leftIndex].value - if leftValue is not None: - return - rightValue = evaluators[rightIndex].value - if rightValue is None: - print('Warning, can not minus.') - print( evaluators[rightIndex].word ) - else: - evaluators[rightIndex].value = self.getNegativeValue(rightValue) - del evaluators[evaluatorIndex] - - def executeLeftOperation(self, evaluators, evaluatorIndex, operationLevel): - """Minus the value to the right.""" - if operationLevel == 200: - self.executeLeft(evaluators, evaluatorIndex) - - def getNegativeValue( self, value ): - """Get the negative value.""" - keys = getKeys(value) - if keys is None: - return self.getValueFromSingleValue(value) - for key in keys: - value[key] = self.getNegativeValue(value[key]) - return value - - def getValueFromSingleValue( self, value ): - """Minus value.""" - return -value - - def getValueFromValuePair(self, leftValue, rightValue): - """Subtract two values.""" - return leftValue - rightValue - - -class EvaluatorAnd(EvaluatorAddition): - """Class to compare two evaluators.""" - def executePairOperation(self, evaluators, evaluatorIndex, operationLevel): - """Operate on two evaluators.""" - if operationLevel == 12: - self.executePair(evaluators, evaluatorIndex) - - def getBooleanFromValuePair(self, leftValue, rightValue): - """And two values.""" - return leftValue and rightValue - - def getValueFromValuePair(self, leftValue, rightValue): - """Get value from comparison.""" - return self.getBooleanFromValuePair(leftValue, rightValue) - - -class EvaluatorAttribute(Evaluator): - """Class to handle an attribute.""" - def executeFunction(self, evaluators, evaluatorIndex, nextEvaluator): - """Execute the function.""" - executeNextEvaluatorArguments(self, evaluators, evaluatorIndex, nextEvaluator) - - def executeRightOperation( self, evaluators, evaluatorIndex ): - """Execute operator which acts from the right.""" - attributeName = self.word[1 :] - previousIndex = evaluatorIndex - 1 - previousEvaluator = evaluators[previousIndex] - if previousEvaluator.value.__class__ == dict: - from fabmetheus_utilities.geometry.geometry_utilities.evaluate_enumerables import dictionary_attribute - self.value = dictionary_attribute._getAccessibleAttribute(attributeName, previousEvaluator.value) - elif previousEvaluator.value.__class__ == list: - from fabmetheus_utilities.geometry.geometry_utilities.evaluate_enumerables import list_attribute - self.value = list_attribute._getAccessibleAttribute(attributeName, previousEvaluator.value) - elif previousEvaluator.value.__class__ == str: - from fabmetheus_utilities.geometry.geometry_utilities.evaluate_enumerables import string_attribute - self.value = string_attribute._getAccessibleAttribute(attributeName, previousEvaluator.value) - else: - attributeKeywords = attributeName.split('.') - self.value = previousEvaluator.value - for attributeKeyword in attributeKeywords: - self.value = getattr(self.value, '_getAccessibleAttribute', None)(attributeKeyword) - if self.value is None: - print('Warning, EvaluatorAttribute in evaluate can not get a getAccessibleAttributeFunction for:') - print(attributeName) - print(previousEvaluator.value) - print(self) - return - del evaluators[previousIndex] - - -class EvaluatorBracketCurly(Evaluator): - """Class to evaluate a string.""" - def executeBracket(self, bracketBeginIndex, bracketEndIndex, evaluators): - """Execute the bracket.""" - for evaluatorIndex in xrange(bracketEndIndex - 3, bracketBeginIndex, - 1): - bracketEndIndex = getEndIndexConvertEquationValue(bracketEndIndex, evaluatorIndex, evaluators) - evaluatedExpressionValueEvaluators = getBracketEvaluators(bracketBeginIndex, bracketEndIndex, evaluators) - self.value = {} - for evaluatedExpressionValueEvaluator in evaluatedExpressionValueEvaluators: - keyValue = evaluatedExpressionValueEvaluator.value - self.value[keyValue.key] = keyValue.value - del evaluators[bracketBeginIndex + 1: bracketEndIndex + 1] - - -class EvaluatorBracketRound(Evaluator): - """Class to evaluate a string.""" - def __init__(self, word, xmlElement): - """Set value to none.""" - self.arguments = [] - self.value = None - self.word = word - - def executeBracket( self, bracketBeginIndex, bracketEndIndex, evaluators ): - """Execute the bracket.""" - self.arguments = getBracketValuesDeleteEvaluator(bracketBeginIndex, bracketEndIndex, evaluators) - if len( self.arguments ) < 1: - return - if len( self.arguments ) > 1: - self.value = self.arguments - else: - self.value = self.arguments[0] - - def executeRightOperation( self, evaluators, evaluatorIndex ): - """Evaluate the statement and delete the evaluators.""" - previousIndex = evaluatorIndex - 1 - if previousIndex < 0: - return - evaluators[ previousIndex ].executeFunction( evaluators, previousIndex, self ) - - -class EvaluatorBracketSquare(Evaluator): - """Class to evaluate a string.""" - def executeBracket( self, bracketBeginIndex, bracketEndIndex, evaluators ): - """Execute the bracket.""" - self.value = getBracketValuesDeleteEvaluator(bracketBeginIndex, bracketEndIndex, evaluators) - - def executeRightOperation( self, evaluators, evaluatorIndex ): - """Evaluate the statement and delete the evaluators.""" - previousIndex = evaluatorIndex - 1 - if previousIndex < 0: - return - if self.value.__class__ != list: - return - evaluators[ previousIndex ].executeKey( evaluators, self.value, previousIndex, self ) - - -class EvaluatorClass(Evaluator): - """Class evaluator class.""" - def __init__(self, word, xmlElement): - """Set value to none.""" - self.value = None - self.word = word - self.xmlElement = xmlElement - - def executeFunction(self, evaluators, evaluatorIndex, nextEvaluator): - """Execute the function.""" - if self.xmlElement.xmlObject is None: - self.xmlElement.xmlObject = FunctionVariable(self.xmlElement) - nextEvaluator.value = ClassObject(self.xmlElement) - initializeFunction = None - if '_init' in self.xmlElement.xmlObject.functionDictionary: - function = self.xmlElement.xmlObject.functionDictionary['_init'] - function.classObject = nextEvaluator.value - setFunctionLocalDictionary(nextEvaluator.arguments, function) - function.getReturnValue() - del evaluators[evaluatorIndex] - - -class EvaluatorComma(Evaluator): - """Class to join two evaluators.""" - def executePairOperation(self, evaluators, evaluatorIndex, operationLevel): - """Operate on two evaluators.""" - if operationLevel != 0: - return - previousIndex = evaluatorIndex - 1 - if previousIndex < 0: - evaluators[evaluatorIndex].value = None - return - if evaluators[previousIndex].word == ',': - evaluators[evaluatorIndex].value = None - return - del evaluators[evaluatorIndex] - - -class EvaluatorConcatenate(Evaluator): - """Class to join two evaluators.""" - def executePairOperation(self, evaluators, evaluatorIndex, operationLevel): - """Operate on two evaluators.""" - if operationLevel != 80: - return - leftIndex = evaluatorIndex - 1 - if leftIndex < 0: - del evaluators[evaluatorIndex] - return - rightIndex = evaluatorIndex + 1 - if rightIndex >= len(evaluators): - del evaluators[ leftIndex : rightIndex ] - return - leftValue = evaluators[leftIndex].value - rightValue = evaluators[rightIndex].value - if leftValue.__class__ == rightValue.__class__ and (leftValue.__class__ == list or rightValue.__class__ == str): - evaluators[leftIndex].value = leftValue + rightValue - del evaluators[ evaluatorIndex : evaluatorIndex + 2 ] - return - if leftValue.__class__ == list and rightValue.__class__ == int: - if rightValue > 0: - originalList = leftValue[:] - for copyIndex in xrange( rightValue - 1 ): - leftValue += originalList - evaluators[leftIndex].value = leftValue - del evaluators[ evaluatorIndex : evaluatorIndex + 2 ] - return - if leftValue.__class__ == dict and rightValue.__class__ == dict: - leftValue.update(rightValue) - evaluators[leftIndex].value = leftValue - del evaluators[ evaluatorIndex : evaluatorIndex + 2 ] - return - del evaluators[ leftIndex : evaluatorIndex + 2 ] - - -class EvaluatorDictionary(Evaluator): - """Class to join two evaluators.""" - def executePairOperation(self, evaluators, evaluatorIndex, operationLevel): - """Operate on two evaluators.""" - if operationLevel != 10: - return - leftEvaluatorIndex = evaluatorIndex - 1 - if leftEvaluatorIndex < 0: - print('Warning, leftEvaluatorIndex is less than zero in EvaluatorDictionary for:') - print(self) - print(evaluators) - return - rightEvaluatorIndex = evaluatorIndex + 1 - if rightEvaluatorIndex >= len(evaluators): - print('Warning, rightEvaluatorIndex too high in EvaluatorDictionary for:') - print(rightEvaluatorIndex) - print(self) - print(evaluators) - return - evaluators[rightEvaluatorIndex].value = KeyValue(evaluators[leftEvaluatorIndex].value, evaluators[rightEvaluatorIndex].value) - del evaluators[ leftEvaluatorIndex : rightEvaluatorIndex ] - - -class EvaluatorDivision(EvaluatorAddition): - """Class to divide two evaluators.""" - def executePairOperation(self, evaluators, evaluatorIndex, operationLevel): - """Operate on two evaluators.""" - if operationLevel == 40: - self.executePair(evaluators, evaluatorIndex) - - def getValueFromValuePair(self, leftValue, rightValue): - """Divide two values.""" - return leftValue / rightValue - - -class EvaluatorElement(Evaluator): - """Element evaluator class.""" - def __init__(self, word, xmlElement): - """Set value to none.""" - self.value = None - self.word = word - self.xmlElement = xmlElement - - def executeCenterOperation(self, evaluators, evaluatorIndex): - """Execute operator which acts on the center.""" - dotIndex = self.word.find('.') - if dotIndex < 0: - print('Warning, EvaluatorElement in evaluate can not find the dot for:') - print(functionName) - print(self) - return - attributeName = self.word[dotIndex + 1 :] - moduleName = self.word[: dotIndex] - if moduleName in globalModuleFunctionsDictionary: - self.value = globalModuleFunctionsDictionary[moduleName](attributeName, self.xmlElement) - return - pluginModule = None - if moduleName in globalElementNameSet: - pluginModule = archive.getModuleWithPath(archive.getElementsPath(moduleName)) - if pluginModule is None: - print('Warning, EvaluatorElement in evaluate can not get a pluginModule for:') - print(moduleName) - print(self) - return - getAccessibleAttributeFunction = pluginModule._getAccessibleAttribute - globalModuleFunctionsDictionary[moduleName] = getAccessibleAttributeFunction - self.value = getAccessibleAttributeFunction(attributeName, self.xmlElement) - - def executeFunction(self, evaluators, evaluatorIndex, nextEvaluator): - """Execute the function.""" - executeNextEvaluatorArguments(self, evaluators, evaluatorIndex, nextEvaluator) - - -class EvaluatorFalse(Evaluator): - """Class to evaluate a string.""" - def __init__(self, word, xmlElement): - """Set value to zero.""" - self.value = False - self.word = word - - -class EvaluatorFunction(Evaluator): - """Function evaluator class.""" - def __init__(self, word, xmlElement): - """Set value to none.""" - self.value = None - self.word = word - self.xmlElement = xmlElement - - def executeFunction(self, evaluators, evaluatorIndex, nextEvaluator): - """Execute the function.""" - if self.xmlElement.xmlObject is None: - if 'return' in self.xmlElement.attributeDictionary: - value = self.xmlElement.attributeDictionary['return'] - self.xmlElement.xmlObject = getEvaluatorSplitWords(value) - else: - self.xmlElement.xmlObject = [] - self.function = Function(self.xmlElement ) - setFunctionLocalDictionary(nextEvaluator.arguments, self.function) - nextEvaluator.value = self.function.getReturnValue() - del evaluators[evaluatorIndex] - - -class EvaluatorFundamental(Evaluator): - """Fundamental evaluator class.""" - def executeCenterOperation(self, evaluators, evaluatorIndex): - """Execute operator which acts on the center.""" - dotIndex = self.word.find('.') - if dotIndex < 0: - print('Warning, EvaluatorFundamental in evaluate can not find the dot for:') - print(functionName) - print(self) - return - attributeName = self.word[dotIndex + 1 :] - moduleName = self.word[: dotIndex] - if moduleName in globalModuleFunctionsDictionary: - self.value = globalModuleFunctionsDictionary[moduleName](attributeName) - return - pluginModule = None - if moduleName in globalFundamentalNameSet: - pluginModule = archive.getModuleWithPath(archive.getFundamentalsPath(moduleName)) - else: - underscoredName = '_' + moduleName - if underscoredName in globalFundamentalNameSet: - pluginModule = archive.getModuleWithPath(archive.getFundamentalsPath(underscoredName)) - if pluginModule is None: - print('Warning, EvaluatorFundamental in evaluate can not get a pluginModule for:') - print(moduleName) - print(self) - return - getAccessibleAttributeFunction = pluginModule._getAccessibleAttribute - globalModuleFunctionsDictionary[moduleName] = getAccessibleAttributeFunction - self.value = getAccessibleAttributeFunction(attributeName) - - def executeFunction(self, evaluators, evaluatorIndex, nextEvaluator): - """Execute the function.""" - executeNextEvaluatorArguments(self, evaluators, evaluatorIndex, nextEvaluator) - - -class EvaluatorGreaterEqual( EvaluatorEqual ): - """Class to compare two evaluators.""" - def getBooleanFromValuePair(self, leftValue, rightValue): - """Compare two values.""" - return leftValue >= rightValue - - -class EvaluatorGreater( EvaluatorEqual ): - """Class to compare two evaluators.""" - def getBooleanFromValuePair(self, leftValue, rightValue): - """Compare two values.""" - return leftValue > rightValue - - -class EvaluatorLessEqual( EvaluatorEqual ): - """Class to compare two evaluators.""" - def getBooleanFromValuePair(self, leftValue, rightValue): - """Compare two values.""" - return leftValue <= rightValue - - -class EvaluatorLess( EvaluatorEqual ): - """Class to compare two evaluators.""" - def getBooleanFromValuePair(self, leftValue, rightValue): - """Compare two values.""" - return leftValue < rightValue - - -class EvaluatorLocal(EvaluatorElement): - """Class to get a local variable.""" - def executeCenterOperation(self, evaluators, evaluatorIndex): - """Execute operator which acts on the center.""" - functions = self.xmlElement.getXMLProcessor().functions - if len(functions) < 1: - print('Warning, there are no functions in EvaluatorLocal in evaluate for:') - print(self.word) - return - attributeKeywords = self.word.split('.') - self.value = functions[-1].localDictionary[attributeKeywords[0]] - for attributeKeyword in attributeKeywords[1 :]: - self.value = self.value._getAccessibleAttribute(attributeKeyword) - - -class EvaluatorModulo( EvaluatorDivision ): - """Class to modulo two evaluators.""" - def getValueFromValuePair(self, leftValue, rightValue): - """Modulo two values.""" - return leftValue % rightValue - - -class EvaluatorMultiplication( EvaluatorDivision ): - """Class to multiply two evaluators.""" - def getValueFromValuePair(self, leftValue, rightValue): - """Multiply two values.""" - return leftValue * rightValue - - -class EvaluatorNone(Evaluator): - """Class to evaluate None.""" - def __init__(self, word, xmlElement): - """Set value to none.""" - self.value = None - self.word = str(word) - - -class EvaluatorNot(EvaluatorSubtraction): - """Class to compare two evaluators.""" - def executeLeftOperation(self, evaluators, evaluatorIndex, operationLevel): - """Minus the value to the right.""" - if operationLevel == 13: - self.executeLeft(evaluators, evaluatorIndex) - - def getValueFromSingleValue( self, value ): - """Minus value.""" - return not value - - -class EvaluatorNotEqual( EvaluatorEqual ): - """Class to compare two evaluators.""" - def getBooleanFromValuePair(self, leftValue, rightValue): - """Compare two values.""" - return leftValue != rightValue - - -class EvaluatorNumeric(Evaluator): - """Class to evaluate a string.""" - def __init__(self, word, xmlElement): - """Set value.""" - self.value = None - self.word = word - try: - if '.' in word: - self.value = float(word) - else: - self.value = int(word) - except: - print('Warning, EvaluatorNumeric in evaluate could not get a numeric value for:') - print(word) - print(xmlElement) - - -class EvaluatorOr( EvaluatorAnd ): - """Class to compare two evaluators.""" - def getBooleanFromValuePair(self, leftValue, rightValue): - """Or two values.""" - return leftValue or rightValue - - -class EvaluatorPower(EvaluatorAddition): - """Class to power two evaluators.""" - def executePairOperation(self, evaluators, evaluatorIndex, operationLevel): - """Operate on two evaluators.""" - if operationLevel == 60: - self.executePair(evaluators, evaluatorIndex) - - def getValueFromValuePair(self, leftValue, rightValue): - """Power of two values.""" - return leftValue ** rightValue - - -class EvaluatorSelf(EvaluatorElement): - """Class to handle self.""" - def executeCenterOperation(self, evaluators, evaluatorIndex): - """Execute operator which acts on the center.""" - functions = self.xmlElement.getXMLProcessor().functions - if len(functions) < 1: - print('Warning, there are no functions in executeCenterOperation in EvaluatorSelf in evaluate for:') - print(self.xmlElement) - return - function = functions[-1] - attributeKeywords = self.word.split('.') - self.value = function.classObject - for attributeKeyword in attributeKeywords[1 :]: - self.value = self.value._getAccessibleAttribute(attributeKeyword) - - -class EvaluatorTrue(Evaluator): - """Class to evaluate a string.""" - def __init__(self, word, xmlElement): - """Set value to true.""" - self.value = True - self.word = word - - -class EvaluatorValue(Evaluator): - """Class to evaluate a string.""" - def __init__(self, word): - """Set value to none.""" - self.value = word - self.word = str(word) - - -class Function(BaseFunction): - """Class to get equation results.""" - def __init__(self, xmlElement): - """Initialize.""" - self.localDictionary = {} - self.evaluatorSplitLine = xmlElement.xmlObject - self.xmlElement = xmlElement - self.xmlProcessor = xmlElement.getXMLProcessor() - - def getReturnValueWithoutDeletion(self): - """Get return value without deleting last function.""" - self.returnValue = None - self.xmlProcessor.functions.append(self) - if len(self.evaluatorSplitLine) < 1: - self.shouldReturn = False - self.processChildren(self.xmlElement) - else: - self.returnValue = getEvaluatedExpressionValueBySplitLine(self.evaluatorSplitLine, self.xmlElement) - return self.returnValue - - -class FunctionVariable: - """Class to hold class functions and variable set.""" - def __init__(self, xmlElement): - """Initialize.""" - self.functionDictionary = {} - self.variables = [] - self.processClass(xmlElement) - - def addToVariableSet(self, xmlElement): - """Add to variables.""" - setLocalAttribute(xmlElement) - keySplitLine = xmlElement.xmlObject.key.split('.') - if len(keySplitLine) == 2: - if keySplitLine[0] == 'self': - variable = keySplitLine[1] - if variable not in self.variables: - self.variables.append(variable) - - def processClass(self, xmlElement): - """Add class to FunctionVariable.""" - for child in xmlElement.children: - self.processFunction(child) - if 'parent' in xmlElement.attributeDictionary: - self.processClass(xmlElement.getXMLElementByImportID(xmlElement.attributeDictionary['parent'])) - - def processFunction(self, xmlElement): - """Add function to function dictionary.""" - if xmlElement.className != 'function': - return - idKey = xmlElement.attributeDictionary['id'] - if idKey in self.functionDictionary: - return - self.functionDictionary[idKey] = ClassFunction(xmlElement) - for child in xmlElement.children: - self.processStatement(child) - - def processStatement(self, xmlElement): - """Add self statement to variables.""" - if xmlElement.className == 'statement': - self.addToVariableSet(xmlElement) - for child in xmlElement.children: - self.processStatement(child) - - -class KeyValue: - """Class to hold a key value.""" - def __init__(self, key=None, value=None): - """Get key value.""" - self.key = key - self.value = value - - def __repr__(self): - """Get the string representation of this KeyValue.""" - return str(self.__dict__) - - def getByCharacter( self, character, line ): - """Get by character.""" - dotIndex = line.find( character ) - if dotIndex < 0: - self.key = line - self.value = None - return self - self.key = line[: dotIndex] - self.value = line[dotIndex + 1 :] - return self - - def getByDot(self, line): - """Get by dot.""" - return self.getByCharacter('.', line ) - - def getByEqual(self, line): - """Get by dot.""" - return self.getByCharacter('=', line ) - - -class ModuleXMLElement: - """Class to get the in attribute, the index name and the value name.""" - def __init__( self, xmlElement): - """Initialize.""" - self.conditionSplitWords = None - self.elseElement = None - if 'condition' in xmlElement.attributeDictionary: - self.conditionSplitWords = getEvaluatorSplitWords( xmlElement.attributeDictionary['condition'] ) - else: - print('Warning, could not find the condition attribute in ModuleXMLElement in evaluate for:') - print(xmlElement) - return - if len( self.conditionSplitWords ) < 1: - self.conditionSplitWords = None - print('Warning, could not get split words for the condition attribute in ModuleXMLElement in evaluate for:') - print(xmlElement) - nextIndex = getNextChildIndex(xmlElement) - if nextIndex >= len( xmlElement.parent.children ): - return - nextXMLElement = xmlElement.parent.children[ nextIndex ] - lowerClassName = nextXMLElement.className.lower() - if lowerClassName != 'else' and lowerClassName != 'elif': - return - xmlProcessor = xmlElement.getXMLProcessor() - if lowerClassName not in xmlProcessor.namePathDictionary: - return - self.pluginModule = archive.getModuleWithPath( xmlProcessor.namePathDictionary[ lowerClassName ] ) - if self.pluginModule is None: - return - self.elseElement = nextXMLElement - - def processElse( self, xmlElement): - """Process the else statement.""" - if self.elseElement is not None: - self.pluginModule.processElse( self.elseElement) - - -globalCreationDictionary = archive.getGeometryDictionary('creation') -globalDictionaryOperatorBegin = { - '||' : EvaluatorConcatenate, - '==' : EvaluatorEqual, - '>=' : EvaluatorGreaterEqual, - '<=' : EvaluatorLessEqual, - '!=' : EvaluatorNotEqual, - '**' : EvaluatorPower } -globalModuleEvaluatorDictionary = {} -globalFundamentalNameSet = set(archive.getPluginFileNamesFromDirectoryPath(archive.getFundamentalsPath())) -addPrefixDictionary(globalModuleEvaluatorDictionary, globalFundamentalNameSet, EvaluatorFundamental) -globalElementNameSet = set(archive.getPluginFileNamesFromDirectoryPath(archive.getElementsPath())) -addPrefixDictionary(globalModuleEvaluatorDictionary, globalElementNameSet, EvaluatorElement) -globalModuleEvaluatorDictionary['self'] = EvaluatorSelf -globalSplitDictionaryOperator = { - '+' : EvaluatorAddition, - '{' : EvaluatorBracketCurly, - '}' : Evaluator, - '(' : EvaluatorBracketRound, - ')' : Evaluator, - '[' : EvaluatorBracketSquare, - ']' : Evaluator, - ',' : EvaluatorComma, - ':' : EvaluatorDictionary, - '/' : EvaluatorDivision, - '>' : EvaluatorGreater, - '<' : EvaluatorLess, - '%' : EvaluatorModulo, - '*' : EvaluatorMultiplication, - '-' : EvaluatorSubtraction } -globalSplitDictionary = getSplitDictionary() # must be after globalSplitDictionaryOperator diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_elements/__init__.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_elements/__init__.py deleted file mode 100644 index 58ec332..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_elements/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 4 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_elements/creation.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_elements/creation.py deleted file mode 100644 index 00aa3d7..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_elements/creation.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -Boolean geometry utilities. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def _getAccessibleAttribute(attributeName, xmlElement): - """Get the accessible attribute.""" - functionName = attributeName[len('get') :].lower() - if functionName not in evaluate.globalCreationDictionary: - print('Warning, functionName not in globalCreationDictionary in _getAccessibleAttribute in creation for:') - print(functionName) - print(xmlElement) - return None - pluginModule = archive.getModuleWithPath(evaluate.globalCreationDictionary[functionName]) - if pluginModule is None: - print('Warning, _getAccessibleAttribute in creation can not get a pluginModule for:') - print(functionName) - print(xmlElement) - return None - return Creation(pluginModule, xmlElement).getCreation - - -class Creation: - """Class to handle a creation.""" - def __init__(self, pluginModule, xmlElement): - """Initialize.""" - self.pluginModule = pluginModule - self.xmlElement = xmlElement - - def __repr__(self): - """Get the string representation of this creation.""" - return self.xmlElement - - def getCreation(self, *arguments): - """Get creation.""" - dictionary = {'_fromCreationEvaluator': 'true'} - firstArgument = None - if len(arguments) > 0: - firstArgument = arguments[0] - if firstArgument.__class__ == dict: - dictionary.update(firstArgument) - return self.pluginModule.getGeometryOutput(None, self.xmlElement.getCopyShallow(dictionary)) - copyShallow = self.xmlElement.getCopyShallow(dictionary) - return self.pluginModule.getGeometryOutputByArguments(arguments, copyShallow) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_elements/document.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_elements/document.py deleted file mode 100644 index fb796c1..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_elements/document.py +++ /dev/null @@ -1,113 +0,0 @@ -""" -Boolean geometry utilities. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def _getAccessibleAttribute(attributeName, xmlElement): - """Get the accessible attribute.""" - if attributeName in globalGetAccessibleAttributeSet: - return getattr(Document(xmlElement), attributeName, None) - return None - - -class Document: - """Class to get handle xmlElements in a document.""" - def __init__(self, xmlElement): - """Initialize.""" - self.xmlElement = xmlElement - - def __repr__(self): - """Get the string representation of this Document.""" - return self.xmlElement - - def getByID(self, idKey): - """Get element by id.""" - return self.getElementByID(idKey) - - def getByName(self, nameKey): - """Get element by name.""" - return self.getElementsByName(nameKey) - - def getCascadeFloat(self, defaultFloat, key): - """Get cascade float.""" - return self.xmlElement.getCascadeFloat(defaultFloat, key) - - def getElementByID(self, idKey): - """Get element by id.""" - elementByID = self.xmlElement.getXMLElementByImportID(idKey) - if elementByID is None: - print('Warning, could not get elementByID in getElementByID in document for:') - print(idKey) - print(self.xmlElement) - return elementByID - - def getElementsByName(self, nameKey): - """Get element by name.""" - elementsByName = self.xmlElement.getXMLElementsByImportName(nameKey) - if elementsByName is None: - print('Warning, could not get elementsByName in getElementsByName in document for:') - print(nameKey) - print(self.xmlElement) - return elementsByName - - def getElementsByTag(self, tagKey): - """Get element by tag.""" - elementsByTag = self.xmlElement.getXMLElementsByTag(tagKey) - if elementsByTag is None: - print('Warning, could not get elementsByTag in getElementsByTag in document for:') - print(tagKey) - print(self.xmlElement) - return elementsByTag - - def getParent(self): - """Get parent element.""" - return self.getParentElement() - - def getParentElement(self): - """Get parent element.""" - return self.xmlElement.parent - - def getPrevious(self): - """Get previous element.""" - return self.getPreviousElement() - - def getPreviousElement(self): - """Get previous element.""" - return self.xmlElement.getPreviousXMLElement() - - def getPreviousVertex(self): - """Get previous element.""" - return self.xmlElement.getPreviousVertex() - - def getRoot(self): - """Get root element.""" - return self.getRootElement() - - def getRootElement(self): - """Get root element.""" - return self.xmlElement.getRoot() - - def getSelf(self): - """Get self element.""" - return self.getSelfElement() - - def getSelfElement(self): - """Get self element.""" - return self.xmlElement - - -globalAccessibleAttributes = 'getByID getByName getCascadeFloat getElementByID getElementsByName getElementsByTag'.split() -globalAccessibleAttributes += 'getParent getParentElement getPrevious getPreviousElement getPreviousVertex getRoot'.split() -globalAccessibleAttributes += 'getRootElement getSelf getSelfElement'.split() -globalGetAccessibleAttributeSet = set(globalAccessibleAttributes) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_elements/setting.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_elements/setting.py deleted file mode 100644 index 221b09d..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_elements/setting.py +++ /dev/null @@ -1,144 +0,0 @@ -""" -Boolean geometry utilities. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def _getAccessibleAttribute(attributeName, xmlElement): - """Get the accessible attribute.""" - if attributeName in globalGetAccessibleAttributeSet: - return getattr(Setting(xmlElement), attributeName, None) - return None - -def getCascadeFloatWithoutSelf(defaultFloat, key, xmlElement): - """Get the importRadius.""" - if key in xmlElement.attributeDictionary: - value = xmlElement.attributeDictionary[key] - functionName = 'get' + key[0].upper() + key[1 :] - if functionName in value: - if xmlElement.parent is None: - return defaultFloat - else: - xmlElement = xmlElement.parent - return xmlElement.getCascadeFloat(defaultFloat, key) - -def getImportRadius(xmlElement): - """Get the importRadius.""" - if xmlElement is None: - return 0.6 - return getCascadeFloatWithoutSelf(1.5 * getLayerThickness(xmlElement), 'importRadius', xmlElement) - -def getInteriorOverhangAngle(xmlElement): - """Get the interior overhang support angle in degrees.""" - return getCascadeFloatWithoutSelf(30.0, 'interiorOverhangAngle', xmlElement) - -def getInteriorOverhangRadians(xmlElement): - """Get the interior overhang support angle in radians.""" - return math.radians(getInteriorOverhangAngle(xmlElement)) - -def getLayerThickness(xmlElement): - """Get the layer thickness.""" - if xmlElement is None: - return 0.4 - return getCascadeFloatWithoutSelf(0.4, 'layerThickness', xmlElement) - -def getOverhangSpan(xmlElement): - """Get the overhang span.""" - return getCascadeFloatWithoutSelf(2.0 * getLayerThickness(xmlElement), 'overhangSpan', xmlElement) - -def getOverhangAngle(xmlElement): - """Get the overhang support angle in degrees.""" - return getCascadeFloatWithoutSelf(45.0, 'overhangAngle', xmlElement) - -def getOverhangRadians(xmlElement): - """Get the overhang support angle in radians.""" - return math.radians(getOverhangAngle(xmlElement)) - -def getPrecision(xmlElement): - """Get the cascade precision.""" - return getCascadeFloatWithoutSelf(0.2 * getLayerThickness(xmlElement), 'precision', xmlElement) - -def getSheetThickness(xmlElement): - """Get the sheet thickness.""" - return getCascadeFloatWithoutSelf(3.0, 'sheetThickness', xmlElement) - -def getTwistPrecision(xmlElement): - """Get the twist precision in degrees.""" - return getCascadeFloatWithoutSelf(5.0, 'twistPrecision', xmlElement) - -def getTwistPrecisionRadians(xmlElement): - """Get the twist precision in radians.""" - return math.radians(getTwistPrecision(xmlElement)) - - -class Setting: - """Class to get handle xmlElements in a setting.""" - def __init__(self, xmlElement): - """Initialize.""" - self.xmlElement = xmlElement - - def __repr__(self): - """Get the string representation of this Setting.""" - return self.xmlElement - - def getImportRadius(self): - """Get the importRadius.""" - return getImportRadius(self.xmlElement) - - def getInteriorOverhangAngle(self): - """Get the interior overhang support angle in degrees.""" - return getInteriorOverhangAngle(self.xmlElement) - - def getInteriorOverhangRadians(self): - """Get the interior overhang support angle in radians.""" - return getInteriorOverhangRadians(self.xmlElement) - - def getLayerThickness(self): - """Get the layer thickness.""" - return getLayerThickness(self.xmlElement) - - def getOverhangSpan(self): - """Get the overhang span.""" - return getOverhangSpan(self.xmlElement) - - def getOverhangAngle(self): - """Get the overhang support angle in degrees.""" - return getOverhangAngle(self.xmlElement) - - def getOverhangRadians(self): - """Get the overhang support angle in radians.""" - return getOverhangRadians(self.xmlElement) - - def getPrecision(self): - """Get the cascade precision.""" - return getPrecision(self.xmlElement) - - def getSheetThickness(self): - """Get the sheet thickness.""" - return getSheetThickness(self.xmlElement) - - def getTwistPrecision(self): - """Get the twist precision in degrees.""" - return getTwistPrecision(self.xmlElement) - - def getTwistPrecisionRadians(self): - """Get the twist precision in radians.""" - return getTwistPrecisionRadians(self.xmlElement) - - -globalAccessibleAttributes = 'getImportRadius getInteriorOverhangAngle getInteriorOverhangRadians'.split() -globalAccessibleAttributes += 'getLayerThickness getOverhangSpan getOverhangAngle getOverhangRadians'.split() -globalAccessibleAttributes += 'getPrecision getSheetThickness getTwistPrecision getTwistPrecisionRadians'.split() -globalGetAccessibleAttributeSet = set(globalAccessibleAttributes) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_enumerables/__init__.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_enumerables/__init__.py deleted file mode 100644 index 58ec332..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_enumerables/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 4 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_enumerables/dictionary_attribute.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_enumerables/dictionary_attribute.py deleted file mode 100644 index 7399db7..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_enumerables/dictionary_attribute.py +++ /dev/null @@ -1,102 +0,0 @@ -""" -Dictionary object attributes. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import euclidean - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def _getAccessibleAttribute(attributeName, dictionaryObject): - """Get the accessible attribute.""" - if attributeName in globalNativeFunctionSet: - return getattr(dictionaryObject, attributeName, None) - if attributeName in globalGetAccessibleAttributeSet: - stringAttribute = DictionaryAttribute(dictionaryObject) - return getattr(stringAttribute, attributeName, None) - return None - - -class DictionaryAttribute: - """Class to handle a dictionary.""" - def __init__(self, dictionaryObject): - """Initialize.""" - self.dictionaryObject = dictionaryObject - - def __repr__(self): - """Get the dictionary representation of this DictionaryAttribute.""" - return str(self.dictionaryObject) - - def count(self, value): - """Get the count.""" - countTotal = 0 - for key, iteratorValue in self.dictionaryObject.iteritems(): - if iteratorValue == value: - countTotal += 1 - return countTotal - - def delete(self, arguments): - """Get the delete dictionary.""" - if arguments.__class__ != list: - del self.dictionaryObject[arguments] - return self.dictionaryObject - if len(arguments) == 0: - self.dictionaryObject.clear() - return self.dictionaryObject - if len(arguments) == 1: - del self.dictionaryObject[arguments[0]] - return self.dictionaryObject - for enumeratorKey in euclidean.getEnumeratorKeysAlwaysList(self.dictionaryObject, arguments): - del self.dictionaryObject[enumeratorKey] - return self.dictionaryObject - - def getIsIn(self, value): - """Determine if the value is in.""" - return value in self.dictionaryObject - - def getIsNotIn(self, value): - """Determine if the value is in.""" - return not(value in self.dictionaryObject) - - def getLength(self): - """Get the length.""" - return len(self.dictionaryObject) - - def getMax(self): - """Get the max.""" - return max(self.dictionaryObject) - - def getMin(self): - """Get the min.""" - return min(self.dictionaryObject) - - def index(self, value): - """Get the index element.""" - for key, iteratorValue in self.dictionaryObject.iteritems(): - if iteratorValue == value: - return key - raise ValueError('Value (%s) not found in index in DictionaryAttribute for (%s).' % (value, self.dictionaryObject)) - - def length(self): - """Get the length.""" - return len(self.dictionaryObject) - - def set(self, itemIndex, value): - """Set value.""" - self.dictionaryObject[itemIndex] = value - return self.dictionaryObject - - -globalAccessibleAttributes = 'count delete getIsIn getIsNotIn getLength getMax getMin index length set'.split() -globalGetAccessibleAttributeSet = set(globalAccessibleAttributes) -globalNativeFunctions = 'clear copy fromkeys get items keys pop popitem remove setdefault update values'.split() -globalNativeFunctionSet = set(globalNativeFunctions) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_enumerables/list_attribute.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_enumerables/list_attribute.py deleted file mode 100644 index 0b26f78..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_enumerables/list_attribute.py +++ /dev/null @@ -1,123 +0,0 @@ -""" -List object attributes. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import euclidean - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def _getAccessibleAttribute(attributeName, listObject): - """Get the accessible attribute.""" - if attributeName in globalNativeFunctionSet: - return getattr(listObject, attributeName, None) - if attributeName in globalGetAccessibleAttributeSet: - stringAttribute = ListAttribute(listObject) - return getattr(stringAttribute, attributeName, None) - return None - - -class ListAttribute: - """Class to handle a list.""" - def __init__(self, listObject): - """Initialize.""" - self.listObject = listObject - - def __repr__(self): - """Get the list representation of this ListAttribute.""" - return str(self.listObject) - - def add(self, value): - """Get the concatenation, same as append.""" - return self.listObject + [value] - - def copy(self): - """Get the copy.""" - return self.listObject[:] - - def delete(self, arguments): - """Get the delete list.""" - deleteList = [] - enumeratorSet = set(euclidean.getEnumeratorKeysAlwaysList(self.listObject, arguments)) - for elementIndex, element in enumerate(self.listObject): - if elementIndex not in enumeratorSet: - deleteList.append(element) - return deleteList - - def get(self, itemIndex): - """Get value by index""" - return self.listObject[itemIndex] - - def getExpansion(self, items): - """Get the concatenated copies.""" - expansion = [] - for itemIndex in xrange(items): - expansion += self.listObject[:] - return expansion - - def getIsIn(self, value): - """Determine if the value is in.""" - return value in self.listObject - - def getIsNotIn(self, value): - """Determine if the value is in.""" - return not(value in self.listObject) - - def getLength(self): - """Get the length.""" - return len(self.listObject) - - def getMax(self): - """Get the max.""" - return max(self.listObject) - - def getMin(self): - """Get the min.""" - return min(self.listObject) - - def insert(self, insertIndex, value): - """Get the insert list.""" - if insertIndex < 0: - insertIndex += len(self.listObject) - insertIndex = max(0, insertIndex) - return self.listObject[: insertIndex] + [value] + self.listObject[insertIndex :] - - def keys(self): - """Get the keys.""" - return range(len(self.listObject)) - - def length(self): - """Get the length.""" - return len(self.listObject) - - def rindex(self, value): - """Get the rindex element.""" - for elementIndex, element in enumerate(self.listObject): - if element == value: - return elementIndex - raise ValueError('Value (%s) not found in rindex in ListAttribute for (%s).' % (value, self.listObject)) - - def set(self, itemIndex, value): - """Set value.""" - self.listObject[itemIndex] = value - return self.listObject - - def values(self, arguments=None): - """Get the values.""" - return self.listObject - - -globalAccessibleAttributes = 'add copy count delete get getExpansion getIsIn getIsNotIn getLength getMax getMin'.split() -globalAccessibleAttributes += 'insert keys length rindex set values'.split() -globalGetAccessibleAttributeSet = set(globalAccessibleAttributes) -globalNativeFunctions = 'append extend index pop remove reverse sort'.split() -globalNativeFunctionSet = set(globalNativeFunctions) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_enumerables/string_attribute.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_enumerables/string_attribute.py deleted file mode 100644 index 5479eea..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_enumerables/string_attribute.py +++ /dev/null @@ -1,136 +0,0 @@ -""" -String object attributes. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import euclidean - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def _getAccessibleAttribute(attributeName, stringObject): - """Get the accessible attribute.""" - if attributeName in globalNativeFunctionSet: - return getattr(stringObject, attributeName, None) - if attributeName in globalGetAccessibleAttributeSet: - stringAttribute = StringAttribute(stringObject) - return getattr(stringAttribute, attributeName, None) - return None - - -class StringAttribute: - """Class to handle a string.""" - def __init__(self, stringObject): - """Initialize.""" - self.stringObject = stringObject - - def __repr__(self): - """Get the string representation of this StringAttribute.""" - return self.stringObject - - def add(self, nextString): - """Get the add string, same as append.""" - return self.stringObject + nextString - - def append(self, nextString): - """Get the append string.""" - return self.stringObject + nextString - - def copy(self): - """Get the copy.""" - return self.stringObject[:] - - def delete(self, arguments): - """Get the delete string.""" - deleteString = '' - enumeratorSet = set(euclidean.getEnumeratorKeysAlwaysList(self.stringObject, arguments)) - for characterIndex, character in enumerate(self.stringObject): - if characterIndex not in enumeratorSet: - deleteString += character - return deleteString - - def get(self, itemIndex): - """Get value by characterIndex""" - return self.stringObject[itemIndex] - - def getExpansion(self, items): - """Get the concatenated copies.""" - expansion = '' - for itemIndex in xrange(items): - expansion += self.stringObject - return expansion - - def getIsIn(self, value): - """Determine if the value is in.""" - return value in self.stringObject - - def getIsNotIn(self, value): - """Determine if the value is in.""" - return not(value in self.stringObject) - - def getLength(self): - """Get the length.""" - return len(self.stringObject) - - def getMax(self): - """Get the max.""" - return max(self.stringObject) - - def getMin(self): - """Get the min.""" - return min(self.stringObject) - - def insert(self, insertIndex, value): - """Get the insert string.""" - if insertIndex < 0: - insertIndex += len(self.stringObject) - insertIndex = max(0, insertIndex) - return self.stringObject[: insertIndex] + value + self.stringObject[insertIndex :] - - def keys(self): - """Get the keys.""" - return range(len(self.stringObject)) - - def length(self): - """Get the length.""" - return len(self.stringObject) - - def remove(self, value): - """Get the remove string.""" - removeIndex = self.stringObject.find(value) - if removeIndex > -1: - return self.stringObject[: removeIndex] + self.stringObject[removeIndex + len(value) :] - return self.stringObject - - def reverse(self): - """Get the reverse string.""" - return self.stringObject[: : -1] - - def set(self, itemIndex, value): - """Set value.""" - self.stringObject[itemIndex] = value - return self.stringObject - - def values(self): - """Get the values.""" - values = [] - for character in self.stringObject: - values.append(character) - return values - - -globalAccessibleAttributes = 'add append copy delete get getExpansion getIsIn getIsNotIn getLength getMax getMin'.split() -globalAccessibleAttributes += 'insert keys length remove reverse set values'.split() -globalGetAccessibleAttributeSet = set(globalAccessibleAttributes) -globalNativeFunctions = 'capitalize center count decode encode endswith expandtabs find format index isalnum join'.split() -globalNativeFunctions += 'isalpha isdigit islower isspace istitle isupper ljust lower lstrip partition replace rfind rindex'.split() -globalNativeFunctions += 'rjust rpartition rsplit rstrip split splitlines startswith strip swapcase title translate upper zfill'.split() -globalNativeFunctionSet = set(globalNativeFunctions) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_fundamentals/__init__.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_fundamentals/__init__.py deleted file mode 100644 index 58ec332..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_fundamentals/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 4 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_fundamentals/_math.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_fundamentals/_math.py deleted file mode 100644 index 050dd3a..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_fundamentals/_math.py +++ /dev/null @@ -1,101 +0,0 @@ -""" -Boolean geometry utilities. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalNativeFunctions = 'acos asin atan atan2 ceil cos cosh degrees e exp fabs floor fmod frexp hypot'.split() -globalNativeFunctions += 'ldexp log log10 modf pi pow radians sin sinh sqrt tan tanh trunc'.split() -globalNativeFunctionSet = set(globalNativeFunctions) -#Constants from: http://www.physlink.com/reference/MathConstants.cfm -#Tau is from: http://tauday.com/ -#If anyone wants to add stuff, more constants are at: http://en.wikipedia.org/wiki/Mathematical_constant -globalMathConstantDictionary = { - 'euler' : 0.5772156649015328606065120, - 'golden' : euclidean.globalGoldenRatio, - 'goldenAngle' : euclidean.globalGoldenAngle, - 'goldenRatio' : euclidean.globalGoldenRatio, - 'tau' : euclidean.globalTau} - - -def _getAccessibleAttribute(attributeName): - """Get the accessible attribute.""" - if attributeName in globalMathConstantDictionary: - return globalMathConstantDictionary[attributeName] - if attributeName in globalNativeFunctionSet: - return math.__dict__[attributeName] - if attributeName in globalAccessibleAttributeDictionary: - return globalAccessibleAttributeDictionary[attributeName] - return None - - -def getAbs(value): - """Get the abs.""" - return abs(value) - -def getBoolean(value): - """Get the boolean.""" - return bool(value) - -def getDivmod(x, y): - """Get the divmod.""" - return divmod(x, y) - -def getFloat(value): - """Get the float.""" - return float(value) - -def getHex(value): - """Get the hex.""" - return hex(value) - -def getInt(value): - """Get the int.""" - return int(value) - -def getLong(value): - """Get the long.""" - return long(value) - -def getMax(first, second): - """Get the max.""" - return max(first, second) - -def getMin(first, second): - """Get the min.""" - return min(first, second) - -def getRound(value): - """Get the round.""" - return round(value) - -def getString(value): - """Get the string.""" - return str(value) - - -globalAccessibleAttributeDictionary = { - 'abs' : getAbs, - 'boolean' : getBoolean, - 'divmod' : getDivmod, - 'float' : getFloat, - 'hex' : getHex, - 'int' : getInt, - 'long' : getLong, - 'max' : getMax, - 'min' : getMin, - 'round' : getRound, - 'string' : getString} diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_fundamentals/euclid.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_fundamentals/euclid.py deleted file mode 100644 index 4a50b6b..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_fundamentals/euclid.py +++ /dev/null @@ -1,95 +0,0 @@ -""" -Boolean geometry utilities. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities.vector3index import Vector3Index -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def _getAccessibleAttribute(attributeName): - """Get the accessible attribute.""" - if attributeName in globalAccessibleAttributeDictionary: - return globalAccessibleAttributeDictionary[attributeName] - return None - -def getComplex(x=0.0, y=0.0): - """Get the complex.""" - return complex(x, y) - -def getCylindrical(azimuthDegrees, radius=1.0, z=0.0): - """Get the cylindrical vector3 by degrees.""" - return getCylindricalByRadians(math.radians(azimuthDegrees), radius, z) - -def getCylindricalByRadians(azimuthRadians, radius=1.0, z=0.0): - """Get the cylindrical vector3 by radians.""" - polar = radius * euclidean.getWiddershinsUnitPolar(azimuthRadians) - return Vector3(polar.real, polar.imag, z) - -def getNestedVectorTestExample(x=0.0, y=0.0, z=0.0): - """Get the NestedVectorTestExample.""" - return NestedVectorTestExample(Vector3(x, y, z)) - -def getPolar(angleDegrees, radius=1.0): - """Get the complex polar by degrees.""" - return radius * euclidean.getWiddershinsUnitPolar(math.radians(angleDegrees)) - -def getPolarByRadians(angleRadians, radius=1.0): - """Get the complex polar by radians.""" - return radius * euclidean.getWiddershinsUnitPolar(angleRadians) - -def getSpherical(azimuthDegrees, elevationDegrees, radius=1.0): - """Get the spherical vector3 unit by degrees.""" - return getSphericalByRadians(math.radians(azimuthDegrees), math.radians(elevationDegrees), radius) - -def getSphericalByRadians(azimuthRadians, elevationRadians, radius=1.0): - """Get the spherical vector3 unit by radians.""" - elevationComplex = euclidean.getWiddershinsUnitPolar(elevationRadians) - azimuthComplex = euclidean.getWiddershinsUnitPolar(azimuthRadians) * elevationComplex.real - return Vector3(azimuthComplex.real, azimuthComplex.imag, elevationComplex.imag) * radius - -def getVector3(x=0.0, y=0.0, z=0.0): - """Get the vector3.""" - return Vector3(x, y, z) - -def getVector3Index(index=0, x=0.0, y=0.0, z=0.0): - """Get the vector3.""" - return Vector3Index(index, x, y, z) - - -class NestedVectorTestExample: - """Class to test local attribute.""" - def __init__(self, vector3): - """Get the accessible attribute.""" - self.vector3 = vector3 - - def _getAccessibleAttribute(self, attributeName): - """Get the accessible attribute.""" - if attributeName == 'vector3': - return getattr(self, attributeName, None) - return None - - -globalAccessibleAttributeDictionary = { - 'complex' : getComplex, - 'getCylindrical' : getCylindrical, - 'getCylindricalByRadians' : getCylindricalByRadians, - 'getPolar' : getPolar, - 'getPolarByRadians' : getPolarByRadians, - 'getSpherical' : getSpherical, - 'getSphericalByRadians' : getSphericalByRadians, - 'NestedVectorTestExample' : getNestedVectorTestExample, - 'Vector3' : getVector3, - 'Vector3Index' : getVector3Index} diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_fundamentals/print.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_fundamentals/print.py deleted file mode 100644 index 6a24f46..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/evaluate_fundamentals/print.py +++ /dev/null @@ -1,36 +0,0 @@ -""" -Boolean geometry utilities. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def _getAccessibleAttribute(attributeName): - """Get the accessible attribute.""" - if attributeName in globalAccessibleAttributeDictionary: - return globalAccessibleAttributeDictionary[attributeName] - return None - -def continuous(valueString): - """Print continuous.""" - sys.stdout.write(str(valueString)) - return valueString - -def line(valueString): - """Print line.""" - print(valueString) - return valueString - - -globalAccessibleAttributeDictionary = {'continuous' : continuous, 'line' : line} diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/example.csv b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/example.csv deleted file mode 100644 index eeecad1..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/example.csv +++ /dev/null @@ -1,22 +0,0 @@ -"A" -0 0 -2 8 -4 0 - -1 4 -3 4 - -"B" -0 4 -2 4 -4 5 -4 7 -3 8 -0 8 -0 0 -3 0 -4 1 -4 3 -2 4 - -"C" diff --git a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/matrix.py b/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/matrix.py deleted file mode 100644 index d879db9..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/geometry_utilities/matrix.py +++ /dev/null @@ -1,458 +0,0 @@ -""" -Boolean geometry four by four matrix. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import xml_simple_writer -import cStringIO -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = 300 - - -def addVertexes(geometryOutput, vertexes): - """Add the vertexes.""" - if geometryOutput.__class__ == list: - for element in geometryOutput: - addVertexes(element, vertexes) - return - if geometryOutput.__class__ != dict: - return - for geometryOutputKey in geometryOutput.keys(): - geometryOutputValue = geometryOutput[geometryOutputKey] - if geometryOutputKey == 'vertex': - for vertex in geometryOutputValue: - vertexes.append(vertex) - else: - addVertexes(geometryOutputValue, vertexes) - -def getBranchMatrix(xmlElement): - """Get matrix starting from the object if it exists, otherwise get a matrix starting from stratch.""" - branchMatrix = Matrix() - matrixChildElement = xmlElement.getFirstChildWithClassName('matrix') - if matrixChildElement is not None: - branchMatrix = branchMatrix.getFromXMLElement('', matrixChildElement) - branchMatrix = branchMatrix.getFromXMLElement('matrix.', xmlElement) - if xmlElement.xmlObject is None: - return branchMatrix - xmlElementMatrix = xmlElement.xmlObject.getMatrix4X4() - if xmlElementMatrix is None: - return branchMatrix - return xmlElementMatrix.getOtherTimesSelf(branchMatrix.tetragrid) - -def getBranchMatrixSetXMLElement(xmlElement): - """Get matrix starting from the object if it exists, otherwise get a matrix starting from stratch.""" - branchMatrix = getBranchMatrix(xmlElement) - setXMLElementDictionaryMatrix(branchMatrix, xmlElement) - return branchMatrix - -def getCumulativeVector3Remove(defaultVector3, prefix, xmlElement): - """Get cumulative vector3 and delete the prefixed attributes.""" - if prefix == '': - defaultVector3.x = evaluate.getEvaluatedFloat(defaultVector3.x, 'x', xmlElement) - defaultVector3.y = evaluate.getEvaluatedFloat(defaultVector3.y, 'y', xmlElement) - defaultVector3.z = evaluate.getEvaluatedFloat(defaultVector3.z, 'z', xmlElement) - euclidean.removeElementsFromDictionary(xmlElement.attributeDictionary, ['x', 'y', 'z']) - prefix = 'cartesian' - defaultVector3 = evaluate.getVector3ByPrefix(defaultVector3, prefix, xmlElement) - euclidean.removePrefixFromDictionary(xmlElement.attributeDictionary, prefix) - return defaultVector3 - -def getDiagonalSwitchedTetragrid(angleDegrees, diagonals): - """Get the diagonals and switched matrix by degrees.""" - return getDiagonalSwitchedTetragridByRadians(math.radians(angleDegrees), diagonals) - -def getDiagonalSwitchedTetragridByRadians(angleRadians, diagonals): - """Get the diagonals and switched matrix by radians.""" - return getDiagonalSwitchedTetragridByPolar(diagonals, euclidean.getWiddershinsUnitPolar(angleRadians)) - -def getDiagonalSwitchedTetragridByPolar(diagonals, unitPolar): - """Get the diagonals and switched matrix by unitPolar.""" - diagonalSwitchedTetragrid = getIdentityTetragrid() - for diagonal in diagonals: - diagonalSwitchedTetragrid[diagonal][diagonal] = unitPolar.real - diagonalSwitchedTetragrid[diagonals[0]][diagonals[1]] = -unitPolar.imag - diagonalSwitchedTetragrid[diagonals[1]][diagonals[0]] = unitPolar.imag - return diagonalSwitchedTetragrid - -def getIdentityTetragrid(tetragrid=None): - """Get four by four matrix with diagonal elements set to one.""" - if tetragrid is None: - return [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]] - return tetragrid - -def getKeyA(row, column, prefix=''): - """Get the a format key string from row & column, counting from zero.""" - return '%sa%s%s' % (prefix, row, column) - -def getKeyM(row, column, prefix=''): - """Get the m format key string from row & column, counting from one.""" - return '%sm%s%s' % (prefix, row + 1, column + 1) - -def getKeysA(prefix=''): - """Get the matrix keys, counting from zero.""" - keysA = [] - for row in xrange(4): - for column in xrange(4): - key = getKeyA(row, column, prefix) - keysA.append(key) - return keysA - -def getKeysM(prefix=''): - """Get the matrix keys, counting from one.""" - keysM = [] - for row in xrange(4): - for column in xrange(4): - key = getKeyM(row, column, prefix) - keysM.append(key) - return keysM - -def getRemovedFloat(defaultFloat, key, prefix, xmlElement): - """Get the float by the key and the prefix.""" - prefixKey = prefix + key - if prefixKey in xmlElement.attributeDictionary: - floatValue = evaluate.getEvaluatedFloat(None, prefixKey, xmlElement) - if floatValue is None: - print('Warning, evaluated value in getRemovedFloatByKeys in matrix is None for key:') - print(prefixKey) - print('for xmlElement dictionary value:') - print(xmlElement.attributeDictionary[prefixKey]) - print('for xmlElement dictionary:') - print(xmlElement.attributeDictionary) - else: - defaultFloat = floatValue - del xmlElement.attributeDictionary[prefixKey] - return defaultFloat - -def getRemovedFloatByKeys(defaultFloat, keys, prefix, xmlElement): - """Get the float by the keys and the prefix.""" - for key in keys: - defaultFloat = getRemovedFloat(defaultFloat, key, prefix, xmlElement) - return defaultFloat - -def getRotateAroundAxisTetragrid(prefix, xmlElement): - """Get rotate around axis tetragrid and delete the axis and angle attributes.""" - angle = getRemovedFloatByKeys(0.0, ['angle', 'counterclockwise'], prefix, xmlElement) - angle -= getRemovedFloat(0.0, 'clockwise', prefix, xmlElement) - if angle == 0.0: - return None - angleRadians = math.radians(angle) - axis = getCumulativeVector3Remove(Vector3(), prefix + 'axis', xmlElement) - axisLength = abs(axis) - if axisLength <= 0.0: - print('Warning, axisLength was zero in getRotateAroundAxisTetragrid in matrix so nothing will be done for:') - print(xmlElement) - return None - axis /= axisLength - tetragrid = getIdentityTetragrid() - cosAngle = math.cos(angleRadians) - sinAngle = math.sin(angleRadians) - oneMinusCos = 1.0 - math.cos(angleRadians) - xx = axis.x * axis.x - xy = axis.x * axis.y - xz = axis.x * axis.z - yy = axis.y * axis.y - yz = axis.y * axis.z - zz = axis.z * axis.z - tetragrid[0] = [cosAngle + xx * oneMinusCos, xy * oneMinusCos - axis.z * sinAngle, xz * oneMinusCos + axis.y * sinAngle, 0.0] - tetragrid[1] = [xy * oneMinusCos + axis.z * sinAngle, cosAngle + yy * oneMinusCos, yz * oneMinusCos - axis.x * sinAngle, 0.0] - tetragrid[2] = [xz * oneMinusCos - axis.y * sinAngle, yz * oneMinusCos + axis.x * sinAngle, cosAngle + zz * oneMinusCos, 0.0] - return tetragrid - -def getRotateTetragrid(prefix, xmlElement): - """Get rotate tetragrid and delete the rotate attributes.""" - # http://en.wikipedia.org/wiki/Rotation_matrix - rotateMatrix = Matrix() - rotateMatrix.tetragrid = getRotateAroundAxisTetragrid(prefix, xmlElement) - zAngle = getRemovedFloatByKeys(0.0, ['axisclockwisez', 'observerclockwisez', 'z'], prefix, xmlElement) - zAngle -= getRemovedFloatByKeys(0.0, ['axiscounterclockwisez', 'observercounterclockwisez'], prefix, xmlElement) - if zAngle != 0.0: - rotateMatrix.tetragrid = getTetragridTimesOther(getDiagonalSwitchedTetragrid(-zAngle, [0, 1]), rotateMatrix.tetragrid) - xAngle = getRemovedFloatByKeys(0.0, ['axisclockwisex', 'observerclockwisex', 'x'], prefix, xmlElement) - xAngle -= getRemovedFloatByKeys(0.0, ['axiscounterclockwisex', 'observercounterclockwisex'], prefix, xmlElement) - if xAngle != 0.0: - rotateMatrix.tetragrid = getTetragridTimesOther(getDiagonalSwitchedTetragrid(-xAngle, [1, 2]), rotateMatrix.tetragrid) - yAngle = getRemovedFloatByKeys(0.0, ['axiscounterclockwisey', 'observerclockwisey', 'y'], prefix, xmlElement) - yAngle -= getRemovedFloatByKeys(0.0, ['axisclockwisey', 'observercounterclockwisey'], prefix, xmlElement) - if yAngle != 0.0: - rotateMatrix.tetragrid = getTetragridTimesOther(getDiagonalSwitchedTetragrid(yAngle, [0, 2]), rotateMatrix.tetragrid) - return rotateMatrix.tetragrid - -def getScaleTetragrid(prefix, xmlElement): - """Get scale matrix and delete the scale attributes.""" - scaleDefaultVector3 = Vector3(1.0, 1.0, 1.0) - scale = getCumulativeVector3Remove(scaleDefaultVector3.copy(), prefix, xmlElement) - if scale == scaleDefaultVector3: - return None - return [[scale.x, 0.0, 0.0, 0.0], [0.0, scale.y, 0.0, 0.0], [0.0, 0.0, scale.z, 0.0], [0.0, 0.0, 0.0, 1.0]] - -def getTetragridA(prefix, tetragrid, xmlElement): - """Get the tetragrid from the xmlElement letter a values.""" - keysA = getKeysA(prefix) - evaluatedDictionary = evaluate.getEvaluatedDictionaryByEvaluationKeys(keysA, xmlElement) - if len(evaluatedDictionary.keys()) < 1: - return tetragrid - for row in xrange(4): - for column in xrange(4): - key = getKeyA(row, column, prefix) - if key in evaluatedDictionary: - value = evaluatedDictionary[key] - if value is None or value == 'None': - print('Warning, value in getTetragridA in matrix is None for key for dictionary:') - print(key) - print(evaluatedDictionary) - else: - tetragrid = getIdentityTetragrid(tetragrid) - tetragrid[row][column] = float(value) - euclidean.removeElementsFromDictionary(xmlElement.attributeDictionary, keysA) - return tetragrid - -def getTetragridC(prefix, tetragrid, xmlElement): - """Get the matrix Tetragrid from the xmlElement letter c values.""" - columnKeys = 'Pc1 Pc2 Pc3 Pc4'.replace('P', prefix).split() - evaluatedDictionary = evaluate.getEvaluatedDictionaryByEvaluationKeys(columnKeys, xmlElement) - if len(evaluatedDictionary.keys()) < 1: - return tetragrid - for columnKeyIndex, columnKey in enumerate(columnKeys): - if columnKey in evaluatedDictionary: - value = evaluatedDictionary[columnKey] - if value is None or value == 'None': - print('Warning, value in getTetragridC in matrix is None for columnKey for dictionary:') - print(columnKey) - print(evaluatedDictionary) - else: - tetragrid = getIdentityTetragrid(tetragrid) - for elementIndex, element in enumerate(value): - tetragrid[elementIndex][columnKeyIndex] = element - euclidean.removeElementsFromDictionary(xmlElement.attributeDictionary, columnKeys) - return tetragrid - -def getTetragridCopy(tetragrid): - """Get tetragrid copy.""" - tetragridCopy = [] - for tetragridRow in tetragrid: - tetragridCopy.append(tetragridRow[:]) - return tetragridCopy - -def getTetragridM(prefix, tetragrid, xmlElement): - """Get the tetragrid from the xmlElement letter m values.""" - keysM = getKeysM(prefix) - evaluatedDictionary = evaluate.getEvaluatedDictionaryByEvaluationKeys(keysM, xmlElement) - if len(evaluatedDictionary.keys()) < 1: - return tetragrid - for row in xrange(4): - for column in xrange(4): - key = getKeyM(row, column, prefix) - if key in evaluatedDictionary: - value = evaluatedDictionary[key] - if value is None or value == 'None': - print('Warning, value in getTetragridM in matrix is None for key for dictionary:') - print(key) - print(evaluatedDictionary) - else: - tetragrid = getIdentityTetragrid(tetragrid) - tetragrid[row][column] = float(value) - euclidean.removeElementsFromDictionary(xmlElement.attributeDictionary, keysM) - return tetragrid - -def getTetragridMatrix(prefix, tetragrid, xmlElement): - """Get the tetragrid from the xmlElement matrix value.""" - matrixKey = prefix + 'matrix' - evaluatedDictionary = evaluate.getEvaluatedDictionaryByEvaluationKeys([matrixKey], xmlElement) - if len(evaluatedDictionary.keys()) < 1: - return tetragrid - value = evaluatedDictionary[matrixKey] - if value is None or value == 'None': - print('Warning, value in getTetragridMatrix in matrix is None for matrixKey for dictionary:') - print(matrixKey) - print(evaluatedDictionary) - else: - tetragrid = getIdentityTetragrid(tetragrid) - for rowIndex, row in enumerate(value): - for elementIndex, element in enumerate(row): - tetragrid[rowIndex][elementIndex] = element - euclidean.removeElementsFromDictionary(xmlElement.attributeDictionary, [matrixKey]) - return tetragrid - -def getTetragridR(prefix, tetragrid, xmlElement): - """Get the tetragrid from the xmlElement letter r values.""" - rowKeys = 'Pr1 Pr2 Pr3 Pr4'.replace('P', prefix).split() - evaluatedDictionary = evaluate.getEvaluatedDictionaryByEvaluationKeys(rowKeys, xmlElement) - if len(evaluatedDictionary.keys()) < 1: - return tetragrid - for rowKeyIndex, rowKey in enumerate(rowKeys): - if rowKey in evaluatedDictionary: - value = evaluatedDictionary[rowKey] - if value is None or value == 'None': - print('Warning, value in getTetragridR in matrix is None for rowKey for dictionary:') - print(rowKey) - print(evaluatedDictionary) - else: - tetragrid = getIdentityTetragrid(tetragrid) - for elementIndex, element in enumerate(value): - tetragrid[rowKeyIndex][elementIndex] = element - euclidean.removeElementsFromDictionary(xmlElement.attributeDictionary, rowKeys) - return tetragrid - -def getTetragridTimesOther(firstTetragrid, otherTetragrid ): - """Get this matrix multiplied by the other matrix.""" - #A down, B right from http://en.wikipedia.org/wiki/Matrix_multiplication - if firstTetragrid is None: - return otherTetragrid - if otherTetragrid is None: - return firstTetragrid - tetragridTimesOther = [] - for row in xrange(4): - matrixRow = firstTetragrid[row] - tetragridTimesOtherRow = [] - tetragridTimesOther.append(tetragridTimesOtherRow) - for column in xrange(4): - dotProduct = 0 - for elementIndex in xrange(4): - dotProduct += matrixRow[elementIndex] * otherTetragrid[elementIndex][column] - tetragridTimesOtherRow.append(dotProduct) - return tetragridTimesOther - -def getTransformedByList(floatList, point): - """Get the point transformed by the array.""" - return floatList[0] * point.x + floatList[1] * point.y + floatList[2] * point.z + floatList[3] - -def getTransformedVector3(tetragrid, vector3): - """Get the vector3 multiplied by a matrix.""" - if tetragrid is None: - return vector3.copy() - return Vector3( - getTransformedByList(tetragrid[0], vector3), - getTransformedByList(tetragrid[1], vector3), - getTransformedByList(tetragrid[2], vector3)) - -def getTransformedVector3s(tetragrid, vector3s): - """Get the vector3s multiplied by a matrix.""" - transformedVector3s = [] - for vector3 in vector3s: - transformedVector3s.append(getTransformedVector3(tetragrid, vector3)) - return transformedVector3s - -def getTransformTetragrid(prefix, xmlElement): - """Get the tetragrid from the xmlElement.""" - tetragrid = getTetragridA(prefix, None, xmlElement) - tetragrid = getTetragridC(prefix, tetragrid, xmlElement) - tetragrid = getTetragridM(prefix, tetragrid, xmlElement) - tetragrid = getTetragridMatrix(prefix, tetragrid, xmlElement) - tetragrid = getTetragridR(prefix, tetragrid, xmlElement) - return tetragrid - -def getTranslateTetragrid(prefix, xmlElement): - """Get translate matrix and delete the translate attributes.""" - translation = getCumulativeVector3Remove(Vector3(), prefix, xmlElement) - if translation.getIsDefault(): - return None - return getTranslateTetragridByTranslation(translation) - -def getTranslateTetragridByTranslation(translation): - """Get translate tetragrid by translation.""" - return [[1.0, 0.0, 0.0, translation.x], [0.0, 1.0, 0.0, translation.y], [0.0, 0.0, 1.0, translation.z], [0.0, 0.0, 0.0, 1.0]] - -def getVertexes(geometryOutput): - """Get the vertexes.""" - vertexes = [] - addVertexes(geometryOutput, vertexes) - return vertexes - -def setAttributeDictionaryToMultipliedTetragrid(tetragrid, xmlElement): - """Set the element attribute dictionary and element matrix to the matrix times the tetragrid.""" - setXMLElementDictionaryMatrix(getBranchMatrix(xmlElement).getOtherTimesSelf(tetragrid), xmlElement) - -def setXMLElementDictionaryMatrix(matrix4X4, xmlElement): - """Set the element attribute dictionary or element matrix to the matrix.""" - if xmlElement.xmlObject is None: - xmlElement.attributeDictionary.update(matrix4X4.getAttributeDictionary('matrix.')) - else: - xmlElement.xmlObject.matrix4X4 = matrix4X4 - -def transformVector3ByMatrix( tetragrid, vector3 ): - """Transform the vector3 by a matrix.""" - vector3.setToVector3(getTransformedVector3(tetragrid, vector3)) - - -class Matrix: - """A four by four matrix.""" - def __init__(self, tetragrid=None): - """Add empty lists.""" - if tetragrid is None: - self.tetragrid = None - return - self.tetragrid = getTetragridCopy(tetragrid) - - def __eq__(self, other): - """Determine whether this matrix is identical to other one.""" - if other is None: - return False - if other.__class__ != self.__class__: - return False - return other.tetragrid == self.tetragrid - - def __ne__(self, other): - """Determine whether this vector is not identical to other one.""" - return not self.__eq__(other) - - def __repr__(self): - """Get the string representation of this four by four matrix.""" - output = cStringIO.StringIO() - self.addXML(0, output) - return output.getvalue() - - def addXML(self, depth, output): - """Add xml for this object.""" - attributeDictionary = self.getAttributeDictionary() - if len(attributeDictionary) > 0: - xml_simple_writer.addClosedXMLTag(attributeDictionary, self.__class__.__name__.lower(), depth, output) - - def getAttributeDictionary(self, prefix=''): - """Get the attributeDictionary from row column attribute strings, counting from one.""" - attributeDictionary = {} - if self.tetragrid is None: - return attributeDictionary - for row in xrange(4): - for column in xrange(4): - default = float(column == row) - value = self.tetragrid[row][column] - if abs( value - default ) > 0.00000000000001: - if abs(value) < 0.00000000000001: - value = 0.0 - attributeDictionary[prefix + getKeyM(row, column)] = value - return attributeDictionary - - def getFromXMLElement(self, prefix, xmlElement): - """Get the values from row column attribute strings, counting from one.""" - attributeDictionary = xmlElement.attributeDictionary - if attributeDictionary is None: - return self - self.tetragrid = getTetragridTimesOther(getTransformTetragrid(prefix, xmlElement), self.tetragrid) - self.tetragrid = getTetragridTimesOther(getScaleTetragrid('scale.', xmlElement), self.tetragrid) - self.tetragrid = getTetragridTimesOther(getRotateTetragrid('rotate.', xmlElement), self.tetragrid) - self.tetragrid = getTetragridTimesOther(getTranslateTetragrid('translate.', xmlElement), self.tetragrid) - return self - - def getOtherTimesSelf(self, otherTetragrid): - """Get this matrix reverse multiplied by the other matrix.""" - return Matrix(getTetragridTimesOther(otherTetragrid, self.tetragrid)) - - def getSelfTimesOther(self, otherTetragrid): - """Get this matrix multiplied by the other matrix.""" - return Matrix(getTetragridTimesOther(self.tetragrid, otherTetragrid)) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_matrix/__init__.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_matrix/__init__.py deleted file mode 100644 index 1121e8a..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_matrix/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_matrix/_scale.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_matrix/_scale.py deleted file mode 100644 index 65f38cc..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_matrix/_scale.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Boolean geometry scale. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = 340 - - -def getManipulatedGeometryOutput(geometryOutput, prefix, xmlElement): - """Get equated geometryOutput.""" - scalePoints( matrix.getVertexes(geometryOutput), prefix, xmlElement ) - return geometryOutput - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get equated paths.""" - scalePoints( loop, prefix, xmlElement ) - return [loop] - -def manipulateXMLElement(target, xmlElement): - """Manipulate the xml element.""" - scaleTetragrid = matrix.getScaleTetragrid('', xmlElement) - if scaleTetragrid is None: - print('Warning, scaleTetragrid was None in scale so nothing will be done for:') - print(xmlElement) - return - matrix.setAttributeDictionaryToMultipliedTetragrid(scaleTetragrid, target) - -def processXMLElement(xmlElement): - """Process the xml element.""" - solid.processXMLElementByFunction( manipulateXMLElement, xmlElement) - -def scalePoints(points, prefix, xmlElement): - """Scale the points.""" - scaleDefaultVector3 = Vector3(1.0, 1.0, 1.0) - scaleVector3 = matrix.getCumulativeVector3Remove(scaleDefaultVector3.copy(), prefix, xmlElement) - if scaleVector3 == scaleDefaultVector3: - return - for point in points: - point.x *= scaleVector3.x - point.y *= scaleVector3.y - point.z *= scaleVector3.z diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_matrix/rotate.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_matrix/rotate.py deleted file mode 100644 index 22c8b5e..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_matrix/rotate.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Boolean geometry rotate. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = 360 - - -def getManipulatedGeometryOutput(geometryOutput, prefix, xmlElement): - """Get equated geometryOutput.""" - rotatePoints(matrix.getVertexes(geometryOutput), prefix, xmlElement) - return geometryOutput - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get equated paths.""" - rotatePoints(loop, prefix, xmlElement) - return [loop] - -def manipulateXMLElement(target, xmlElement): - """Manipulate the xml element.""" - rotateTetragrid = matrix.getRotateTetragrid('', xmlElement) - if rotateTetragrid is None: - print('Warning, rotateTetragrid was None in rotate so nothing will be done for:') - print(xmlElement) - return - matrix.setAttributeDictionaryToMultipliedTetragrid(rotateTetragrid, target) - -def processXMLElement(xmlElement): - """Process the xml element.""" - solid.processXMLElementByFunction(manipulateXMLElement, xmlElement) - -def rotatePoints(points, prefix, xmlElement): - """Rotate the points.""" - rotateTetragrid = matrix.getRotateTetragrid(prefix, xmlElement) - if rotateTetragrid is None: - print('Warning, rotateTetragrid was None in rotate so nothing will be done for:') - print(xmlElement) - return - for point in points: - matrix.transformVector3ByMatrix(rotateTetragrid, point) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_matrix/transform.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_matrix/transform.py deleted file mode 100644 index cd4ecc1..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_matrix/transform.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Boolean geometry transform. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = 320 - - -def getManipulatedGeometryOutput(geometryOutput, prefix, xmlElement): - """Get equated geometryOutput.""" - transformPoints(matrix.getVertexes(geometryOutput), prefix, xmlElement) - return geometryOutput - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get equated paths.""" - transformPoints(loop, prefix, xmlElement) - return [loop] - -def manipulateXMLElement(target, xmlElement): - """Manipulate the xml element.""" - transformTetragrid = matrix.getTransformTetragrid('', xmlElement) - if transformTetragrid is None: - print('Warning, transformTetragrid was None in transform so nothing will be done for:') - print(xmlElement) - return - matrix.setAttributeDictionaryToMultipliedTetragrid(transformTetragrid, target) - -def processXMLElement(xmlElement): - """Process the xml element.""" - solid.processXMLElementByFunction(manipulateXMLElement, xmlElement) - -def transformPoints(points, prefix, xmlElement): - """Transform the points.""" - transformTetragrid = matrix.getTransformTetragrid(prefix, xmlElement) - if transformTetragrid is None: - print('Warning, transformTetragrid was None in transform so nothing will be done for:') - print(xmlElement) - return - for point in points: - matrix.transformVector3ByMatrix(transformTetragrid, point) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_matrix/translate.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_matrix/translate.py deleted file mode 100644 index 90ee5ad..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_matrix/translate.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Boolean geometry translation. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = 380 - - -def getManipulatedGeometryOutput(geometryOutput, prefix, xmlElement): - """Get equated geometryOutput.""" - translatePoints( matrix.getVertexes(geometryOutput), prefix, xmlElement ) - return geometryOutput - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get equated paths.""" - translatePoints( loop, prefix, xmlElement ) - return [loop] - -def manipulateXMLElement(target, xmlElement): - """Manipulate the xml element.""" - translateTetragrid = matrix.getTranslateTetragrid('', xmlElement) - if translateTetragrid is None: - print('Warning, translateTetragrid was None in translate so nothing will be done for:') - print(xmlElement) - return - matrix.setAttributeDictionaryToMultipliedTetragrid(translateTetragrid, target) - -def processXMLElement(xmlElement): - """Process the xml element.""" - solid.processXMLElementByFunction(manipulateXMLElement, xmlElement) - -def translateNegativesPositives(negatives, positives, translation): - """Translate the negatives and postives.""" - euclidean.translateVector3Path(matrix.getVertexes(negatives), translation) - euclidean.translateVector3Path(matrix.getVertexes(positives), translation) - -def translatePoints(points, prefix, xmlElement): - """Translate the points.""" - translateVector3 = matrix.getCumulativeVector3Remove(Vector3(), prefix, xmlElement) - if abs(translateVector3) > 0.0: - euclidean.translateVector3Path(points, translateVector3) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/__init__.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/__init__.py deleted file mode 100644 index 1121e8a..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/_copy.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/_copy.py deleted file mode 100644 index fce523e..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/_copy.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -Boolean geometry copy. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities import euclidean - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return CopyDerivation(xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - processXMLElementByDerivation(None, xmlElement) - -def processXMLElementByDerivation(derivation, xmlElement): - """Process the xml element by derivation.""" - if derivation is None: - derivation = CopyDerivation(xmlElement) - if derivation.target is None: - print('Warning, copy could not get target for:') - print(xmlElement) - return - del xmlElement.attributeDictionary['target'] - copyMatrix = matrix.getBranchMatrixSetXMLElement(xmlElement) - targetMatrix = matrix.getBranchMatrixSetXMLElement(derivation.target) - targetDictionaryCopy = derivation.target.attributeDictionary.copy() - evaluate.removeIdentifiersFromDictionary(targetDictionaryCopy) - targetDictionaryCopy.update(xmlElement.attributeDictionary) - xmlElement.attributeDictionary = targetDictionaryCopy - euclidean.removeTrueFromDictionary(xmlElement.attributeDictionary, 'visible') - xmlElement.className = derivation.target.className - derivation.target.copyXMLChildren(xmlElement.getIDSuffix(), xmlElement) - xmlElement.getXMLProcessor().processXMLElement(xmlElement) - if copyMatrix is not None and targetMatrix is not None: - xmlElement.xmlObject.matrix4X4 = copyMatrix.getSelfTimesOther(targetMatrix.tetragrid) - - -class CopyDerivation: - """Class to hold copy variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.target = evaluate.getXMLElementByKey('target', xmlElement) - - def __repr__(self): - """Get the string representation of this CopyDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/array.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/array.py deleted file mode 100644 index 4b5bdbf..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/array.py +++ /dev/null @@ -1,134 +0,0 @@ -""" -Boolean geometry array. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_tools import vertex -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addPathToGroup(derivation, groupDictionaryCopy, path, targetMatrix, totalIndex): - """Add path to the array group.""" - for pointIndex, point in enumerate(path): - arrayElement = derivation.target.getCopy(derivation.xmlElement.getIDSuffix(totalIndex), derivation.xmlElement) - arrayDictionary = arrayElement.attributeDictionary - arrayDictionary['visible'] = str(derivation.visible).lower() - arrayDictionary.update(groupDictionaryCopy) - euclidean.removeTrueFromDictionary(arrayDictionary, 'visible') - vertexMatrix = matrix.Matrix(matrix.getTranslateTetragridByTranslation(point)) - zAngle = totalIndex * 50.0 - rotationMatrix = getRotationMatrix(arrayDictionary, derivation, path, point, pointIndex) - arrayElementMatrix = vertexMatrix.getSelfTimesOther(rotationMatrix.getSelfTimesOther(targetMatrix.tetragrid).tetragrid) - arrayDictionary.update(arrayElementMatrix.getAttributeDictionary('matrix.')) - arrayDictionary['_arrayIndex'] = totalIndex - arrayDictionary['_arrayPoint'] = point - totalIndex += 1 - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return ArrayDerivation(xmlElement) - -def getRotationMatrix(arrayDictionary, derivation, path, point, pointIndex): - """Get rotationMatrix.""" - if len(path) < 2 or not derivation.track: - return matrix.Matrix() - point = point.dropAxis() - begin = path[(pointIndex + len(path) - 1) % len(path)].dropAxis() - end = path[(pointIndex + 1) % len(path)].dropAxis() - pointMinusBegin = point - begin - pointMinusBeginLength = abs(pointMinusBegin) - endMinusPoint = end - point - endMinusPointLength = abs(endMinusPoint) - if not derivation.closed: - if pointIndex == 0 and endMinusPointLength > 0.0: - return getRotationMatrixByPolar(arrayDictionary, endMinusPoint, endMinusPointLength) - elif pointIndex == len(path) - 1 and pointMinusBeginLength > 0.0: - return getRotationMatrixByPolar(arrayDictionary, pointMinusBegin, pointMinusBeginLength) - if pointMinusBeginLength <= 0.0: - print('Warning, point equals previous point in getRotationMatrix in array for:') - print(path) - print(pointIndex) - print(xmlElement) - return matrix.Matrix() - pointMinusBegin /= pointMinusBeginLength - if endMinusPointLength <= 0.0: - print('Warning, point equals next point in getRotationMatrix in array for:') - print(path) - print(pointIndex) - print(xmlElement) - return matrix.Matrix() - endMinusPoint /= endMinusPointLength - averagePolar = pointMinusBegin + endMinusPoint - averagePolarLength = abs(averagePolar) - if averagePolarLength <= 0.0: - print('Warning, averagePolarLength is zero in getRotationMatrix in array for:') - print(path) - print(pointIndex) - print(xmlElement) - return matrix.Matrix() - return getRotationMatrixByPolar(arrayDictionary, averagePolar, averagePolarLength) - -def getRotationMatrixByPolar(arrayDictionary, polar, polarLength): - """Get rotationMatrix by polar and polarLength.""" - polar /= polarLength - arrayDictionary['_arrayRotation'] = math.degrees(math.atan2(polar.imag, polar.real)) - return matrix.Matrix(matrix.getDiagonalSwitchedTetragridByPolar([0, 1], polar)) - -def processXMLElement(xmlElement): - """Process the xml element.""" - processXMLElementByDerivation(None, xmlElement) - -def processXMLElementByDerivation(derivation, xmlElement): - """Process the xml element by derivation.""" - if derivation is None: - derivation = ArrayDerivation(xmlElement) - if derivation.target is None: - print('Warning, array could not get target for:') - print(xmlElement) - return - if len(derivation.paths) < 1: - print('Warning, array could not get paths for:') - print(xmlElement) - return - groupDictionaryCopy = xmlElement.attributeDictionary.copy() - euclidean.removeElementsFromDictionary(groupDictionaryCopy, ['closed', 'paths', 'target', 'track', 'vertexes']) - evaluate.removeIdentifiersFromDictionary(groupDictionaryCopy) - targetMatrix = matrix.getBranchMatrixSetXMLElement(derivation.target) - xmlElement.className = 'group' - totalIndex = 0 - for path in derivation.paths: - addPathToGroup(derivation, groupDictionaryCopy, path, targetMatrix, totalIndex) - xmlElement.getXMLProcessor().processXMLElement(xmlElement) - return - - -class ArrayDerivation: - """Class to hold array variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.closed = evaluate.getEvaluatedBoolean(True, 'closed', xmlElement) - self.paths = evaluate.getTransformedPathsByKey([], 'paths', xmlElement) - vertexTargets = evaluate.getXMLElementsByKey('vertexes', xmlElement) - for vertexTarget in vertexTargets: - self.paths.append(vertexTarget.getVertexes()) - self.target = evaluate.getXMLElementByKey('target', xmlElement) - self.track = evaluate.getEvaluatedBoolean(True, 'track', xmlElement) - self.visible = evaluate.getEvaluatedBoolean(True, 'visible', xmlElement) - self.xmlElement = xmlElement - - def __repr__(self): - """Get the string representation of this ArrayDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/disjoin.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/disjoin.py deleted file mode 100644 index a99e82c..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/disjoin.py +++ /dev/null @@ -1,119 +0,0 @@ -""" -Boolean geometry disjoin. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_tools import path -from fabmetheus_utilities.geometry.geometry_utilities.evaluate_elements import setting -from fabmetheus_utilities.geometry.geometry_utilities import boolean_geometry -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.geometry.solids import difference -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import xml_simple_reader -from fabmetheus_utilities.vector3 import Vector3 - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getLinkedXMLElement(idSuffix, parent, target): - """Get xmlElement with identifiers, importName and parent.""" - linkedXMLElement = xml_simple_reader.XMLElement() - linkedXMLElement.importName = parent.importName - euclidean.overwriteDictionary(target.attributeDictionary, ['id', 'name', 'quantity'], linkedXMLElement.attributeDictionary) - linkedXMLElement.addSuffixToID(idSuffix) - tagKeys = target.getTagKeys() - tagKeys.append('disjoin') - tagKeys.sort() - tags = ', '.join(tagKeys) - linkedXMLElement.attributeDictionary['tags'] = tags - linkedXMLElement.setParentAddToChildren(parent) - linkedXMLElement.addToIdentifierDictionaryIFIdentifierExists() - return linkedXMLElement - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return DisjoinDerivation(xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - processXMLElementByDerivation(None, xmlElement) - -def processXMLElementByDerivation(derivation, xmlElement): - """Process the xml element by derivation.""" - if derivation is None: - derivation = DisjoinDerivation(xmlElement) - targetXMLElement = derivation.targetXMLElement - if targetXMLElement is None: - print('Warning, disjoin could not get target for:') - print(xmlElement) - return - xmlObject = targetXMLElement.xmlObject - if xmlObject is None: - print('Warning, processXMLElementByDerivation in disjoin could not get xmlObject for:') - print(targetXMLElement) - print(derivation.xmlElement) - return - transformedVertexes = xmlObject.getTransformedVertexes() - if len(transformedVertexes) < 1: - print('Warning, transformedVertexes is zero in processXMLElementByDerivation in disjoin for:') - print(xmlObject) - print(targetXMLElement) - print(derivation.xmlElement) - return - xmlElement.className = 'group' - xmlElement.getXMLProcessor().processXMLElement(xmlElement) - matrix.getBranchMatrixSetXMLElement(targetXMLElement) - targetChainMatrix = matrix.Matrix(xmlObject.getMatrixChainTetragrid()) - minimumZ = boolean_geometry.getMinimumZ(xmlObject) - z = minimumZ + 0.5 * derivation.sheetThickness - zoneArrangement = triangle_mesh.ZoneArrangement(derivation.layerThickness, transformedVertexes) - oldVisibleString = targetXMLElement.attributeDictionary['visible'] - targetXMLElement.attributeDictionary['visible'] = True - loops = boolean_geometry.getEmptyZLoops([xmlObject], derivation.importRadius, False, z, zoneArrangement) - targetXMLElement.attributeDictionary['visible'] = oldVisibleString - vector3Loops = euclidean.getVector3Paths(loops, z) - pathElement = getLinkedXMLElement('_sheet', xmlElement, targetXMLElement) - path.convertXMLElement(vector3Loops, pathElement) - targetOutput = xmlObject.getGeometryOutput() - differenceElement = getLinkedXMLElement('_solid', xmlElement, targetXMLElement) - targetElementCopy = targetXMLElement.getCopy('_positive', differenceElement) - targetElementCopy.attributeDictionary['visible'] = True - targetElementCopy.attributeDictionary.update(targetChainMatrix.getAttributeDictionary('matrix.')) - complexMaximum = euclidean.getMaximumByVector3Path(transformedVertexes).dropAxis() - complexMinimum = euclidean.getMinimumByVector3Path(transformedVertexes).dropAxis() - centerComplex = 0.5 * (complexMaximum + complexMinimum) - centerVector3 = Vector3(centerComplex.real, centerComplex.imag, minimumZ) - slightlyMoreThanHalfExtent = 0.501 * (complexMaximum - complexMinimum) - inradius = Vector3(slightlyMoreThanHalfExtent.real, slightlyMoreThanHalfExtent.imag, derivation.sheetThickness) - cubeElement = xml_simple_reader.XMLElement() - cubeElement.attributeDictionary['inradius'] = str(inradius) - if not centerVector3.getIsDefault(): - cubeElement.attributeDictionary['translate.'] = str(centerVector3) - cubeElement.className = 'cube' - cubeElement.importName = differenceElement.importName - cubeElement.setParentAddToChildren(differenceElement) - difference.processXMLElement(differenceElement) - - -class DisjoinDerivation: - """Class to hold disjoin variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.importRadius = setting.getImportRadius(xmlElement) - self.layerThickness = setting.getLayerThickness(xmlElement) - self.sheetThickness = setting.getSheetThickness(xmlElement) - self.targetXMLElement = evaluate.getXMLElementByKey('target', xmlElement) - - def __repr__(self): - """Get the string representation of this DisjoinDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/import.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/import.py deleted file mode 100644 index bd5e576..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/import.py +++ /dev/null @@ -1,103 +0,0 @@ -""" -Boolean geometry group of solids. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.solids import group -from fabmetheus_utilities import xml_simple_reader -from fabmetheus_utilities import xml_simple_writer -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -import cStringIO -import os - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return ImportDerivation(xmlElement) - -def getXMLFromCarvingFileName(fileName): - """Get xml text from xml text.""" - carving = fabmetheus_interpret.getCarving(fileName) - if carving is None: - return '' - output = xml_simple_writer.getBeginGeometryXMLOutput() - carving.addXML(0, output) - return xml_simple_writer.getEndGeometryXMLString(output) - -def processXMLElement(xmlElement): - """Process the xml element.""" - processXMLElementByDerivation(None, xmlElement) - -def processXMLElementByDerivation(derivation, xmlElement): - """Process the xml element by derivation.""" - if derivation is None: - derivation = ImportDerivation(xmlElement) - if derivation.fileName is None: - return - parserFileName = xmlElement.getParser().fileName - absoluteFileName = archive.getAbsoluteFolderPath(parserFileName, derivation.fileName) - if 'models/' not in absoluteFileName: - print('Warning, models/ was not in the absolute file path, so for security nothing will be done for:') - print(xmlElement) - print('For which the absolute file path is:') - print(absoluteFileName) - print('The import tool can only read a file which has models/ in the file path.') - print('To import the file, move the file into a folder called model/ or a subfolder which is inside the model folder tree.') - return - xmlText = '' - if derivation.fileName.endswith('.xml'): - xmlText = archive.getFileText(absoluteFileName) - else: - xmlText = getXMLFromCarvingFileName(absoluteFileName) - print('The import tool is opening the file:') - print(absoluteFileName) - if xmlText == '': - print('The file %s could not be found by processXMLElement in import.' % derivation.fileName) - return - if derivation.importName is None: - xmlElement.importName = archive.getUntilDot(derivation.fileName) - if derivation.basename: - xmlElement.importName = os.path.basename(xmlElement.importName) - xmlElement.attributeDictionary['_importName'] = xmlElement.importName - else: - xmlElement.importName = derivation.importName - importXMLElement = xml_simple_reader.XMLElement() - xml_simple_reader.XMLSimpleReader(parserFileName, importXMLElement, xmlText) - for child in importXMLElement.children: - child.copyXMLChildren('', xmlElement) - evaluate.removeIdentifiersFromDictionary(child.attributeDictionary) - xmlElement.attributeDictionary.update(child.attributeDictionary) - if derivation.overwriteRoot: - xmlElement.getRoot().attributeDictionary.update(child.attributeDictionary) - xmlElement.className = 'group' - evaluate.processArchivable(group.Group, xmlElement) - - -class ImportDerivation: - """Class to hold import variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.basename = evaluate.getEvaluatedBoolean(True, 'basename', xmlElement) - self.fileName = evaluate.getEvaluatedString('', 'file', xmlElement) - self.importName = evaluate.getEvaluatedString(None, '_importName', xmlElement) - self.overwriteRoot = evaluate.getEvaluatedBoolean(False, 'overwriteRoot', xmlElement) - self.xmlElement = xmlElement - - def __repr__(self): - """Get the string representation of this ImportDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/write.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/write.py deleted file mode 100644 index 9eca4f2..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_meta/write.py +++ /dev/null @@ -1,102 +0,0 @@ -""" -Boolean geometry write. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -import os - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return WriteDerivation(xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - processXMLElementByDerivation(None, xmlElement) - -def processXMLElementByDerivation(derivation, xmlElement): - """Process the xml element by derivation.""" - if derivation is None: - derivation = WriteDerivation(xmlElement) - if len(derivation.targets) < 1: - print('Warning, processXMLElement in write could not get targets for:') - print(xmlElement) - return - fileNames = [] - for target in derivation.targets: - writeXMLElement(derivation, fileNames, target) - -def writeXMLElement(derivation, fileNames, target): - """Write a quantity of the target.""" - xmlObject = target.xmlObject - if xmlObject is None: - print('Warning, writeTarget in write could not get xmlObject for:') - print(target) - print(derivation.xmlElement) - return - parserDirectory = os.path.dirname(derivation.xmlElement.getRoot().parser.fileName) - absoluteFolderDirectory = os.path.abspath(os.path.join(parserDirectory, derivation.folderName)) - if '/models' not in absoluteFolderDirectory: - print('Warning, models/ was not in the absolute file path, so for security nothing will be done for:') - print(derivation.xmlElement) - print('For which the absolute folder path is:') - print(absoluteFolderDirectory) - print('The write tool can only write a file which has models/ in the file path.') - print('To write the file, move the file into a folder called model/ or a subfolder which is inside the model folder tree.') - return - quantity = evaluate.getEvaluatedInt(1, 'quantity', target) - for itemIndex in xrange(quantity): - writeXMLObject(absoluteFolderDirectory, derivation, fileNames, target, xmlObject) - -def writeXMLObject(absoluteFolderDirectory, derivation, fileNames, target, xmlObject): - """Write one instance of the xmlObject.""" - extension = evaluate.getEvaluatedString(xmlObject.getFabricationExtension(), 'extension', derivation.xmlElement) - fileNameRoot = derivation.fileName - if fileNameRoot == '': - fileNameRoot = evaluate.getEvaluatedString('', 'name', target) - fileNameRoot = evaluate.getEvaluatedString(fileNameRoot, 'id', target) - fileNameRoot += derivation.suffix - fileName = '%s.%s' % (fileNameRoot, extension) - suffixIndex = 2 - while fileName in fileNames: - fileName = '%s_%s.%s' % (fileNameRoot, suffixIndex, extension) - suffixIndex += 1 - absoluteFileName = os.path.join(absoluteFolderDirectory, fileName) - fileNames.append(fileName) - archive.makeDirectory(absoluteFolderDirectory) - if not derivation.writeMatrix: - xmlObject.matrix4X4 = matrix.Matrix() - print('The write tool generated the file:') - print(absoluteFileName) - archive.writeFileText(absoluteFileName, xmlObject.getFabricationText(derivation.addLayerTemplate)) - - -class WriteDerivation: - """Class to hold write variables.""" - def __init__(self, xmlElement): - """Set defaults.""" - self.addLayerTemplate = evaluate.getEvaluatedBoolean(False, 'addLayerTemplate', xmlElement) - self.fileName = evaluate.getEvaluatedString('', 'file', xmlElement) - self.folderName = evaluate.getEvaluatedString('', 'folder', xmlElement) - self.suffix = evaluate.getEvaluatedString('', 'suffix', xmlElement) - self.targets = evaluate.getXMLElementsByKey('target', xmlElement) - self.writeMatrix = evaluate.getEvaluatedBoolean(True, 'writeMatrix', xmlElement) - self.xmlElement = xmlElement - - def __repr__(self): - """Get the string representation of this WriteDerivation.""" - return str(self.__dict__) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/__init__.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/__init__.py deleted file mode 100644 index 1121e8a..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/_inset.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/_inset.py deleted file mode 100644 index 33b5471..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/_inset.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Create inset. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities import intercircle - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = 80 - - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get inset path.""" - radius = lineation.getStrokeRadiusByPrefix(prefix, xmlElement ) - return intercircle.getInsetLoopsFromVector3Loop(loop, radius) - -def processXMLElement(xmlElement): - """Process the xml element.""" - lineation.processXMLElementByFunction(getManipulatedPaths, xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/_outset.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/_outset.py deleted file mode 100644 index 47eedd3..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/_outset.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Create inset. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities import intercircle - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = 80 - - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get outset path.""" - radius = lineation.getStrokeRadiusByPrefix(prefix, xmlElement ) - return intercircle.getInsetLoopsFromVector3Loop(loop, -radius) - -def processXMLElement(xmlElement): - """Process the xml element.""" - lineation.processXMLElementByFunction(getManipulatedPaths, xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/bevel.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/bevel.py deleted file mode 100644 index eb6613d..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/bevel.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -Add material to support overhang or remove material at the overhang angle. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = 20 - - -def getBevelPath( begin, center, close, end, radius ): - """Get bevel path.""" - beginComplex = begin.dropAxis() - centerComplex = center.dropAxis() - endComplex = end.dropAxis() - beginComplexSegmentLength = abs( centerComplex - beginComplex ) - endComplexSegmentLength = abs( centerComplex - endComplex ) - minimumRadius = lineation.getMinimumRadius( beginComplexSegmentLength, endComplexSegmentLength, radius ) - if minimumRadius <= close: - return [ center ] - beginBevel = center + minimumRadius / beginComplexSegmentLength * ( begin - center ) - endBevel = center + minimumRadius / endComplexSegmentLength * ( end - center ) - if radius > 0.0: - return [ beginBevel, endBevel ] - midpointComplex = 0.5 * ( beginBevel.dropAxis() + endBevel.dropAxis() ) - spikeComplex = centerComplex + centerComplex - midpointComplex - return [ beginBevel, Vector3( spikeComplex.real, spikeComplex.imag, center.z ), endBevel ] - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get bevel loop.""" - if len(loop) < 3: - return [loop] - radius = lineation.getRadiusByPrefix( prefix, sideLength, xmlElement ) - if radius == 0.0: - return loop - bevelLoop = [] - for pointIndex in xrange(len(loop)): - begin = loop[(pointIndex + len(loop) - 1) % len(loop)] - center = loop[pointIndex] - end = loop[(pointIndex + 1) % len(loop)] - bevelLoop += getBevelPath( begin, center, close, end, radius ) - return [ euclidean.getLoopWithoutCloseSequentialPoints( close, bevelLoop ) ] - -def processXMLElement(xmlElement): - """Process the xml element.""" - lineation.processXMLElementByFunction(getManipulatedPaths, xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/convex.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/convex.py deleted file mode 100644 index 544aae5..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/convex.py +++ /dev/null @@ -1,32 +0,0 @@ -""" -Create outline. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities import euclidean - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = 80 - - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get path with overhangs removed or filled in.""" - if len(loop) < 4: - return [loop] - loopComplex = euclidean.getComplexPath(loop) - return euclidean.getVector3Paths([euclidean.getLoopConvex(loopComplex)], loop[0].z) - -def processXMLElement(xmlElement): - """Process the xml element.""" - lineation.processXMLElementByFunction(getManipulatedPaths, xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/outline.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/outline.py deleted file mode 100644 index dc41ca4..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/outline.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -Create outline. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import intercircle - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = 80 - - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get path with outline.""" - if len(loop) < 2: - return [loop] - isClosed = evaluate.getEvaluatedBoolean(False, prefix + 'closed', xmlElement) - radius = lineation.getStrokeRadiusByPrefix(prefix, xmlElement ) - loopComplex = euclidean.getComplexPath(loop) - if isClosed: - loopComplexes = intercircle.getAroundsFromLoop(loopComplex, radius) - else: - loopComplexes = intercircle.getAroundsFromPath(loopComplex, radius) - return euclidean.getVector3Paths(loopComplexes, loop[0].z) - -def processXMLElement(xmlElement): - """Process the xml element.""" - lineation.processXMLElementByFunction(getManipulatedPaths, xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/overhang.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/overhang.py deleted file mode 100644 index 52be92f..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/overhang.py +++ /dev/null @@ -1,386 +0,0 @@ -""" -Add material to support overhang or remove material at the overhang angle. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_utilities.evaluate_elements import setting -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = 100 - - -def addUnsupportedPointIndexes( alongAway ): - """Add the indexes of the unsupported points.""" - addedUnsupportedPointIndexes = [] - for pointIndex in xrange( len( alongAway.loop ) ): - point = alongAway.loop[pointIndex] - if pointIndex not in alongAway.unsupportedPointIndexes: - if not alongAway.getIsClockwisePointSupported(point): - alongAway.unsupportedPointIndexes.append( pointIndex ) - addedUnsupportedPointIndexes.append( pointIndex ) - for pointIndex in addedUnsupportedPointIndexes: - point = alongAway.loop[pointIndex] - point.y += alongAway.maximumYPlus - -def alterClockwiseSupportedPath( alongAway, xmlElement ): - """Get clockwise path with overhangs carved out.""" - alongAway.bottomPoints = [] - alongAway.overhangSpan = setting.getOverhangSpan(xmlElement) - maximumY = - 987654321.0 - minimumYPointIndex = 0 - for pointIndex in xrange( len( alongAway.loop ) ): - point = alongAway.loop[pointIndex] - if point.y < alongAway.loop[ minimumYPointIndex ].y: - minimumYPointIndex = pointIndex - maximumY = max( maximumY, point.y ) - alongAway.maximumYPlus = 2.0 * ( maximumY - alongAway.loop[ minimumYPointIndex ].y ) - alongAway.loop = euclidean.getAroundLoop( minimumYPointIndex, minimumYPointIndex, alongAway.loop ) - overhangClockwise = OverhangClockwise( alongAway ) - alongAway.unsupportedPointIndexes = [] - oldUnsupportedPointIndexesLength = - 987654321.0 - while len( alongAway.unsupportedPointIndexes ) > oldUnsupportedPointIndexesLength: - oldUnsupportedPointIndexesLength = len( alongAway.unsupportedPointIndexes ) - addUnsupportedPointIndexes( alongAway ) - for pointIndex in alongAway.unsupportedPointIndexes: - point = alongAway.loop[pointIndex] - point.y -= alongAway.maximumYPlus - alongAway.unsupportedPointIndexes.sort() - alongAway.unsupportedPointIndexLists = [] - oldUnsupportedPointIndex = - 987654321.0 - unsupportedPointIndexList = None - for unsupportedPointIndex in alongAway.unsupportedPointIndexes: - if unsupportedPointIndex > oldUnsupportedPointIndex + 1: - unsupportedPointIndexList = [] - alongAway.unsupportedPointIndexLists.append( unsupportedPointIndexList ) - oldUnsupportedPointIndex = unsupportedPointIndex - unsupportedPointIndexList.append( unsupportedPointIndex ) - alongAway.unsupportedPointIndexLists.reverse() - for unsupportedPointIndexList in alongAway.unsupportedPointIndexLists: - overhangClockwise.alterLoop( unsupportedPointIndexList ) - -def alterWiddershinsSupportedPath( alongAway, close ): - """Get widdershins path with overhangs filled in.""" - alongAway.bottomPoints = [] - alongAway.minimumY = getMinimumYByPath( alongAway.loop ) - for point in alongAway.loop: - if point.y - alongAway.minimumY < close: - alongAway.addToBottomPoints(point) - ascendingYPoints = alongAway.loop[:] - ascendingYPoints.sort( compareYAscending ) - overhangWiddershinsLeft = OverhangWiddershinsLeft( alongAway ) - overhangWiddershinsRight = OverhangWiddershinsRight( alongAway ) - for point in ascendingYPoints: - alterWiddershinsSupportedPathByPoint( alongAway, overhangWiddershinsLeft, overhangWiddershinsRight, point ) - -def alterWiddershinsSupportedPathByPoint( alongAway, overhangWiddershinsLeft, overhangWiddershinsRight, point ): - """Get widdershins path with overhangs filled in for point.""" - if alongAway.getIsWiddershinsPointSupported(point): - return - overhangWiddershins = overhangWiddershinsLeft - if overhangWiddershinsRight.getDistance() < overhangWiddershinsLeft.getDistance(): - overhangWiddershins = overhangWiddershinsRight - overhangWiddershins.alterLoop() - -def compareYAscending( point, pointOther ): - """Get comparison in order to sort points in ascending y.""" - if point.y < pointOther.y: - return - 1 - return int( point.y > pointOther.y ) - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get path with overhangs removed or filled in.""" - if len(loop) < 3: - print('Warning, loop has less than three sides in getManipulatedPaths in overhang for:') - print(xmlElement) - return [loop] - overhangRadians = setting.getOverhangRadians(xmlElement) - overhangPlaneAngle = euclidean.getWiddershinsUnitPolar(0.5 * math.pi - overhangRadians) - overhangVerticalRadians = math.radians(evaluate.getEvaluatedFloat(0.0, prefix + 'inclination', xmlElement)) - if overhangVerticalRadians != 0.0: - overhangVerticalCosine = abs(math.cos(overhangVerticalRadians)) - if overhangVerticalCosine == 0.0: - return [loop] - imaginaryTimesCosine = overhangPlaneAngle.imag * overhangVerticalCosine - overhangPlaneAngle = euclidean.getNormalized(complex(overhangPlaneAngle.real, imaginaryTimesCosine)) - alongAway = AlongAway(loop, overhangPlaneAngle) - if euclidean.getIsWiddershinsByVector3(loop): - alterWiddershinsSupportedPath(alongAway, close) - else: - alterClockwiseSupportedPath(alongAway, xmlElement) - return [euclidean.getLoopWithoutCloseSequentialPoints(close, alongAway.loop)] - -def getMinimumYByPath(path): - """Get path with overhangs removed or filled in.""" - minimumYByPath = path[0].y - for point in path: - minimumYByPath = min( minimumYByPath, point.y ) - return minimumYByPath - -def processXMLElement(xmlElement): - """Process the xml element.""" - lineation.processXMLElementByFunction(getManipulatedPaths, xmlElement) - - -class AlongAway: - """Class to derive the path along the point and away from the point.""" - def __init__( self, loop, overhangPlaneAngle ): - """Initialize.""" - self.loop = loop - self.overhangPlaneAngle = overhangPlaneAngle - self.ySupport = - self.overhangPlaneAngle.imag - - def __repr__(self): - """Get the string representation of AlongAway.""" - return '%s' % self.overhangPlaneAngle - - def addToBottomPoints(self, point): - """Add point to bottom points and set y to minimumY.""" - self.bottomPoints.append(point) - point.y = self.minimumY - - def getIsClockwisePointSupported(self, point): - """Determine if the point on the clockwise loop is supported.""" - self.point = point - self.pointIndex = None - self.awayIndexes = [] - numberOfIntersectionsBelow = 0 - for pointIndex in xrange( len( self.loop ) ): - begin = self.loop[pointIndex] - end = self.loop[ (pointIndex + 1) % len( self.loop ) ] - if begin != point and end != point: - self.awayIndexes.append( pointIndex ) - yIntersection = euclidean.getYIntersectionIfExists( begin.dropAxis(), end.dropAxis(), point.x ) - if yIntersection is not None: - numberOfIntersectionsBelow += ( yIntersection < point.y ) - if begin == point: - self.pointIndex = pointIndex - if numberOfIntersectionsBelow % 2 == 0: - return True - if self.pointIndex is None: - return True - if self.getIsPointSupportedBySegment( self.pointIndex - 1 + len( self.loop ) ): - return True - return self.getIsPointSupportedBySegment( self.pointIndex + 1 ) - - def getIsWiddershinsPointSupported(self, point): - """Determine if the point on the widdershins loop is supported.""" - if point.y <= self.minimumY: - return True - self.point = point - self.pointIndex = None - self.awayIndexes = [] - numberOfIntersectionsBelow = 0 - for pointIndex in xrange( len( self.loop ) ): - begin = self.loop[pointIndex] - end = self.loop[ (pointIndex + 1) % len( self.loop ) ] - if begin != point and end != point: - self.awayIndexes.append( pointIndex ) - yIntersection = euclidean.getYIntersectionIfExists( begin.dropAxis(), end.dropAxis(), point.x ) - if yIntersection is not None: - numberOfIntersectionsBelow += ( yIntersection < point.y ) - if begin == point: - self.pointIndex = pointIndex - if numberOfIntersectionsBelow % 2 == 1: - return True - if self.pointIndex is None: - return True - if self.getIsPointSupportedBySegment( self.pointIndex - 1 + len( self.loop ) ): - return True - return self.getIsPointSupportedBySegment( self.pointIndex + 1 ) - - def getIsPointSupportedBySegment( self, endIndex ): - """Determine if the point on the widdershins loop is supported.""" - endComplex = self.loop[ ( endIndex % len( self.loop ) ) ].dropAxis() - endMinusPointComplex = euclidean.getNormalized( endComplex - self.point.dropAxis() ) - return endMinusPointComplex.imag < self.ySupport - - -class OverhangClockwise: - """Class to get the intersection up from the point.""" - def __init__( self, alongAway ): - """Initialize.""" - self.alongAway = alongAway - self.halfRiseOverWidth = 0.5 * alongAway.overhangPlaneAngle.imag / alongAway.overhangPlaneAngle.real - self.widthOverRise = alongAway.overhangPlaneAngle.real / alongAway.overhangPlaneAngle.imag - - def __repr__(self): - """Get the string representation of OverhangClockwise.""" - return '%s' % self.intersectionPlaneAngle - - def alterLoop( self, unsupportedPointIndexes ): - """Alter alongAway loop.""" - unsupportedBeginIndex = unsupportedPointIndexes[0] - unsupportedEndIndex = unsupportedPointIndexes[-1] - beginIndex = unsupportedBeginIndex - 1 - endIndex = unsupportedEndIndex + 1 - begin = self.alongAway.loop[ beginIndex ] - end = self.alongAway.loop[ endIndex ] - truncatedOverhangSpan = self.alongAway.overhangSpan - width = end.x - begin.x - heightDifference = abs( end.y - begin.y ) - remainingWidth = width - self.widthOverRise * heightDifference - if remainingWidth <= 0.0: - del self.alongAway.loop[ unsupportedBeginIndex : endIndex ] - return - highest = begin - supportX = begin.x + remainingWidth - if end.y > begin.y: - highest = end - supportX = end.x - remainingWidth - tipY = highest.y + self.halfRiseOverWidth * remainingWidth - highestBetween = - 987654321.0 - for unsupportedPointIndex in unsupportedPointIndexes: - highestBetween = max( highestBetween, self.alongAway.loop[ unsupportedPointIndex ].y ) - if highestBetween > highest.y: - truncatedOverhangSpan = 0.0 - if highestBetween < tipY: - below = tipY - highestBetween - truncatedOverhangSpan = min( self.alongAway.overhangSpan, below / self.halfRiseOverWidth ) - truncatedOverhangSpanRadius = 0.5 * truncatedOverhangSpan - if remainingWidth <= truncatedOverhangSpan: - supportPoint = Vector3( supportX, highest.y, highest.z ) - self.alongAway.loop[ unsupportedBeginIndex : endIndex ] = [ supportPoint ] - return - midSupportX = 0.5 * ( supportX + highest.x ) - if truncatedOverhangSpan <= 0.0: - supportPoint = Vector3( midSupportX, tipY, highest.z ) - self.alongAway.loop[ unsupportedBeginIndex : endIndex ] = [ supportPoint ] - return - supportXLeft = midSupportX - truncatedOverhangSpanRadius - supportXRight = midSupportX + truncatedOverhangSpanRadius - supportY = tipY - self.halfRiseOverWidth * truncatedOverhangSpan - supportPoints = [ Vector3( supportXLeft, supportY, highest.z ), Vector3( supportXRight, supportY, highest.z ) ] - self.alongAway.loop[ unsupportedBeginIndex : endIndex ] = supportPoints - - -class OverhangWiddershinsLeft: - """Class to get the intersection from the point down to the left.""" - def __init__( self, alongAway ): - """Initialize.""" - self.alongAway = alongAway - self.intersectionPlaneAngle = - alongAway.overhangPlaneAngle - self.setRatios() - - def __repr__(self): - """Get the string representation of OverhangWiddershins.""" - return '%s' % self.intersectionPlaneAngle - - def alterLoop(self): - """Alter alongAway loop.""" - insertedPoint = self.alongAway.point.copy() - if self.closestXIntersectionIndex is not None: - self.alongAway.loop = self.getIntersectLoop() - intersectionRelativeComplex = self.closestXDistance * self.intersectionPlaneAngle - intersectionPoint = insertedPoint + Vector3( intersectionRelativeComplex.real, intersectionRelativeComplex.imag ) - self.alongAway.loop.append( intersectionPoint ) - return - if self.closestBottomPoint is None: - return - if self.closestBottomPoint not in self.alongAway.loop: - return - insertedPoint.x = self.bottomX - closestBottomIndex = self.alongAway.loop.index( self.closestBottomPoint ) - self.alongAway.addToBottomPoints( insertedPoint ) - self.alongAway.loop = self.getBottomLoop( closestBottomIndex, insertedPoint ) - self.alongAway.loop.append( insertedPoint ) - - def getBottomLoop( self, closestBottomIndex, insertedPoint ): - """Get loop around bottom.""" - endIndex = closestBottomIndex + len( self.alongAway.loop ) + 1 - return euclidean.getAroundLoop( self.alongAway.pointIndex, endIndex, self.alongAway.loop ) - - def getDistance(self): - """Get distance between point and nearest intersection or bottom point along line.""" - self.pointMinusBottomY = self.alongAway.point.y - self.alongAway.minimumY - self.diagonalDistance = self.pointMinusBottomY * self.diagonalRatio - if self.alongAway.pointIndex is None: - return self.getDistanceToBottom() - rotatedLoop = euclidean.getPointsRoundZAxis( self.intersectionYMirror, euclidean.getComplexPath( self.alongAway.loop ) ) - rotatedPointComplex = rotatedLoop[ self.alongAway.pointIndex ] - beginX = rotatedPointComplex.real - endX = beginX + self.diagonalDistance + self.diagonalDistance - xIntersectionIndexList = [] - for pointIndex in self.alongAway.awayIndexes: - beginComplex = rotatedLoop[pointIndex] - endComplex = rotatedLoop[ (pointIndex + 1) % len( rotatedLoop ) ] - xIntersection = euclidean.getXIntersectionIfExists( beginComplex, endComplex, rotatedPointComplex.imag ) - if xIntersection is not None: - if xIntersection >= beginX and xIntersection < endX: - xIntersectionIndexList.append( euclidean.XIntersectionIndex( pointIndex, xIntersection ) ) - self.closestXDistance = 987654321.0 - self.closestXIntersectionIndex = None - for xIntersectionIndex in xIntersectionIndexList: - xDistance = abs( xIntersectionIndex.x - beginX ) - if xDistance < self.closestXDistance: - self.closestXIntersectionIndex = xIntersectionIndex - self.closestXDistance = xDistance - if self.closestXIntersectionIndex is not None: - return self.closestXDistance - return self.getDistanceToBottom() - - def getDistanceToBottom(self): - """Get distance between point and nearest bottom point along line.""" - self.bottomX = self.alongAway.point.x + self.pointMinusBottomY * self.xRatio - self.closestBottomPoint = None - closestDistanceX = 987654321.0 - for point in self.alongAway.bottomPoints: - distanceX = abs( point.x - self.bottomX ) - if self.getIsOnside(point.x): - if distanceX < closestDistanceX: - closestDistanceX = distanceX - self.closestBottomPoint = point - return closestDistanceX + self.diagonalDistance - - def getIntersectLoop(self): - """Get intersection loop.""" - endIndex = self.closestXIntersectionIndex.index + len( self.alongAway.loop ) + 1 - return euclidean.getAroundLoop( self.alongAway.pointIndex, endIndex, self.alongAway.loop ) - - def getIsOnside( self, x ): - """Determine if x is on the side along the direction of the intersection line.""" - return x <= self.alongAway.point.x - - def setRatios(self): - """Set ratios.""" - self.diagonalRatio = 1.0 / abs( self.intersectionPlaneAngle.imag ) - self.intersectionYMirror = complex( self.intersectionPlaneAngle.real, - self.intersectionPlaneAngle.imag ) - self.xRatio = self.intersectionPlaneAngle.real / abs( self.intersectionPlaneAngle.imag ) - - -class OverhangWiddershinsRight( OverhangWiddershinsLeft ): - """Class to get the intersection from the point down to the right.""" - def __init__( self, alongAway ): - """Initialize.""" - self.alongAway = alongAway - self.intersectionPlaneAngle = complex( alongAway.overhangPlaneAngle.real, - alongAway.overhangPlaneAngle.imag ) - self.setRatios() - - def getBottomLoop( self, closestBottomIndex, insertedPoint ): - """Get loop around bottom.""" - endIndex = self.alongAway.pointIndex + len( self.alongAway.loop ) + 1 - return euclidean.getAroundLoop( closestBottomIndex, endIndex, self.alongAway.loop ) - - def getIntersectLoop(self): - """Get intersection loop.""" - beginIndex = self.closestXIntersectionIndex.index + len( self.alongAway.loop ) + 1 - endIndex = self.alongAway.pointIndex + len( self.alongAway.loop ) + 1 - return euclidean.getAroundLoop( beginIndex, endIndex, self.alongAway.loop ) - - def getIsOnside( self, x ): - """Determine if x is on the side along the direction of the intersection line.""" - return x >= self.alongAway.point.x diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/round.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/round.py deleted file mode 100644 index 8bc49f5..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/round.py +++ /dev/null @@ -1,83 +0,0 @@ -""" -Add material to support overhang or remove material at the overhang angle. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = 40 - - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get round loop.""" - if len(loop) < 3: - return [loop] - radius = lineation.getRadiusByPrefix(prefix, sideLength, xmlElement) - if radius == 0.0: - return loop - roundLoop = [] - sidesPerRadian = 0.5 / math.pi * evaluate.getSidesMinimumThreeBasedOnPrecision(sideLength, xmlElement) - for pointIndex in xrange(len(loop)): - begin = loop[(pointIndex + len(loop) - 1) % len(loop)] - center = loop[pointIndex] - end = loop[(pointIndex + 1) % len(loop)] - roundLoop += getRoundPath(begin, center, close, end, radius, sidesPerRadian) - return [euclidean.getLoopWithoutCloseSequentialPoints(close, roundLoop)] - -def getRoundPath( begin, center, close, end, radius, sidesPerRadian ): - """Get round path.""" - beginComplex = begin.dropAxis() - centerComplex = center.dropAxis() - endComplex = end.dropAxis() - beginComplexSegmentLength = abs( centerComplex - beginComplex ) - endComplexSegmentLength = abs( centerComplex - endComplex ) - minimumRadius = lineation.getMinimumRadius( beginComplexSegmentLength, endComplexSegmentLength, radius ) - if minimumRadius <= close: - return [ center ] - beginBevel = center + minimumRadius / beginComplexSegmentLength * ( begin - center ) - endBevel = center + minimumRadius / endComplexSegmentLength * ( end - center ) - beginBevelComplex = beginBevel.dropAxis() - endBevelComplex = endBevel.dropAxis() - midpointComplex = 0.5 * ( beginBevelComplex + endBevelComplex ) - if radius < 0.0: - centerComplex = midpointComplex + midpointComplex - centerComplex - midpointMinusCenterComplex = midpointComplex - centerComplex - midpointCenterLength = abs( midpointMinusCenterComplex ) - midpointEndLength = abs( midpointComplex - endBevelComplex ) - midpointCircleCenterLength = midpointEndLength * midpointEndLength / midpointCenterLength - circleRadius = math.sqrt( midpointCircleCenterLength * midpointCircleCenterLength + midpointEndLength * midpointEndLength ) - circleCenterComplex = midpointComplex + midpointMinusCenterComplex * midpointCircleCenterLength / midpointCenterLength - circleCenter = Vector3( circleCenterComplex.real, circleCenterComplex.imag, center.z ) - endMinusCircleCenterComplex = endBevelComplex - circleCenterComplex - beginMinusCircleCenter = beginBevel - circleCenter - beginMinusCircleCenterComplex = beginMinusCircleCenter.dropAxis() - angleDifference = euclidean.getAngleDifferenceByComplex( endMinusCircleCenterComplex, beginMinusCircleCenterComplex ) - steps = int( math.ceil( abs( angleDifference ) * sidesPerRadian ) ) - stepPlaneAngle = euclidean.getWiddershinsUnitPolar( angleDifference / float( steps ) ) - deltaZStep = ( end.z - begin.z ) / float( steps ) - roundPath = [ beginBevel ] - for step in xrange( 1, steps ): - beginMinusCircleCenterComplex = beginMinusCircleCenterComplex * stepPlaneAngle - arcPointComplex = circleCenterComplex + beginMinusCircleCenterComplex - arcPoint = Vector3( arcPointComplex.real, arcPointComplex.imag, begin.z + deltaZStep * step ) - roundPath.append( arcPoint ) - return roundPath + [ endBevel ] - -def processXMLElement(xmlElement): - """Process the xml element.""" - lineation.processXMLElementByFunction(getManipulatedPaths, xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/segment.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/segment.py deleted file mode 100644 index c7552f0..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/segment.py +++ /dev/null @@ -1,155 +0,0 @@ -""" -Add material to support overhang or remove material at the overhang angle. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = 60 - - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get segment loop.""" - if len(loop) < 3: - return [loop] - path = evaluate.getPathByPrefix(getSegmentPathDefault(), prefix, xmlElement) - if path == getSegmentPathDefault(): - return [loop] - path = getXNormalizedVector3Path(path) - segmentCenter = evaluate.getVector3ByPrefix(None, prefix + 'center', xmlElement) - if euclidean.getIsWiddershinsByVector3(loop): - path = path[: : -1] - for point in path: - point.x = 1.0 - point.x - if segmentCenter is None: - point.y = - point.y - segmentLoop = [] - startEnd = StartEnd(len(loop), prefix, xmlElement) - for pointIndex in xrange(len(loop)): - if pointIndex >= startEnd.start and pointIndex < startEnd.end: - segmentLoop += getSegmentPath(loop, path, pointIndex, segmentCenter) - else: - segmentLoop.append(loop[pointIndex]) - return [euclidean.getLoopWithoutCloseSequentialPoints( close, segmentLoop)] - -def getRadialPath( begin, end, path, segmentCenter ): - """Get radial path.""" - beginComplex = begin.dropAxis() - endComplex = end.dropAxis() - segmentCenterComplex = segmentCenter.dropAxis() - beginMinusCenterComplex = beginComplex - segmentCenterComplex - endMinusCenterComplex = endComplex - segmentCenterComplex - beginMinusCenterComplexRadius = abs( beginMinusCenterComplex ) - endMinusCenterComplexRadius = abs( endMinusCenterComplex ) - if beginMinusCenterComplexRadius == 0.0 or endMinusCenterComplexRadius == 0.0: - return [ begin ] - beginMinusCenterComplex /= beginMinusCenterComplexRadius - endMinusCenterComplex /= endMinusCenterComplexRadius - angleDifference = euclidean.getAngleDifferenceByComplex( endMinusCenterComplex, beginMinusCenterComplex ) - radialPath = [] - for point in path: - weightEnd = point.x - weightBegin = 1.0 - weightEnd - weightedRadius = beginMinusCenterComplexRadius * weightBegin + endMinusCenterComplexRadius * weightEnd * ( 1.0 + point.y ) - radialComplex = weightedRadius * euclidean.getWiddershinsUnitPolar( angleDifference * point.x ) * beginMinusCenterComplex - polygonPoint = segmentCenter + Vector3( radialComplex.real, radialComplex.imag, point.z ) - radialPath.append( polygonPoint ) - return radialPath - -def getSegmentPath( loop, path, pointIndex, segmentCenter ): - """Get segment path.""" - centerBegin = loop[pointIndex] - centerEnd = loop[(pointIndex + 1) % len(loop)] - centerEndMinusBegin = centerEnd - centerBegin - if abs( centerEndMinusBegin ) <= 0.0: - return [ centerBegin ] - if segmentCenter is not None: - return getRadialPath( centerBegin, centerEnd, path, segmentCenter ) - begin = loop[(pointIndex + len(loop) - 1) % len(loop)] - end = loop[ ( pointIndex + 2 ) % len(loop) ] - return getWedgePath( begin, centerBegin, centerEnd, centerEndMinusBegin, end, path ) - -def getSegmentPathDefault(): - """Get segment path default.""" - return [ Vector3(), Vector3( 0.0, 1.0 ) ] - -def getXNormalizedVector3Path(path): - """Get path where the x ranges from 0 to 1.""" - if len(path) < 1: - return path - minimumX = path[0].x - for point in path[1 :]: - minimumX = min( minimumX, point.x ) - for point in path: - point.x -= minimumX - maximumX = path[0].x - for point in path[1 :]: - maximumX = max( maximumX, point.x ) - for point in path: - point.x /= maximumX - return path - -def getWedgePath( begin, centerBegin, centerEnd, centerEndMinusBegin, end, path ): - """Get segment path.""" - beginComplex = begin.dropAxis() - centerBeginComplex = centerBegin.dropAxis() - centerEndComplex = centerEnd.dropAxis() - endComplex = end.dropAxis() - wedgePath = [] - centerBeginMinusBeginComplex = euclidean.getNormalized( centerBeginComplex - beginComplex ) - centerEndMinusCenterBeginComplexOriginal = centerEndComplex - centerBeginComplex - centerEndMinusCenterBeginComplexLength = abs( centerEndMinusCenterBeginComplexOriginal ) - if centerEndMinusCenterBeginComplexLength <= 0.0: - return [ centerBegin ] - centerEndMinusCenterBeginComplex = centerEndMinusCenterBeginComplexOriginal / centerEndMinusCenterBeginComplexLength - endMinusCenterEndComplex = euclidean.getNormalized( endComplex - centerEndComplex ) - widdershinsBegin = getWiddershinsAverageByVector3( centerBeginMinusBeginComplex, centerEndMinusCenterBeginComplex ) - widdershinsEnd = getWiddershinsAverageByVector3( centerEndMinusCenterBeginComplex, endMinusCenterEndComplex ) - for point in path: - weightEnd = point.x - weightBegin = 1.0 - weightEnd - polygonPoint = centerBegin + centerEndMinusBegin * point.x - weightedWiddershins = widdershinsBegin * weightBegin + widdershinsEnd * weightEnd - polygonPoint += weightedWiddershins * point.y * centerEndMinusCenterBeginComplexLength - polygonPoint.z += point.z - wedgePath.append( polygonPoint ) - return wedgePath - -def getWiddershinsAverageByVector3( centerMinusBeginComplex, endMinusCenterComplex ): - """Get the normalized average of the widdershins vectors.""" - centerMinusBeginWiddershins = Vector3( - centerMinusBeginComplex.imag, centerMinusBeginComplex.real ) - endMinusCenterWiddershins = Vector3( - endMinusCenterComplex.imag, endMinusCenterComplex.real ) - return ( centerMinusBeginWiddershins + endMinusCenterWiddershins ).getNormalized() - -def processXMLElement(xmlElement): - """Process the xml element.""" - lineation.processXMLElementByFunction(getManipulatedPaths, xmlElement) - - -class StartEnd: - """Class to get a start through end range.""" - def __init__(self, modulo, prefix, xmlElement): - """Initialize.""" - self.start = evaluate.getEvaluatedInt(0, prefix + 'start', xmlElement) - self.extent = evaluate.getEvaluatedInt(modulo - self.start, prefix + 'extent', xmlElement) - self.end = evaluate.getEvaluatedInt(self.start + self.extent, prefix + 'end', xmlElement) - self.revolutions = evaluate.getEvaluatedInt(1, prefix + 'revolutions', xmlElement) - if self.revolutions > 1: - self.end += modulo * (self.revolutions - 1) - - def __repr__(self): - """Get the string representation of this StartEnd.""" - return '%s, %s, %s' % (self.start, self.end, self.revolutions) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/wedge.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/wedge.py deleted file mode 100644 index d5c772a..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_paths/wedge.py +++ /dev/null @@ -1,32 +0,0 @@ -""" -Add material to support overhang or remove material at the overhang angle. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import lineation -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.vector3 import Vector3 - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = -200 - - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get wedge loop.""" - wedgeCenter = evaluate.getVector3ByPrefix(Vector3(), prefix + 'center', xmlElement) - loop.append(wedgeCenter) - return [loop] - -def processXMLElement(xmlElement): - """Process the xml element.""" - lineation.processXMLElementByFunction(getManipulatedPaths, xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_shapes/__init__.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_shapes/__init__.py deleted file mode 100644 index 1121e8a..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_shapes/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_shapes/_bottom.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_shapes/_bottom.py deleted file mode 100644 index 96f5852..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_shapes/_bottom.py +++ /dev/null @@ -1,108 +0,0 @@ -""" -Boolean geometry bottom. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.geometry_utilities.evaluate_elements import setting -from fabmetheus_utilities.geometry.geometry_utilities import boolean_geometry -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities import euclidean - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = 400 - - -def bottomXMLElement(derivation, target): - """Bottom target.""" - xmlObject = target.xmlObject - if xmlObject is None: - print('Warning, bottomTarget in bottom could not get xmlObject for:') - print(target) - print(derivation.xmlElement) - return - targetMatrix = matrix.getBranchMatrixSetXMLElement(target) - lift = derivation.altitude - transformedPaths = xmlObject.getTransformedPaths() - if len(transformedPaths) > 0: - lift += derivation.getAdditionalPathLift() - euclidean.getBottomByPaths(transformedPaths) - else: - lift -= boolean_geometry.getMinimumZ(xmlObject) - targetMatrix.tetragrid = matrix.getIdentityTetragrid(targetMatrix.tetragrid) - targetMatrix.tetragrid[2][3] += lift - matrix.setXMLElementDictionaryMatrix(targetMatrix, target) - -def getManipulatedGeometryOutput(geometryOutput, prefix, xmlElement): - """Get bottomed geometryOutput.""" - derivation = BottomDerivation(prefix, xmlElement) - copyShallow = xmlElement.getCopyShallow() - solid.processXMLElementByGeometry(geometryOutput, copyShallow) - targetMatrix = matrix.getBranchMatrixSetXMLElement(xmlElement) - matrix.setXMLElementDictionaryMatrix(targetMatrix, copyShallow) - minimumZ = boolean_geometry.getMinimumZ(copyShallow.xmlObject) - copyShallow.parent.xmlObject.archivableObjects.remove(copyShallow.xmlObject) - lift = derivation.altitude - minimumZ - vertexes = matrix.getVertexes(geometryOutput) - for vertex in vertexes: - vertex.z += lift - return geometryOutput - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get flipped paths.""" - if len(loop) < 1: - return [[]] - derivation = BottomDerivation(prefix, xmlElement) - targetMatrix = matrix.getBranchMatrixSetXMLElement(xmlElement) - transformedLoop = matrix.getTransformedVector3s(matrix.getIdentityTetragrid(targetMatrix.tetragrid), loop) - lift = derivation.altitude + derivation.getAdditionalPathLift() - euclidean.getBottomByPath(transformedLoop) - for point in loop: - point.z += lift - return [loop] - -def getNewDerivation(xmlElement): - """Get new derivation.""" - return BottomDerivation('', xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - processXMLElementByDerivation(None, xmlElement) - -def processXMLElementByDerivation(derivation, xmlElement): - """Process the xml element by derivation.""" - if derivation is None: - derivation = BottomDerivation('', xmlElement) - targets = evaluate.getXMLElementsByKey('target', xmlElement) - if len(targets) < 1: - print('Warning, processXMLElement in bottom could not get targets for:') - print(xmlElement) - return - for target in targets: - bottomXMLElement(derivation, target) - - -class BottomDerivation: - """Class to hold bottom variables.""" - def __init__(self, prefix, xmlElement): - """Set defaults.""" - self.altitude = evaluate.getEvaluatedFloat(0.0, prefix + 'altitude', xmlElement) - self.liftPath = evaluate.getEvaluatedBoolean(True, prefix + 'liftPath', xmlElement) - self.xmlElement = xmlElement - - def __repr__(self): - """Get the string representation of this BottomDerivation.""" - return str(self.__dict__) - - def getAdditionalPathLift(self): - """Get path lift.""" - return 0.5 * setting.getLayerThickness(self.xmlElement) * float(self.liftPath) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_shapes/equation.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_shapes/equation.py deleted file mode 100644 index 372f68c..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_shapes/equation.py +++ /dev/null @@ -1,105 +0,0 @@ -""" -Equation for vertexes. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = -100 - - -def equate(point, returnValue): - """Get equation for rectangular.""" - point.setToVector3(evaluate.getVector3ByDictionaryListValue(returnValue, point)) - -def equatePoints(points, prefix, revolutions, xmlElement): - """Equate the points.""" - equateVertexesByFunction(equate, points, prefix, revolutions, xmlElement) - equateVertexesByFunction(equateX, points, prefix, revolutions, xmlElement) - equateVertexesByFunction(equateY, points, prefix, revolutions, xmlElement) - equateVertexesByFunction(equateZ, points, prefix, revolutions, xmlElement) - -def equateX(point, returnValue): - """Get equation for rectangular x.""" - point.x = returnValue - -def equateY(point, returnValue): - """Get equation for rectangular y.""" - point.y = returnValue - -def equateZ(point, returnValue): - """Get equation for rectangular z.""" - point.z = returnValue - -def equateVertexesByFunction( equationFunction, points, prefix, revolutions, xmlElement ): - """Get equated points by equation function.""" - prefixedEquationName = prefix + equationFunction.__name__[ len('equate') : ].replace('Dot', '.').lower() - if prefixedEquationName not in xmlElement.attributeDictionary: - return - equationResult = EquationResult( prefixedEquationName, revolutions, xmlElement ) - for point in points: - returnValue = equationResult.getReturnValue(point) - if returnValue is None: - print('Warning, returnValue in alterVertexesByEquation in equation is None for:') - print(point) - print(xmlElement) - else: - equationFunction(point, returnValue) -# equationResult.function.reset() #removeLater - -def getManipulatedGeometryOutput(geometryOutput, prefix, xmlElement): - """Get equated geometryOutput.""" - equatePoints( matrix.getVertexes(geometryOutput), prefix, None, xmlElement ) - return geometryOutput - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get equated paths.""" - equatePoints( loop, prefix, 0.0, xmlElement ) - return [loop] - - -class EquationResult: - """Class to get equation results.""" - def __init__(self, key, revolutions, xmlElement): - """Initialize.""" - self.distance = 0.0 - xmlElement.xmlObject = evaluate.getEvaluatorSplitWords(xmlElement.attributeDictionary[key]) - self.function = evaluate.Function(xmlElement) - self.points = [] - self.revolutions = revolutions - - def getReturnValue(self, point): - """Get return value.""" - if self.function is None: - return point - self.function.localDictionary['azimuth'] = math.degrees(math.atan2(point.y, point.x)) - if len(self.points) > 0: - self.distance += abs(point - self.points[-1]) - self.function.localDictionary['distance'] = self.distance - self.function.localDictionary['radius'] = abs(point.dropAxis()) - if self.revolutions is not None: - if len( self.points ) > 0: - self.revolutions += 0.5 / math.pi * euclidean.getAngleAroundZAxisDifference(point, self.points[-1]) - self.function.localDictionary['revolutions'] = self.revolutions - self.function.localDictionary['vertex'] = point - self.function.localDictionary['vertexes'] = self.points - self.function.localDictionary['vertexindex'] = len(self.points) - self.function.localDictionary['x'] = point.x - self.function.localDictionary['y'] = point.y - self.function.localDictionary['z'] = point.z - self.points.append(point) - return self.function.getReturnValueWithoutDeletion() diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_shapes/flip.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_shapes/flip.py deleted file mode 100644 index 60c0c0b..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_shapes/flip.py +++ /dev/null @@ -1,81 +0,0 @@ -""" -Add material to support overhang or remove material at the overhang angle. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.vector3 import Vector3 - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = 200 - - -# http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=269576 -# http://www.opengl.org/resources/code/samples/sig99/advanced99/notes/node159.html -# m.a00 = -2 * norm.x * norm.x + 1; -# m.a10 = -2 * norm.y * norm.x; -# m.a20 = -2 * norm.z * norm.x; -# m.a30 = 0; - -# m.a01 = -2 * norm.x * norm.y; -# m.a11 = -2 * norm.y * norm.y + 1; -# m.a21 = -2 * norm.z * norm.y; -# m.a31 = 0; - -# m.a02 = -2 * norm.x * norm.z; -# m.a12 = -2 * norm.y * norm.z; -# m.a22 = -2 * norm.z * norm.z + 1; -# m.a32 = 0; - -# m.a03 = -2 * norm.x * d; -# m.a13 = -2 * norm.y * d; -# m.a23 = -2 * norm.z * d; -# m.a33 = 1; - -# normal = unit_vector(normal[:3]) -# M = numpy.identity(4) -# M[:3, :3] -= 2.0 * numpy.outer(normal, normal) -# M[:3, 3] = (2.0 * numpy.dot(point[:3], normal)) * normal -# return M -def flipPoints(points, prefix, xmlElement): - """Flip the points.""" - origin = evaluate.getVector3ByPrefix(Vector3(), prefix + 'origin', xmlElement) - axis = evaluate.getVector3ByPrefix(Vector3(1.0, 0.0, 0.0), prefix + 'axis', xmlElement).getNormalized() - for point in points: - point.setToVector3(point - 2.0 * axis.dot(point - origin) * axis) - -def getFlippedLoop(loop, prefix, xmlElement): - """Get flipped loop.""" - flipPoints(loop, prefix, xmlElement) - if getShouldReverse(prefix, xmlElement): - loop.reverse() - return loop - -def getManipulatedGeometryOutput(geometryOutput, prefix, xmlElement): - """Get equated geometryOutput.""" - flipPoints(matrix.getVertexes(geometryOutput), prefix, xmlElement) - return geometryOutput - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get flipped paths.""" - return [getFlippedLoop(loop, prefix, xmlElement)] - -def getShouldReverse(prefix, xmlElement): - """Determine if the loop should be reversed.""" - return evaluate.getEvaluatedBoolean(True, prefix + 'reverse', xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - solid.processXMLElementByFunctions(getManipulatedGeometryOutput, getManipulatedPaths, xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/manipulation_shapes/mirror.py b/skeinforge/fabmetheus_utilities/geometry/manipulation_shapes/mirror.py deleted file mode 100644 index d134266..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/manipulation_shapes/mirror.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Add material to support overhang or remove material at the overhang angle. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.geometry_tools import face -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.geometry.manipulation_shapes import flip -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalExecutionOrder = 200 - - -def getManipulatedGeometryOutput(geometryOutput, prefix, xmlElement): - """Get equated geometryOutput.""" - flippedGeometryOutput = triangle_mesh.getGeometryOutputCopy(geometryOutput) - flip.flipPoints(matrix.getVertexes(flippedGeometryOutput), prefix, xmlElement) - if flip.getShouldReverse(prefix, xmlElement): - flippedFaces = face.getFaces(flippedGeometryOutput) - for flippedFace in flippedFaces: - flippedFace.vertexIndexes.reverse() - return {'union' : {'shapes' : [flippedGeometryOutput, geometryOutput]}} - -def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): - """Get flipped paths.""" - return [loop + flip.getFlippedLoop(euclidean.getPathCopy(loop), prefix, xmlElement)] - - -def processXMLElement(xmlElement): - """Process the xml element.""" - solid.processXMLElementByFunctions(getManipulatedGeometryOutput, getManipulatedPaths, xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/solids/__init__.py b/skeinforge/fabmetheus_utilities/geometry/solids/__init__.py deleted file mode 100644 index cefa3e7..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/solids/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -This page is in the table of contents. -This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -""" -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry/solids/cube.py b/skeinforge/fabmetheus_utilities/geometry/solids/cube.py deleted file mode 100644 index aea2042..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/solids/cube.py +++ /dev/null @@ -1,68 +0,0 @@ -""" -Boolean geometry cube. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addCube(faces, inradius, vertexes, xmlElement): - """Add cube by inradius.""" - square = [ - complex(-inradius.x, -inradius.y), - complex(inradius.x, -inradius.y), - complex(inradius.x, inradius.y), - complex(-inradius.x, inradius.y)] - bottomTopSquare = triangle_mesh.getAddIndexedLoops(square, vertexes, [-inradius.z, inradius.z]) - triangle_mesh.addPillarByLoops(faces, bottomTopSquare) - -def getGeometryOutput(inradius, xmlElement): - """Get cube triangle mesh by inradius.""" - faces = [] - vertexes = [] - addCube(faces, inradius, vertexes, xmlElement) - return {'trianglemesh' : {'vertex' : vertexes, 'face' : faces}} - -def processXMLElement(xmlElement): - """Process the xml element.""" - evaluate.processArchivable(Cube, xmlElement) - - -class Cube(triangle_mesh.TriangleMesh): - """A cube object.""" - def addXMLSection(self, depth, output): - """Add the xml section for this object.""" - pass - - def createShape(self): - """Create the shape.""" - addCube(self.faces, self.inradius, self.vertexes, self.xmlElement) - - def setToXMLElement(self, xmlElement): - """Set to xmlElement.""" - attributeDictionary = xmlElement.attributeDictionary - self.inradius = evaluate.getVector3ByPrefixes(['demisize', 'inradius'], Vector3(1.0, 1.0, 1.0), xmlElement) - self.inradius = evaluate.getVector3ByMultiplierPrefix(2.0, 'size', self.inradius, xmlElement) - self.xmlElement = xmlElement - attributeDictionary['inradius.x'] = self.inradius.x - attributeDictionary['inradius.y'] = self.inradius.y - attributeDictionary['inradius.z'] = self.inradius.z - if 'inradius' in attributeDictionary: - del attributeDictionary['inradius'] - self.createShape() - self.liftByMinimumZ(-self.inradius.z) - solid.processArchiveRemoveSolid(self.getGeometryOutput(), xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/solids/cylinder.py b/skeinforge/fabmetheus_utilities/geometry/solids/cylinder.py deleted file mode 100644 index ed8b4b1..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/solids/cylinder.py +++ /dev/null @@ -1,90 +0,0 @@ -""" -Boolean geometry cylinder. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.geometry.solids import cube -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addCylinder(faces, inradius, sides, topOverBottom, vertexes): - """Add cylinder by inradius.""" - polygonBottom = euclidean.getComplexPolygonByComplexRadius(complex(inradius.x, inradius.y), sides) - polygonTop = polygonBottom - if topOverBottom <= 0.0: - polygonTop = [complex()] - elif topOverBottom != 1.0: - polygonTop = euclidean.getComplexPathByMultiplier(topOverBottom, polygonTop) - bottomTopPolygon = [ - triangle_mesh.getAddIndexedLoop(polygonBottom, vertexes, -inradius.z), - triangle_mesh.getAddIndexedLoop(polygonTop, vertexes, inradius.z)] - triangle_mesh.addPillarByLoops(faces, bottomTopPolygon) - -def addCylinderOutputByEndStart(endZ, inradiusComplex, outputs, sides, start, topOverBottom=1.0): - """Add cylinder triangle mesh by endZ, inradius and start.""" - inradius = Vector3(inradiusComplex.real, inradiusComplex.imag, 0.5 * abs(endZ - start.z)) - cylinderOutput = getGeometryOutput(inradius, sides, topOverBottom) - vertexes = matrix.getVertexes(cylinderOutput) - if endZ < start.z: - for vertex in vertexes: - vertex.z = -vertex.z - translation = Vector3(start.x, start.y, inradius.z + min(start.z, endZ)) - euclidean.translateVector3Path(vertexes, translation) - outputs.append(cylinderOutput) - -def getGeometryOutput(inradius, sides, topOverBottom): - """Get cylinder triangle mesh by inradius.""" - faces = [] - vertexes = [] - addCylinder(faces, inradius, sides, topOverBottom, vertexes) - return {'trianglemesh' : {'vertex' : vertexes, 'face' : faces}} - -def processXMLElement(xmlElement): - """Process the xml element.""" - evaluate.processArchivable(Cylinder, xmlElement) - - -class Cylinder( cube.Cube ): - """A cylinder object.""" - def __init__(self): - """Add empty lists.""" - cube.Cube.__init__(self) - - def createShape(self): - """Create the shape.""" - sides = evaluate.getSidesMinimumThreeBasedOnPrecision(max(self.inradius.x, self.inradius.y), self.xmlElement ) - addCylinder(self.faces, self.inradius, sides, self.topOverBottom, self.vertexes, self.xmlElement) - - def setToXMLElement(self, xmlElement): - """Set to xmlElement.""" - attributeDictionary = xmlElement.attributeDictionary - self.inradius = evaluate.getVector3ByPrefixes(['demisize', 'inradius', 'radius'], Vector3(1.0, 1.0, 1.0), xmlElement) - self.inradius = evaluate.getVector3ByMultiplierPrefixes(2.0, ['diameter', 'size'], self.inradius, xmlElement) - self.inradius.z = 0.5 * evaluate.getEvaluatedFloat(self.inradius.z + self.inradius.z, 'height', xmlElement) - self.topOverBottom = evaluate.getEvaluatedFloat(1.0, 'topOverBottom', xmlElement ) - self.xmlElement = xmlElement - if 'inradius' in attributeDictionary: - del attributeDictionary['inradius'] - attributeDictionary['height'] = self.inradius.z + self.inradius.z - attributeDictionary['radius.x'] = self.inradius.x - attributeDictionary['radius.y'] = self.inradius.y - attributeDictionary['topOverBottom'] = self.topOverBottom - self.createShape() - self.liftByMinimumZ(-self.inradius.z) - solid.processArchiveRemoveSolid(self.getGeometryOutput(), xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/solids/difference.py b/skeinforge/fabmetheus_utilities/geometry/solids/difference.py deleted file mode 100644 index 35bf550..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/solids/difference.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -Boolean geometry difference of solids. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import boolean_solid -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.solids import group - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def convertXMLElement(geometryOutput, xmlElement): - """Convert the xml element to a difference xml element.""" - group.convertContainerXMLElement(geometryOutput, xmlElement, Difference()) - -def processXMLElement(xmlElement): - """Process the xml element.""" - evaluate.processArchivable(Difference, xmlElement) - - -class Difference( boolean_solid.BooleanSolid ): - """A difference object.""" - def getLoopsFromObjectLoopsList(self, importRadius, visibleObjectLoopsList): - """Get loops from visible object loops list.""" - return self.getDifference(importRadius, visibleObjectLoopsList) - - def getXMLClassName(self): - """Get xml class name.""" - return self.__class__.__name__.lower() diff --git a/skeinforge/fabmetheus_utilities/geometry/solids/group.py b/skeinforge/fabmetheus_utilities/geometry/solids/group.py deleted file mode 100644 index dc2de38..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/solids/group.py +++ /dev/null @@ -1,78 +0,0 @@ -""" -Boolean geometry group of solids. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_tools import dictionary -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities import euclidean - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def convertXMLElement(geometryOutput, xmlElement): - """Convert the xml element to a group xml element.""" - convertContainerXMLElement(geometryOutput, xmlElement, Group()) - -def convertContainerXMLElement(geometryOutput, xmlElement, xmlObject): - """Convert the xml element to a group xml element.""" - xmlElement.linkObject(xmlObject) - matrix.getBranchMatrixSetXMLElement(xmlElement) - xmlElement.getXMLProcessor().createChildren(geometryOutput['shapes'], xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - evaluate.processArchivable(Group, xmlElement) - - -class Group(dictionary.Dictionary): - """A group.""" - def __init__(self): - """Add empty lists.""" - dictionary.Dictionary.__init__(self) - self.matrix4X4 = matrix.Matrix() - - def addXMLInnerSection(self, depth, output): - """Add xml inner section for this object.""" - if self.matrix4X4 is not None: - self.matrix4X4.addXML(depth, output) - self.addXMLSection(depth, output) - - def addXMLSection(self, depth, output): - """Add the xml section for this object.""" - pass - - def getLoops(self, importRadius, z): - """Get loops sliced through shape.""" - visibleObjects = evaluate.getVisibleObjects(self.archivableObjects) - loops = [] - for visibleObject in visibleObjects: - loops += visibleObject.getLoops(importRadius, z) - return loops - - def getMatrix4X4(self): - """Get the matrix4X4.""" - return self.matrix4X4 - - def getMatrixChainTetragrid(self): - """Get the matrix chain tetragrid.""" - return matrix.getTetragridTimesOther(self.xmlElement.parent.xmlObject.getMatrixChainTetragrid(), self.matrix4X4.tetragrid) - - def getVisible(self): - """Get visible.""" - return euclidean.getBooleanFromDictionary(True, self.getAttributeDictionary(), 'visible') - - def setToXMLElement(self, xmlElement): - """Set to xmlElement.""" - self.xmlElement = xmlElement - xmlElement.parent.xmlObject.archivableObjects.append(self) - matrix.getBranchMatrixSetXMLElement(xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/solids/intersection.py b/skeinforge/fabmetheus_utilities/geometry/solids/intersection.py deleted file mode 100644 index 45f95c4..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/solids/intersection.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Boolean geometry intersection of solids. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.solids import difference -from fabmetheus_utilities.geometry.solids import group - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def convertXMLElement(geometryOutput, xmlElement): - """Convert the xml element to an intersection xml element.""" - group.convertContainerXMLElement(geometryOutput, xmlElement, Intersection()) - -def processXMLElement(xmlElement): - """Process the xml element.""" - evaluate.processArchivable(Intersection, xmlElement) - - -class Intersection(difference.Difference): - """An intersection object.""" - def getLoopsFromObjectLoopsList(self, importRadius, visibleObjectLoopsList): - """Get loops from visible object loops list.""" - return self.getIntersection(importRadius, visibleObjectLoopsList) diff --git a/skeinforge/fabmetheus_utilities/geometry/solids/sphere.py b/skeinforge/fabmetheus_utilities/geometry/solids/sphere.py deleted file mode 100644 index 7b6732e..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/solids/sphere.py +++ /dev/null @@ -1,73 +0,0 @@ -""" -Boolean geometry sphere. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.creation import solid -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.solids import cube -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addSphere(faces, radius, vertexes, xmlElement): - """Add sphere by radius.""" - bottom = -radius.z - sides = evaluate.getSidesMinimumThreeBasedOnPrecision(max(radius.x, radius.y, radius.z), xmlElement ) - sphereSlices = max(sides / 2, 2) - equator = euclidean.getComplexPolygonByComplexRadius(complex(radius.x, radius.y), sides) - polygons = [triangle_mesh.getAddIndexedLoop([complex()], vertexes, bottom)] - zIncrement = (radius.z + radius.z) / float(sphereSlices) - z = bottom - for sphereSlice in xrange(1, sphereSlices): - z += zIncrement - zPortion = abs(z) / radius.z - multipliedPath = euclidean.getComplexPathByMultiplier(math.sqrt(1.0 - zPortion * zPortion), equator) - polygons.append(triangle_mesh.getAddIndexedLoop(multipliedPath, vertexes, z)) - polygons.append(triangle_mesh.getAddIndexedLoop([complex()], vertexes, radius.z)) - triangle_mesh.addPillarByLoops(faces, polygons) - -def getGeometryOutput(radius, xmlElement): - """Get triangle mesh from attribute dictionary.""" - faces = [] - vertexes = [] - addSphere(faces, radius, vertexes, xmlElement) - return {'trianglemesh' : {'vertex' : vertexes, 'face' : faces}} - -def processXMLElement(xmlElement): - """Process the xml element.""" - evaluate.processArchivable(Sphere, xmlElement) - - -class Sphere(cube.Cube): - """A sphere object.""" - def createShape(self): - """Create the shape.""" - addSphere(self.faces, self.radius, self.vertexes, self.xmlElement) - - def setToXMLElement(self, xmlElement): - """Set to xmlElement.""" - attributeDictionary = xmlElement.attributeDictionary - self.radius = evaluate.getVector3ByPrefixes( ['demisize', 'radius'], Vector3(1.0, 1.0, 1.0), xmlElement ) - self.radius = evaluate.getVector3ByMultiplierPrefixes( 2.0, ['diameter', 'size'], self.radius, xmlElement ) - self.xmlElement = xmlElement - if 'radius' in attributeDictionary: - del attributeDictionary['radius'] - attributeDictionary['radius.x'] = self.radius.x - attributeDictionary['radius.y'] = self.radius.y - attributeDictionary['radius.z'] = self.radius.z - self.createShape() - self.liftByMinimumZ(-self.radius.z) - solid.processArchiveRemoveSolid(self.getGeometryOutput(), xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/solids/triangle_mesh.py b/skeinforge/fabmetheus_utilities/geometry/solids/triangle_mesh.py deleted file mode 100644 index d680eff..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/solids/triangle_mesh.py +++ /dev/null @@ -1,911 +0,0 @@ -""" -Triangle Mesh holds the faces and edges of a triangular mesh. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_tools import face -from fabmetheus_utilities.geometry.geometry_tools import dictionary -from fabmetheus_utilities.geometry.geometry_tools import vertex -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities.geometry.solids import group -from fabmetheus_utilities import xml_simple_writer -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities.vector3index import Vector3Index -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -import cmath -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addEdgePair( edgePairTable, edges, faceEdgeIndex, remainingEdgeIndex, remainingEdgeTable ): - """Add edge pair to the edge pair table.""" - if faceEdgeIndex == remainingEdgeIndex: - return - if not faceEdgeIndex in remainingEdgeTable: - return - edgePair = EdgePair().getFromIndexesEdges( [ remainingEdgeIndex, faceEdgeIndex ], edges ) - edgePairTable[ str( edgePair ) ] = edgePair - -def addFacesByConcaveLoop(faces, indexedLoop): - """Add faces from a polygon which is concave.""" - if len(indexedLoop) < 3: - return - remainingLoop = indexedLoop[:] - while len(remainingLoop) > 2: - remainingLoop = getRemainingLoopAddFace(faces, remainingLoop) - -def addFacesByConvex(faces, indexedLoop): - """Add faces from a convex polygon.""" - if len(indexedLoop) < 3: - return - indexBegin = indexedLoop[0].index - for indexedPointIndex in xrange(1, len(indexedLoop) - 1): - indexCenter = indexedLoop[indexedPointIndex].index - indexEnd = indexedLoop[(indexedPointIndex + 1) % len(indexedLoop) ].index - if indexBegin != indexCenter and indexCenter != indexEnd and indexEnd != indexBegin: - faceFromConvex = face.Face() - faceFromConvex.index = len(faces) - faceFromConvex.vertexIndexes.append(indexBegin) - faceFromConvex.vertexIndexes.append(indexCenter) - faceFromConvex.vertexIndexes.append(indexEnd) - faces.append(faceFromConvex) - -def addFacesByConvexBottomTopLoop(faces, indexedLoopBottom, indexedLoopTop): - """Add faces from loops.""" - for indexedLoopIndex in xrange(max(len(indexedLoopBottom), len(indexedLoopTop))): - indexedLoopIndexEnd = (indexedLoopIndex + 1) % len(indexedLoopBottom) - indexedConvex = [] - if len(indexedLoopBottom) > 1: - indexedConvex.append(indexedLoopBottom[indexedLoopIndex]) - indexedConvex.append(indexedLoopBottom[(indexedLoopIndex + 1) % len(indexedLoopBottom)]) - else: - indexedConvex.append(indexedLoopBottom[0]) - if len(indexedLoopTop) > 1: - indexedConvex.append(indexedLoopTop[(indexedLoopIndex + 1) % len(indexedLoopTop)]) - indexedConvex.append(indexedLoopTop[indexedLoopIndex]) - else: - indexedConvex.append(indexedLoopTop[0]) - addFacesByConvex(faces, indexedConvex) - -def addFacesByConvexLoops(faces, indexedLoops): - """Add faces from loops.""" - if len(indexedLoops) < 2: - return - for indexedLoopsIndex in xrange(len(indexedLoops) - 2): - addFacesByConvexBottomTopLoop(faces, indexedLoops[indexedLoopsIndex], indexedLoops[indexedLoopsIndex + 1]) - indexedLoopBottom = indexedLoops[-2] - indexedLoopTop = indexedLoops[-1] - if len(indexedLoopTop) < 1: - indexedLoopTop = indexedLoops[0] - addFacesByConvexBottomTopLoop(faces, indexedLoopBottom, indexedLoopTop) - -def addFacesByConvexReversed(faces, indexedLoop): - """Add faces from a reversed convex polygon.""" - addFacesByConvex(faces, indexedLoop[: : -1]) - -def addFacesByGrid(faces, grid): - """Add faces from grid.""" - cellTopLoops = getIndexedCellLoopsFromIndexedGrid(grid) - for cellTopLoop in cellTopLoops: - addFacesByConvex(faces, cellTopLoop) - -def addFacesByLoop(faces, indexedLoop): - """Add faces from a polygon which may be concave.""" - if len(indexedLoop) < 3: - return - lastNormal = None - for pointIndex, point in enumerate(indexedLoop): - center = indexedLoop[(pointIndex + 1) % len(indexedLoop)] - end = indexedLoop[(pointIndex + 2) % len(indexedLoop)] - normal = euclidean.getNormalWeighted(point, center, end) - if abs(normal) > 0.0: - if lastNormal is not None: - if lastNormal.dot(normal) < 0.0: - addFacesByConcaveLoop(faces, indexedLoop) - return - lastNormal = normal -# totalNormal = Vector3() -# for pointIndex, point in enumerate(indexedLoop): -# center = indexedLoop[(pointIndex + 1) % len(indexedLoop)] -# end = indexedLoop[(pointIndex + 2) % len(indexedLoop)] -# totalNormal += euclidean.getNormalWeighted(point, center, end) -# totalNormal.normalize() - addFacesByConvex(faces, indexedLoop) - -def addFacesByLoopReversed(faces, indexedLoop): - """Add faces from a reversed convex polygon.""" - addFacesByLoop(faces, indexedLoop[: : -1]) - -def addLoopToPointTable(loop, pointTable): - """Add the points in the loop to the point table.""" - for point in loop: - pointTable[point] = None - -def addPillarByLoops(faces, indexedLoops): - """Add pillar by loops which may be concave.""" - if len(indexedLoops) < 1: - return - if len(indexedLoops[-1]) < 1: - addFacesByConvexLoops(faces, indexedLoops) - return - addFacesByLoopReversed(faces, indexedLoops[0]) - addFacesByConvexLoops(faces, indexedLoops) - addFacesByLoop(faces, indexedLoops[-1]) - -def addPillarFromConvexLoopsGrids(faces, indexedGrids, indexedLoops): - """Add pillar from convex loops and grids.""" - cellBottomLoops = getIndexedCellLoopsFromIndexedGrid(indexedGrids[0]) - for cellBottomLoop in cellBottomLoops: - addFacesByConvexReversed(faces, cellBottomLoop) - addFacesByConvexLoops(faces, indexedLoops) - addFacesByGrid(faces, indexedGrids[-1]) - -def addPillarFromConvexLoopsGridTop(faces, indexedGridTop, indexedLoops): - """Add pillar from convex loops and grid top.""" - addFacesByLoopReversed(faces, indexedLoops[0]) - addFacesByConvexLoops(faces, indexedLoops) - addFacesByGrid(faces, indexedGridTop) - -def addPointsAtZ(edgePair, points, radius, vertexes, z): - """Add point complexes on the segment between the edge intersections with z.""" - carveIntersectionFirst = getCarveIntersectionFromEdge(edgePair.edges[0], vertexes, z) - carveIntersectionSecond = getCarveIntersectionFromEdge(edgePair.edges[1], vertexes, z) - # threshold radius above 0.8 can create extra holes on Screw Holder, 0.7 should be safe for everything - intercircle.addPointsFromSegment(carveIntersectionFirst, carveIntersectionSecond, points, radius, 0.7) - -def addSymmetricXPath(outputs, path, x): - """Add x path output to outputs.""" - vertexes = [] - loops = [getSymmetricXLoop(path, vertexes, -x), getSymmetricXLoop(path, vertexes, x)] - outputs.append(getPillarOutput(loops)) - -def addSymmetricXPaths(outputs, paths, x): - """Add x paths outputs to outputs.""" - for path in paths: - addSymmetricXPath(outputs, path, x) - -def addSymmetricYPath(outputs, path, y): - """Add y path output to outputs.""" - vertexes = [] - loops = [getSymmetricYLoop(path, vertexes, -y), getSymmetricYLoop(path, vertexes, y)] - outputs.append(getPillarOutput(loops)) - -def addSymmetricYPaths(outputs, paths, y): - """Add y paths outputs to outputs.""" - for path in paths: - addSymmetricYPath(outputs, path, y) - -def addWithLeastLength(importRadius, loops, point): - """Insert a point into a loop, at the index at which the loop would be shortest.""" - close = importRadius + importRadius - shortestAdditionalLength = close - shortestLoop = None - shortestPointIndex = None - for loop in loops: - if len(loop) > 3: - for pointIndex in xrange(len(loop)): - additionalLoopLength = getAdditionalLoopLength(loop, point, pointIndex) - if additionalLoopLength < shortestAdditionalLength: - if getIsPointCloseInline(close, loop, point, pointIndex): - shortestAdditionalLength = additionalLoopLength - shortestLoop = loop - shortestPointIndex = pointIndex - if shortestPointIndex is not None: - shortestLoop.insert( shortestPointIndex, point ) - -def convertXMLElement(geometryOutput, xmlElement): - """Convert the xml element to a TriangleMesh xml element.""" - xmlElement.linkObject(TriangleMesh()) - matrix.getBranchMatrixSetXMLElement(xmlElement) - vertex.addGeometryList(geometryOutput['vertex'], xmlElement) - face.addGeometryList(geometryOutput['face'], xmlElement) - xmlElement.getXMLProcessor().processChildren(xmlElement) - -def getAddIndexedGrid( grid, vertexes, z ): - """Get and add an indexed grid.""" - indexedGrid = [] - for row in grid: - indexedRow = [] - indexedGrid.append( indexedRow ) - for pointComplex in row: - vector3index = Vector3Index( len(vertexes), pointComplex.real, pointComplex.imag, z ) - indexedRow.append(vector3index) - vertexes.append(vector3index) - return indexedGrid - -def getAddIndexedLoop(loop, vertexes, z): - """Get and add an indexed loop.""" - indexedLoop = [] - for index in xrange(len(loop)): - pointComplex = loop[index] - vector3index = Vector3Index(len(vertexes), pointComplex.real, pointComplex.imag, z) - indexedLoop.append(vector3index) - vertexes.append(vector3index) - return indexedLoop - -def getAddIndexedLoops( loop, vertexes, zList ): - """Get and add indexed loops.""" - indexedLoops = [] - for z in zList: - indexedLoop = getAddIndexedLoop( loop, vertexes, z ) - indexedLoops.append(indexedLoop) - return indexedLoops - -def getAdditionalLoopLength(loop, point, pointIndex): - """Get the additional length added by inserting a point into a loop.""" - afterPoint = loop[pointIndex] - beforePoint = loop[(pointIndex + len(loop) - 1) % len(loop)] - return abs(point - beforePoint) + abs(point - afterPoint) - abs(afterPoint - beforePoint) - -def getBridgeDirection( belowLoops, layerLoops, layerThickness ): - """Get span direction for the majority of the overhanging extrusion perimeter, if any.""" - if len( belowLoops ) < 1: - return None - belowOutsetLoops = [] - overhangInset = 1.875 * layerThickness - slightlyGreaterThanOverhang = 1.1 * overhangInset - for loop in belowLoops: - centers = intercircle.getCentersFromLoopDirection( True, loop, slightlyGreaterThanOverhang ) - for center in centers: - outset = intercircle.getSimplifiedInsetFromClockwiseLoop( center, overhangInset ) - if intercircle.isLargeSameDirection( outset, center, overhangInset ): - belowOutsetLoops.append( outset ) - bridgeRotation = complex() - for loop in layerLoops: - for pointIndex in xrange(len(loop)): - previousIndex = ( pointIndex + len(loop) - 1 ) % len(loop) - bridgeRotation += getOverhangDirection( belowOutsetLoops, loop[ previousIndex ], loop[pointIndex] ) - if abs( bridgeRotation ) < 0.75 * layerThickness: - return None - else: - bridgeRotation /= abs( bridgeRotation ) - return cmath.sqrt( bridgeRotation ) - -def getBridgeLoops( layerThickness, loop ): - """Get the inset bridge loops from the loop.""" - halfWidth = 1.5 * layerThickness - slightlyGreaterThanHalfWidth = 1.1 * halfWidth - extrudateLoops = [] - centers = intercircle.getCentersFromLoop( loop, slightlyGreaterThanHalfWidth ) - for center in centers: - extrudateLoop = intercircle.getSimplifiedInsetFromClockwiseLoop( center, halfWidth ) - if intercircle.isLargeSameDirection( extrudateLoop, center, halfWidth ): - if euclidean.isPathInsideLoop( loop, extrudateLoop ) == euclidean.isWiddershins(loop): - extrudateLoop.reverse() - extrudateLoops.append( extrudateLoop ) - return extrudateLoops - -def getCarveIntersectionFromEdge(edge, vertexes, z): - """Get the complex where the carve intersects the edge.""" - firstVertex = vertexes[ edge.vertexIndexes[0] ] - firstVertexComplex = firstVertex.dropAxis() - secondVertex = vertexes[ edge.vertexIndexes[1] ] - secondVertexComplex = secondVertex.dropAxis() - zMinusFirst = z - firstVertex.z - up = secondVertex.z - firstVertex.z - return zMinusFirst * ( secondVertexComplex - firstVertexComplex ) / up + firstVertexComplex - -def getDescendingAreaLoops(allPoints, corners, importRadius): - """Get descending area loops which include most of the points.""" - loops = intercircle.getCentersFromPoints(allPoints, importRadius) - descendingAreaLoops = [] - sortLoopsInOrderOfArea(True, loops) - pointDictionary = {} - for loop in loops: - if len(loop) > 2 and getOverlapRatio(loop, pointDictionary) < 0.2: - intercircle.directLoop(not euclidean.getIsInFilledRegion(descendingAreaLoops, loop[0]), loop) - descendingAreaLoops.append(loop) - addLoopToPointTable(loop, pointDictionary) - descendingAreaLoops = euclidean.getSimplifiedLoops(descendingAreaLoops, importRadius) - return getLoopsWithCorners(corners, importRadius, descendingAreaLoops, pointDictionary) - -def getDescendingAreaOrientedLoops(allPoints, corners, importRadius): - """Get descending area oriented loops which include most of the points.""" - return getOrientedLoops(getDescendingAreaLoops(allPoints, corners, importRadius)) - -def getDoubledRoundZ( overhangingSegment, segmentRoundZ ): - """Get doubled plane angle around z of the overhanging segment.""" - endpoint = overhangingSegment[0] - roundZ = endpoint.point - endpoint.otherEndpoint.point - roundZ *= segmentRoundZ - if abs( roundZ ) == 0.0: - return complex() - if roundZ.real < 0.0: - roundZ *= - 1.0 - roundZLength = abs( roundZ ) - return roundZ * roundZ / roundZLength - -def getGeometryOutputByFacesVertexes(faces, vertexes): - """Get geometry output dictionary by faces and vertexes.""" - return {'trianglemesh' : {'vertex' : vertexes, 'face' : faces}} - -def getGeometryOutputCopy(object): - """Get the geometry output copy.""" - objectClass = object.__class__ - if objectClass == dict: - objectCopy = {} - for key in object: - objectCopy[key] = getGeometryOutputCopy(object[key]) - return objectCopy - if objectClass == list: - objectCopy = [] - for value in object: - objectCopy.append(getGeometryOutputCopy(value)) - return objectCopy - if objectClass == face.Face or objectClass == Vector3 or objectClass == Vector3Index: - return object.copy() - return object - -def getIndexedCellLoopsFromIndexedGrid( grid ): - """Get indexed cell loops from an indexed grid.""" - indexedCellLoops = [] - for rowIndex in xrange( len( grid ) - 1 ): - rowBottom = grid[ rowIndex ] - rowTop = grid[ rowIndex + 1 ] - for columnIndex in xrange( len( rowBottom ) - 1 ): - columnIndexEnd = columnIndex + 1 - indexedConvex = [] - indexedConvex.append( rowBottom[ columnIndex ] ) - indexedConvex.append( rowBottom[ columnIndex + 1 ] ) - indexedConvex.append( rowTop[ columnIndex + 1 ] ) - indexedConvex.append( rowTop[ columnIndex ] ) - indexedCellLoops.append( indexedConvex ) - return indexedCellLoops - -def getIndexedLoopFromIndexedGrid( indexedGrid ): - """Get indexed loop from around the indexed grid.""" - indexedLoop = indexedGrid[0][:] - for row in indexedGrid[1 : -1]: - indexedLoop.append( row[-1] ) - indexedLoop += indexedGrid[-1][: : -1] - for row in indexedGrid[ len( indexedGrid ) - 2 : 0 : - 1 ]: - indexedLoop.append( row[0] ) - return indexedLoop - -def getInsetPoint( loop, tinyRadius ): - """Get the inset vertex.""" - pointIndex = getWideAnglePointIndex(loop) - point = loop[ pointIndex % len(loop) ] - afterPoint = loop[(pointIndex + 1) % len(loop)] - beforePoint = loop[ ( pointIndex - 1 ) % len(loop) ] - afterSegmentNormalized = euclidean.getNormalized( afterPoint - point ) - beforeSegmentNormalized = euclidean.getNormalized( beforePoint - point ) - afterClockwise = complex( afterSegmentNormalized.imag, - afterSegmentNormalized.real ) - beforeWiddershins = complex( - beforeSegmentNormalized.imag, beforeSegmentNormalized.real ) - midpoint = afterClockwise + beforeWiddershins - midpointNormalized = midpoint / abs( midpoint ) - return point + midpointNormalized * tinyRadius - -def getIsPointCloseInline(close, loop, point, pointIndex): - """Insert a point into a loop, at the index at which the loop would be shortest.""" - afterCenterComplex = loop[pointIndex] - if abs(afterCenterComplex - point) > close: - return False - afterEndComplex = loop[(pointIndex + 1) % len(loop)] - if not isInline( point, afterCenterComplex, afterEndComplex ): - return False - beforeCenterComplex = loop[(pointIndex + len(loop) - 1) % len(loop)] - if abs(beforeCenterComplex - point) > close: - return False - beforeEndComplex = loop[(pointIndex + len(loop) - 2) % len(loop)] - return isInline(point, beforeCenterComplex, beforeEndComplex) - -def getIsPathEntirelyOutsideTriangle(begin, center, end, vector3Path): - """Determine if a path is entirely outside another loop.""" - loop = [begin.dropAxis(), center.dropAxis(), end.dropAxis()] - for vector3 in vector3Path: - point = vector3.dropAxis() - if euclidean.isPointInsideLoop(loop, point): - return False - return True - -def getLoopsFromCorrectMesh( edges, faces, vertexes, z ): - """Get loops from a carve of a correct mesh.""" - remainingEdgeTable = getRemainingEdgeTable(edges, vertexes, z) - remainingValues = remainingEdgeTable.values() - for edge in remainingValues: - if len( edge.faceIndexes ) < 2: - print('This should never happen, there is a hole in the triangle mesh, each edge should have two faces.') - print(edge) - print('Something will still be printed, but there is no guarantee that it will be the correct shape.' ) - print('Once the gcode is saved, you should check over the layer with a z of:') - print(z) - return [] - loops = [] - while isPathAdded( edges, faces, loops, remainingEdgeTable, vertexes, z ): - pass - if euclidean.isLoopListIntersecting(loops): - print('Warning, the triangle mesh slice intersects itself in getLoopsFromCorrectMesh in triangle_mesh.') - print('Something will still be printed, but there is no guarantee that it will be the correct shape.') - print('Once the gcode is saved, you should check over the layer with a z of:') - print(z) - return [] - return loops -# untouchables = [] -# for boundingLoop in boundingLoops: -# if not boundingLoop.isIntersectingList( untouchables ): -# untouchables.append( boundingLoop ) -# if len( untouchables ) < len( boundingLoops ): -# print('This should never happen, the carve layer intersects itself. Something will still be printed, but there is no guarantee that it will be the correct shape.') -# print('Once the gcode is saved, you should check over the layer with a z of:') -# print(z) -# remainingLoops = [] -# for untouchable in untouchables: -# remainingLoops.append( untouchable.loop ) -# return remainingLoops - -def getLoopsFromUnprovenMesh(edges, faces, importRadius, vertexes, z): - """Get loops from a carve of an unproven mesh.""" - edgePairTable = {} - corners = [] - remainingEdgeTable = getRemainingEdgeTable(edges, vertexes, z) - remainingEdgeTableKeys = remainingEdgeTable.keys() - for remainingEdgeIndexKey in remainingEdgeTable: - edge = remainingEdgeTable[remainingEdgeIndexKey] - carveIntersection = getCarveIntersectionFromEdge(edge, vertexes, z) - corners.append(carveIntersection) - for edgeFaceIndex in edge.faceIndexes: - face = faces[edgeFaceIndex] - for edgeIndex in face.edgeIndexes: - addEdgePair(edgePairTable, edges, edgeIndex, remainingEdgeIndexKey, remainingEdgeTable) - allPoints = corners[:] - for edgePairValue in edgePairTable.values(): - addPointsAtZ(edgePairValue, allPoints, importRadius, vertexes, z) - pointTable = {} - return getDescendingAreaLoops(allPoints, corners, importRadius) - -def getLoopsWithCorners(corners, importRadius, loops, pointTable): - """Add corners to the loops.""" - for corner in corners: - if corner not in pointTable: - addWithLeastLength(importRadius, loops, corner) - pointTable[corner] = None - return euclidean.getSimplifiedLoops(loops, importRadius) - -def getNextEdgeIndexAroundZ( edge, faces, remainingEdgeTable ): - """Get the next edge index in the mesh carve.""" - for faceIndex in edge.faceIndexes: - face = faces[ faceIndex ] - for edgeIndex in face.edgeIndexes: - if edgeIndex in remainingEdgeTable: - return edgeIndex - return - 1 - -def getOrientedLoops(loops): - """Orient the loops which must be in descending order.""" - for loopIndex, loop in enumerate(loops): - leftPoint = euclidean.getLeftPoint(loop) - isInFilledRegion = euclidean.getIsInFilledRegion(loops[: loopIndex] + loops[loopIndex + 1 :], leftPoint) - if isInFilledRegion == euclidean.isWiddershins(loop): - loop.reverse() - return loops - -def getOverhangDirection( belowOutsetLoops, segmentBegin, segmentEnd ): - """Add to span direction from the endpoint segments which overhang the layer below.""" - segment = segmentEnd - segmentBegin - normalizedSegment = euclidean.getNormalized( complex( segment.real, segment.imag ) ) - segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) - segmentBegin = segmentYMirror * segmentBegin - segmentEnd = segmentYMirror * segmentEnd - solidXIntersectionList = [] - y = segmentBegin.imag - solidXIntersectionList.append( euclidean.XIntersectionIndex( - 1.0, segmentBegin.real ) ) - solidXIntersectionList.append( euclidean.XIntersectionIndex( - 1.0, segmentEnd.real ) ) - for belowLoopIndex in xrange( len( belowOutsetLoops ) ): - belowLoop = belowOutsetLoops[ belowLoopIndex ] - rotatedOutset = euclidean.getPointsRoundZAxis( segmentYMirror, belowLoop ) - euclidean.addXIntersectionIndexesFromLoopY( rotatedOutset, belowLoopIndex, solidXIntersectionList, y ) - overhangingSegments = euclidean.getSegmentsFromXIntersectionIndexes( solidXIntersectionList, y ) - overhangDirection = complex() - for overhangingSegment in overhangingSegments: - overhangDirection += getDoubledRoundZ( overhangingSegment, normalizedSegment ) - return overhangDirection - -def getOverlapRatio( loop, pointTable ): - """Get the overlap ratio between the loop and the point table.""" - numberOfOverlaps = 0 - for point in loop: - if point in pointTable: - numberOfOverlaps += 1 - return float( numberOfOverlaps ) / float(len(loop)) - -def getPath( edges, pathIndexes, loop, z ): - """Get the path from the edge intersections.""" - path = [] - for pathIndexIndex in xrange( len( pathIndexes ) ): - pathIndex = pathIndexes[ pathIndexIndex ] - edge = edges[ pathIndex ] - carveIntersection = getCarveIntersectionFromEdge( edge, loop, z ) - path.append( carveIntersection ) - return path - -def getPillarOutput(loops): - """Get pillar output.""" - faces = [] - vertexes = getUniqueVertexes(loops) - addPillarByLoops(faces, loops) - return getGeometryOutputByFacesVertexes(faces, vertexes) - -def getPillarsOutput(loopLists): - """Get pillars output.""" - pillarsOutput = [] - for loopList in loopLists: - pillarsOutput.append(getPillarOutput(loopList)) - return getUnifiedOutput(pillarsOutput) - -def getRemainingEdgeTable(edges, vertexes, z): - """Get the remaining edge hashtable.""" - remainingEdgeTable = {} - if len(edges) > 0: - if edges[0].zMinimum is None: - for edge in edges: - setEdgeMaximumMinimum(edge, vertexes) - for edgeIndex in xrange(len(edges)): - edge = edges[edgeIndex] - if (edge.zMinimum < z) and (edge.zMaximum > z): - remainingEdgeTable[edgeIndex] = edge - return remainingEdgeTable - -def getRemainingLoopAddFace(faces, remainingLoop): - """Get the remaining loop and add face.""" - for indexedVertexIndex, indexedVertex in enumerate(remainingLoop): - nextIndex = (indexedVertexIndex + 1) % len(remainingLoop) - previousIndex = (indexedVertexIndex + len(remainingLoop) - 1) % len(remainingLoop) - nextVertex = remainingLoop[nextIndex] - previousVertex = remainingLoop[previousIndex] - remainingPath = euclidean.getAroundLoop((indexedVertexIndex + 2) % len(remainingLoop), previousIndex, remainingLoop) - if len(remainingLoop) < 4 or getIsPathEntirelyOutsideTriangle(previousVertex, indexedVertex, nextVertex, remainingPath): - faceConvex = face.Face() - faceConvex.index = len(faces) - faceConvex.vertexIndexes.append(indexedVertex.index) - faceConvex.vertexIndexes.append(nextVertex.index) - faceConvex.vertexIndexes.append(previousVertex.index) - faces.append(faceConvex) - return euclidean.getAroundLoop(nextIndex, indexedVertexIndex, remainingLoop) - print('Warning, could not decompose polygon in getRemainingLoopAddFace in trianglemesh for:') - print(remainingLoop) - return [] - -def getSharedFace( firstEdge, faces, secondEdge ): - """Get the face which is shared by two edges.""" - for firstEdgeFaceIndex in firstEdge.faceIndexes: - for secondEdgeFaceIndex in secondEdge.faceIndexes: - if firstEdgeFaceIndex == secondEdgeFaceIndex: - return faces[ firstEdgeFaceIndex ] - return None - -def getSymmetricXLoop(path, vertexes, x): - """Get symmetrix x loop.""" - loop = [] - for point in path: - vector3Index = Vector3Index(len(vertexes), x, point.real, point.imag) - loop.append(vector3Index) - vertexes.append(vector3Index) - return loop - -def getSymmetricYLoop(path, vertexes, y): - """Get symmetrix y loop.""" - loop = [] - for point in path: - vector3Index = Vector3Index(len(vertexes), point.real, y, point.imag) - loop.append(vector3Index) - vertexes.append(vector3Index) - return loop - -def getUnifiedOutput(outputs): - """Get unified output.""" - if len(outputs) < 1: - return {} - if len(outputs) == 1: - return outputs[0] - return {'union' : {'shapes' : outputs}} - -def getUniqueVertexes(loops): - """Get unique vertexes.""" - vertexDictionary = {} - uniqueVertexes = [] - for loop in loops: - for vertexIndex, vertex in enumerate(loop): - vertexTuple = (vertex.x, vertex.y, vertex.z) - if vertexTuple in vertexDictionary: - loop[vertexIndex] = vertexDictionary[vertexTuple] - else: - if vertex.__class__ == Vector3Index: - loop[vertexIndex].index = len(vertexDictionary) - else: - loop[vertexIndex] = Vector3Index(len(vertexDictionary), vertex.x, vertex.y, vertex.z) - vertexDictionary[vertexTuple] = loop[vertexIndex] - uniqueVertexes.append(loop[vertexIndex]) - return uniqueVertexes - -def getWideAnglePointIndex(loop): - """Get a point index which has a wide enough angle, most point indexes have a wide enough angle, this is just to make sure.""" - dotProductMinimum = 9999999.9 - widestPointIndex = 0 - for pointIndex in xrange(len(loop)): - point = loop[ pointIndex % len(loop) ] - afterPoint = loop[(pointIndex + 1) % len(loop)] - beforePoint = loop[ ( pointIndex - 1 ) % len(loop) ] - afterSegmentNormalized = euclidean.getNormalized( afterPoint - point ) - beforeSegmentNormalized = euclidean.getNormalized( beforePoint - point ) - dotProduct = euclidean.getDotProduct( afterSegmentNormalized, beforeSegmentNormalized ) - if dotProduct < .99: - return pointIndex - if dotProduct < dotProductMinimum: - dotProductMinimum = dotProduct - widestPointIndex = pointIndex - return widestPointIndex - -def getZAddExtruderPathsBySolidCarving(rotatedLoopLayer, solidCarving, z): - """Get next z and add extruder loops by solid carving.""" - solidCarving.rotatedLoopLayers.append(rotatedLoopLayer) - nextZ = z + solidCarving.layerThickness - if not solidCarving.infillInDirectionOfBridge: - return nextZ - allExtrudateLoops = [] - for loop in rotatedLoopLayer.loops: - allExtrudateLoops += getBridgeLoops(solidCarving.layerThickness, loop) - rotatedLoopLayer.rotation = getBridgeDirection(solidCarving.belowLoops, allExtrudateLoops, solidCarving.layerThickness) - solidCarving.belowLoops = allExtrudateLoops - return nextZ - -def isInline( beginComplex, centerComplex, endComplex ): - """Determine if the three complex points form a line.""" - centerBeginComplex = beginComplex - centerComplex - centerEndComplex = endComplex - centerComplex - centerBeginLength = abs( centerBeginComplex ) - centerEndLength = abs( centerEndComplex ) - if centerBeginLength <= 0.0 or centerEndLength <= 0.0: - return False - centerBeginComplex /= centerBeginLength - centerEndComplex /= centerEndLength - return euclidean.getDotProduct( centerBeginComplex, centerEndComplex ) < -0.999 - -def isPathAdded( edges, faces, loops, remainingEdgeTable, vertexes, z ): - """Get the path indexes around a triangle mesh carve and add the path to the flat loops.""" - if len( remainingEdgeTable ) < 1: - return False - pathIndexes = [] - remainingEdgeIndexKey = remainingEdgeTable.keys()[0] - pathIndexes.append( remainingEdgeIndexKey ) - del remainingEdgeTable[remainingEdgeIndexKey] - nextEdgeIndexAroundZ = getNextEdgeIndexAroundZ( edges[remainingEdgeIndexKey], faces, remainingEdgeTable ) - while nextEdgeIndexAroundZ != - 1: - pathIndexes.append( nextEdgeIndexAroundZ ) - del remainingEdgeTable[ nextEdgeIndexAroundZ ] - nextEdgeIndexAroundZ = getNextEdgeIndexAroundZ( edges[ nextEdgeIndexAroundZ ], faces, remainingEdgeTable ) - if len( pathIndexes ) < 3: - print('Dangling edges, will use intersecting circles to get import layer at height %s' % z) - del loops[:] - return False - loops.append( getPath( edges, pathIndexes, vertexes, z ) ) - return True - -def processXMLElement(xmlElement): - """Process the xml element.""" - evaluate.processArchivable(TriangleMesh, xmlElement) - -def setEdgeMaximumMinimum(edge, vertexes): - """Set the edge maximum and minimum.""" - beginIndex = edge.vertexIndexes[0] - endIndex = edge.vertexIndexes[1] - if beginIndex >= len(vertexes) or endIndex >= len(vertexes): - print('Warning, there are duplicate vertexes in setEdgeMaximumMinimum in triangle_mesh.') - print('Something might still be printed, but there is no guarantee that it will be the correct shape.' ) - edge.zMaximum = -987654321.0 - edge.zMinimum = -987654321.0 - return - beginZ = vertexes[beginIndex].z - endZ = vertexes[endIndex].z - edge.zMinimum = min(beginZ, endZ) - edge.zMaximum = max(beginZ, endZ) - -def sortLoopsInOrderOfArea(isDescending, loops): - """Sort the loops in the order of area according isDescending.""" - loops.sort(key=euclidean.getAreaLoopAbsolute, reverse=isDescending) - - -class EdgePair: - def __init__(self): - """Pair of edges on a face.""" - self.edgeIndexes = [] - self.edges = [] - - def __repr__(self): - """Get the string representation of this EdgePair.""" - return str( self.edgeIndexes ) - - def getFromIndexesEdges( self, edgeIndexes, edges ): - """Initialize from edge indices.""" - self.edgeIndexes = edgeIndexes[:] - self.edgeIndexes.sort() - for edgeIndex in self.edgeIndexes: - self.edges.append( edges[ edgeIndex ] ) - return self - - -class TriangleMesh( group.Group ): - """A triangle mesh.""" - def __init__(self): - """Add empty lists.""" - group.Group.__init__(self) - self.belowLoops = [] - self.infillInDirectionOfBridge = False - self.edges = [] - self.faces = [] - self.importCoarseness = 1.0 - self.isCorrectMesh = True - self.oldChainTetragrid = None - self.rotatedLoopLayers = [] - self.transformedVertexes = None - self.vertexes = [] - - def addXMLSection(self, depth, output): - """Add the xml section for this object.""" - xml_simple_writer.addXMLFromVertexes( depth, output, self.vertexes ) - xml_simple_writer.addXMLFromObjects( depth, self.faces, output ) - - def getCarveCornerMaximum(self): - """Get the corner maximum of the vertexes.""" - return self.cornerMaximum - - def getCarveCornerMinimum(self): - """Get the corner minimum of the vertexes.""" - return self.cornerMinimum - - def getCarveLayerThickness(self): - """Get the layer thickness.""" - return self.layerThickness - - def getCarveRotatedBoundaryLayers(self): - """Get the rotated boundary layers.""" - if self.getMinimumZ() is None: - return [] - halfHeight = 0.5 * self.layerThickness - self.zoneArrangement = ZoneArrangement(self.layerThickness, self.getTransformedVertexes()) - layerTop = self.cornerMaximum.z - halfHeight * 0.5 - z = self.cornerMinimum.z + halfHeight - while z < layerTop: - z = self.getZAddExtruderPaths(z) - return self.rotatedLoopLayers - - def getFabmetheusXML(self): - """Return the fabmetheus XML.""" - return None - - def getGeometryOutput(self): - """Get geometry output dictionary.""" - return getGeometryOutputByFacesVertexes(self.faces, self.vertexes) - - def getInterpretationSuffix(self): - """Return the suffix for a triangle mesh.""" - return 'xml' - - def getLoops(self, importRadius, z): - """Get loops sliced through shape.""" - self.importRadius = importRadius - return self.getLoopsFromMesh(z) - - def getLoopsFromMesh( self, z ): - """Get loops from a carve of a mesh.""" - originalLoops = [] - self.setEdgesForAllFaces() - if self.isCorrectMesh: - originalLoops = getLoopsFromCorrectMesh( self.edges, self.faces, self.getTransformedVertexes(), z ) - if len( originalLoops ) < 1: - originalLoops = getLoopsFromUnprovenMesh( self.edges, self.faces, self.importRadius, self.getTransformedVertexes(), z ) - loops = euclidean.getSimplifiedLoops(originalLoops, self.importRadius) - sortLoopsInOrderOfArea(True, loops) - return getOrientedLoops(loops) - - def getMinimumZ(self): - """Get the minimum z.""" - self.cornerMaximum = Vector3(-987654321.0, -987654321.0, -987654321.0) - self.cornerMinimum = Vector3(987654321.0, 987654321.0, 987654321.0) - transformedVertexes = self.getTransformedVertexes() - if len(transformedVertexes) < 1: - return None - for point in transformedVertexes: - self.cornerMaximum.maximize(point) - self.cornerMinimum.minimize(point) - return self.cornerMinimum.z - - def getTransformedVertexes(self): - """Get all transformed vertexes.""" - if self.xmlElement is None: - return self.vertexes - chainTetragrid = self.getMatrixChainTetragrid() - if self.oldChainTetragrid != chainTetragrid: - self.oldChainTetragrid = chainTetragrid - self.transformedVertexes = None - if self.transformedVertexes is None: - if len(self.edges) > 0: - self.edges[0].zMinimum = None - self.transformedVertexes = matrix.getTransformedVector3s(chainTetragrid, self.vertexes) - return self.transformedVertexes - - def getTriangleMeshes(self): - """Get all triangleMeshes.""" - return [self] - - def getVertexes(self): - """Get all vertexes.""" - self.transformedVertexes = None - return self.vertexes - - def getZAddExtruderPaths(self, z): - """Get next z and add extruder loops.""" - settings.printProgress(len(self.rotatedLoopLayers), 'slice') - rotatedLoopLayer = euclidean.RotatedLoopLayer(z) - rotatedLoopLayer.loops = self.getLoopsFromMesh(self.zoneArrangement.getEmptyZ(z)) - return getZAddExtruderPathsBySolidCarving(rotatedLoopLayer, self, z) - - def liftByMinimumZ(self, minimumZ): - """Lift the triangle mesh to the altitude.""" - altitude = evaluate.getEvaluatedFloat(None, 'altitude', self.xmlElement) - if altitude is None: - return - lift = altitude - minimumZ - for vertex in self.vertexes: - vertex.z += lift - - def setCarveInfillInDirectionOfBridge( self, infillInDirectionOfBridge ): - """Set the infill in direction of bridge.""" - self.infillInDirectionOfBridge = infillInDirectionOfBridge - - def setCarveLayerThickness( self, layerThickness ): - """Set the layer thickness.""" - self.layerThickness = layerThickness - - def setCarveImportRadius( self, importRadius ): - """Set the import radius.""" - self.importRadius = importRadius - - def setCarveIsCorrectMesh( self, isCorrectMesh ): - """Set the is correct mesh flag.""" - self.isCorrectMesh = isCorrectMesh - - def setEdgesForAllFaces(self): - """Set the face edges of all the faces.""" - edgeTable = {} - for face in self.faces: - face.setEdgeIndexesToVertexIndexes( self.edges, edgeTable ) - - -class ZoneArrangement: - """A zone arrangement.""" - def __init__(self, layerThickness, vertexes): - """Initialize the zone interval and the zZone table.""" - self.zoneInterval = layerThickness / math.sqrt(len(vertexes)) / 1000.0 - self.zZoneSet = set() - for point in vertexes: - zoneIndexFloat = point.z / self.zoneInterval - self.zZoneSet.add(math.floor(zoneIndexFloat)) - self.zZoneSet.add(math.ceil(zoneIndexFloat )) - - def getEmptyZ(self, z): - """Get the first z which is not in the zone table.""" - zoneIndex = round(z / self.zoneInterval) - if zoneIndex not in self.zZoneSet: - return z - zoneAround = 1 - while 1: - zoneDown = zoneIndex - zoneAround - if zoneDown not in self.zZoneSet: - return zoneDown * self.zoneInterval - zoneUp = zoneIndex + zoneAround - if zoneUp not in self.zZoneSet: - return zoneUp * self.zoneInterval - zoneAround += 1 diff --git a/skeinforge/fabmetheus_utilities/geometry/solids/union.py b/skeinforge/fabmetheus_utilities/geometry/solids/union.py deleted file mode 100644 index e9d99c8..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/solids/union.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Boolean geometry union of solids. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.solids import difference -from fabmetheus_utilities.geometry.solids import group - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def convertXMLElement(geometryOutput, xmlElement): - """Convert the xml element to a union xml element.""" - group.convertContainerXMLElement(geometryOutput, xmlElement, Union()) - -def processXMLElement(xmlElement): - """Process the xml element.""" - evaluate.processArchivable(Union, xmlElement) - - -class Union(difference.Difference): - """A difference object.""" - def getLoopsFromObjectLoopsList(self, importRadius, visibleObjectLoopsList): - """Get loops from visible object loops list.""" - return self.getUnion(importRadius, visibleObjectLoopsList) diff --git a/skeinforge/fabmetheus_utilities/geometry/statements/__init__.py b/skeinforge/fabmetheus_utilities/geometry/statements/__init__.py deleted file mode 100644 index 1121e8a..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/statements/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry/statements/_print.py b/skeinforge/fabmetheus_utilities/geometry/statements/_print.py deleted file mode 100644 index 9886cbc..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/statements/_print.py +++ /dev/null @@ -1,63 +0,0 @@ -""" -Print statement. - -There is also the print attribute in geometry_utilities/evaluate_fundamentals/print.py - -The model is xml_models/geometry_utilities/evaluate_fundamentals/print.xml - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getLocalDictionary( attributeDictionaryKey, xmlElement): - """Get the local dictionary.""" - xmlProcessor = xmlElement.getXMLProcessor() - if len( xmlProcessor.functions ) < 1: - return None - return xmlProcessor.functions[-1].localDictionary - -def printAttributeDictionaryKey( attributeDictionaryKey, xmlElement): - """Print the attributeDictionaryKey.""" - if attributeDictionaryKey.lower() == '_localdictionary': - localDictionary = getLocalDictionary( attributeDictionaryKey, xmlElement) - if localDictionary is not None: - localDictionaryKeys = localDictionary.keys() - attributeValue = xmlElement.attributeDictionary[attributeDictionaryKey] - if attributeValue != '': - attributeValue = ' - ' + attributeValue - print('Local Dictionary Variables' + attributeValue ) - localDictionaryKeys.sort() - for localDictionaryKey in localDictionaryKeys: - print('%s: %s' % ( localDictionaryKey, localDictionary[ localDictionaryKey ] ) ) - return - value = xmlElement.attributeDictionary[attributeDictionaryKey] - evaluatedValue = None - if value == '': - evaluatedValue = evaluate.getEvaluatedExpressionValue( attributeDictionaryKey, xmlElement ) - else: - evaluatedValue = evaluate.getEvaluatedExpressionValue(value, xmlElement) - print('%s: %s' % ( attributeDictionaryKey, evaluatedValue ) ) - -def processXMLElement(xmlElement): - """Process the xml element.""" - if len(xmlElement.text) > 1: - print(xmlElement.text) - return - attributeDictionaryKeys = xmlElement.attributeDictionary.keys() - if len( attributeDictionaryKeys ) < 1: - print('') - return - attributeDictionaryKeys.sort() - for attributeDictionaryKey in attributeDictionaryKeys: - printAttributeDictionaryKey( attributeDictionaryKey, xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/statements/class.py b/skeinforge/fabmetheus_utilities/geometry/statements/class.py deleted file mode 100644 index fc6511a..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/statements/class.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -Class. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def processXMLElement(xmlElement): - """Process the xml element.""" - pass diff --git a/skeinforge/fabmetheus_utilities/geometry/statements/elif.py b/skeinforge/fabmetheus_utilities/geometry/statements/elif.py deleted file mode 100644 index 0bef57f..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/statements/elif.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -Polygon path. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def processElse(xmlElement): - """Process the else statement.""" - evaluate.processCondition(xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - pass diff --git a/skeinforge/fabmetheus_utilities/geometry/statements/else.py b/skeinforge/fabmetheus_utilities/geometry/statements/else.py deleted file mode 100644 index cb7ef12..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/statements/else.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -Polygon path. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def processElse(xmlElement): - """Process the else statement.""" - functions = xmlElement.getXMLProcessor().functions - if len(functions) < 1: - print('Warning, "else" element is not in a function in processElse in else.py for:') - print(xmlElement) - return - functions[-1].processChildren(xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - pass diff --git a/skeinforge/fabmetheus_utilities/geometry/statements/for.py b/skeinforge/fabmetheus_utilities/geometry/statements/for.py deleted file mode 100644 index 444c4c8..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/statements/for.py +++ /dev/null @@ -1,72 +0,0 @@ -""" -Polygon path. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def processChildrenByIndexValue( function, index, indexValue, value, xmlElement ): - """Process children by index value.""" - if indexValue.indexName != '': - function.localDictionary[ indexValue.indexName ] = index - if indexValue.valueName != '': - function.localDictionary[ indexValue.valueName ] = value - function.processChildren(xmlElement) - -def processXMLElement(xmlElement): - """Process the xml element.""" - if xmlElement.xmlObject is None: - xmlElement.xmlObject = IndexValue(xmlElement) - if xmlElement.xmlObject.inSplitWords is None: - return - xmlProcessor = xmlElement.getXMLProcessor() - if len( xmlProcessor.functions ) < 1: - print('Warning, "for" element is not in a function in processXMLElement in for.py for:') - print(xmlElement) - return - function = xmlProcessor.functions[-1] - inValue = evaluate.getEvaluatedExpressionValueBySplitLine( xmlElement.xmlObject.inSplitWords, xmlElement ) - if inValue.__class__ == list or inValue.__class__ == str: - for index, value in enumerate( inValue ): - processChildrenByIndexValue( function, index, xmlElement.xmlObject, value, xmlElement ) - return - if inValue.__class__ == dict: - inKeys = inValue.keys() - inKeys.sort() - for inKey in inKeys: - processChildrenByIndexValue( function, inKey, xmlElement.xmlObject, inValue[ inKey ], xmlElement ) - - -class IndexValue: - """Class to get the in attribute, the index name and the value name.""" - def __init__(self, xmlElement): - """Initialize.""" - self.inSplitWords = None - self.indexName = '' - if 'index' in xmlElement.attributeDictionary: - self.indexName = xmlElement.attributeDictionary['index'] - self.valueName = '' - if 'value' in xmlElement.attributeDictionary: - self.valueName = xmlElement.attributeDictionary['value'] - if 'in' in xmlElement.attributeDictionary: - self.inSplitWords = evaluate.getEvaluatorSplitWords( xmlElement.attributeDictionary['in'] ) - else: - print('Warning, could not find the "in" attribute in IndexValue in for.py for:') - print(xmlElement) - return - if len( self.inSplitWords ) < 1: - self.inSplitWords = None - print('Warning, could not get split words for the "in" attribute in IndexValue in for.py for:') - print(xmlElement) - diff --git a/skeinforge/fabmetheus_utilities/geometry/statements/function.py b/skeinforge/fabmetheus_utilities/geometry/statements/function.py deleted file mode 100644 index e72d60c..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/statements/function.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -Polygon path. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def processXMLElement(xmlElement): - """Process the xml element.""" - pass diff --git a/skeinforge/fabmetheus_utilities/geometry/statements/if.py b/skeinforge/fabmetheus_utilities/geometry/statements/if.py deleted file mode 100644 index 4fb4a86..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/statements/if.py +++ /dev/null @@ -1,21 +0,0 @@ -""" -Polygon path. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def processXMLElement(xmlElement): - """Process the xml element.""" - evaluate.processCondition(xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry/statements/return.py b/skeinforge/fabmetheus_utilities/geometry/statements/return.py deleted file mode 100644 index 11f24b3..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/statements/return.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -Polygon path. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def processXMLElement(xmlElement): - """Process the xml element.""" - functions = xmlElement.getXMLProcessor().functions - if len(functions) < 1: - return - function = functions[-1] - function.shouldReturn = True - if xmlElement.xmlObject is None: - if 'return' in xmlElement.attributeDictionary: - value = xmlElement.attributeDictionary['return'] - xmlElement.xmlObject = evaluate.getEvaluatorSplitWords(value) - else: - xmlElement.xmlObject = [] - if len( xmlElement.xmlObject ) > 0: - function.returnValue = evaluate.getEvaluatedExpressionValueBySplitLine( xmlElement.xmlObject, xmlElement ) diff --git a/skeinforge/fabmetheus_utilities/geometry/statements/statement.py b/skeinforge/fabmetheus_utilities/geometry/statements/statement.py deleted file mode 100644 index 291ced5..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/statements/statement.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -Polygon path. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def processXMLElement(xmlElement): - """Process the xml element.""" - functions = xmlElement.getXMLProcessor().functions - if len(functions) < 1: - print('Warning, there are no functions in processXMLElement in statement for:') - print(xmlElement) - return - function = functions[-1] - evaluate.setLocalAttribute(xmlElement) - if xmlElement.xmlObject.value is None: - print('Warning, xmlElement.xmlObject.value is None in processXMLElement in statement for:') - print(xmlElement) - return - localValue = evaluate.getEvaluatedExpressionValueBySplitLine(xmlElement.xmlObject.value, xmlElement) - keywords = xmlElement.xmlObject.key.split('.') - if len(keywords) == 0: - print('Warning, there are no keywords in processXMLElement in statement for:') - print(xmlElement) - return - firstWord = keywords[0] - if len(keywords) == 1: - function.localDictionary[firstWord] = localValue - return - attributeName = keywords[-1] - object = None - if firstWord == 'self': - object = function.classObject - else: - object = function.localDictionary[firstWord] - for keywordIndex in xrange(1, len(keywords) - 1): - object = object._getAccessibleAttribute(keywords[keywordIndex]) - object._setAccessibleAttribute(attributeName, localValue) diff --git a/skeinforge/fabmetheus_utilities/geometry/statements/while.py b/skeinforge/fabmetheus_utilities/geometry/statements/while.py deleted file mode 100644 index f29dfe0..0000000 --- a/skeinforge/fabmetheus_utilities/geometry/statements/while.py +++ /dev/null @@ -1,34 +0,0 @@ -""" -Polygon path. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Art of Illusion ' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def processXMLElement(xmlElement): - """Process the xml element.""" - if xmlElement.xmlObject is None: - if 'condition' in xmlElement.attributeDictionary: - value = xmlElement.attributeDictionary['condition'] - xmlElement.xmlObject = evaluate.getEvaluatorSplitWords(value) - else: - xmlElement.xmlObject = [] - if len( xmlElement.xmlObject ) < 1: - return - xmlProcessor = xmlElement.getXMLProcessor() - if len( xmlProcessor.functions ) < 1: - return - function = xmlProcessor.functions[-1] - while evaluate.getEvaluatedExpressionValueBySplitLine( xmlElement.xmlObject, xmlElement ) > 0: - function.processChildren(xmlElement) diff --git a/skeinforge/fabmetheus_utilities/geometry_plugins/__init__.py b/skeinforge/fabmetheus_utilities/geometry_plugins/__init__.py deleted file mode 100644 index 2dc8ddc..0000000 --- a/skeinforge/fabmetheus_utilities/geometry_plugins/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 2 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry_plugins/creation/__init__.py b/skeinforge/fabmetheus_utilities/geometry_plugins/creation/__init__.py deleted file mode 100644 index 1121e8a..0000000 --- a/skeinforge/fabmetheus_utilities/geometry_plugins/creation/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry_plugins/manipulation_matrix/__init__.py b/skeinforge/fabmetheus_utilities/geometry_plugins/manipulation_matrix/__init__.py deleted file mode 100644 index 1121e8a..0000000 --- a/skeinforge/fabmetheus_utilities/geometry_plugins/manipulation_matrix/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry_plugins/manipulation_meta/__init__.py b/skeinforge/fabmetheus_utilities/geometry_plugins/manipulation_meta/__init__.py deleted file mode 100644 index 1121e8a..0000000 --- a/skeinforge/fabmetheus_utilities/geometry_plugins/manipulation_meta/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry_plugins/manipulation_paths/__init__.py b/skeinforge/fabmetheus_utilities/geometry_plugins/manipulation_paths/__init__.py deleted file mode 100644 index 1121e8a..0000000 --- a/skeinforge/fabmetheus_utilities/geometry_plugins/manipulation_paths/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/geometry_plugins/manipulation_shapes/__init__.py b/skeinforge/fabmetheus_utilities/geometry_plugins/manipulation_shapes/__init__.py deleted file mode 100644 index 1121e8a..0000000 --- a/skeinforge/fabmetheus_utilities/geometry_plugins/manipulation_shapes/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/hidden_scrollbar.py b/skeinforge/fabmetheus_utilities/hidden_scrollbar.py deleted file mode 100644 index b5e4ed6..0000000 --- a/skeinforge/fabmetheus_utilities/hidden_scrollbar.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -Hidden scrollbar is in its own file so that even if Tkinter is not installed, settings can still be imported. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ -try: - import Tkinter - class HiddenScrollbar(Tkinter.Scrollbar): - """A class to hide the scrollbar if it is not needed.""" - def set(self, lo, hi): - """Add to grid is needed, remove if not.""" - if float(lo) <= 0.0 and float(hi) >= 1.0: - self.grid_remove() - self.visible = False - else: - self.grid() - self.visible = True - Tkinter.Scrollbar.set(self, lo, hi) -except: - pass - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/23/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' diff --git a/skeinforge/fabmetheus_utilities/images/display_line.ppm b/skeinforge/fabmetheus_utilities/images/display_line.ppm deleted file mode 100644 index 4738d03..0000000 --- a/skeinforge/fabmetheus_utilities/images/display_line.ppm +++ /dev/null @@ -1,5 +0,0 @@ -P6 -# CREATOR: The GIMP's PNM Filter Version 1.0 -27 27 -255 -ðôôðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóðóóîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòîòòîòòîòòíññÙØZäâHîìMõóP÷õRôòRíìcåéééíííññîòòîòòîòòîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòîòòíññÜÞ«ÖÔCæäHïíM÷õRüúVÿÿ\ÿÿkÿÿ\õóTáâ¦äèèëïïíññîòòîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòîòòëïïÎÍ@àÞEëéKõóPüúVÿÿ~ÿÿÉÿÿãÿÿÉÿÿ~õóTÐÔÔãççëïïîòòîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòíññÄÃRÖÕ@ãáFîìLøöSÿÿ\ÿÿÉÿÿþÿÿÛÿÿþÿÿÉÿÿ\åä\ÐÔÔäèèíññîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòéííÄÃ:×Ö@äâGïíMù÷TÿÿkÿÿãÿÿÛÿýYÿÿÛÿÿãÿÿkòðQº½½ÙÜÜéííîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòåééÇÆ:ÖÕ@ãáFîìLøöSÿÿ\ÿÿÉÿÿþÿÿÛÿÿþÿÿÉÿÿ\õóQ¢¥¥ËÏÏåééîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòàääÆÄ9ÔÒ?àÞEëéKõóPüúVÿÿ~ÿÿÉÿÿãÿÿÉÿÿ~üúVõóP”——ÃÆÆàääîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòÞâ⿾6ÏÍ=ÛÙBæäHïíM÷õRüúVÿÿ\ÿÿkÿÿ\üúV÷õRìêKŽ¾ÂÂÞââîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòÞâⱯ4ÈÇ:ÕÓ?ßÝDèæIïíMõóPøöSù÷TøöSõóPïíMàÞEŽ¾ÂÂÞââîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòÞâ⢢CÀ¿7ÌÊ<ÖÕ@ßÝDæäHëéKîìLïíMîìLëéKæäHÆÄGŽ¾ÂÂÞââîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòàääÃÆÆ©¨2ÂÀ8ÌÊ<ÕÓ?ÛÙBàÞEãáFäâGãáFàÞEÑÏ@rtt”——ÃÆÆàääîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòåééËÏÏœw¨¦2ÑÐ@óñRÿýYôòSæåWÿýYôòSÉÇ=ŠŠV}¢¥¥ËÏÏåééîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòéííÙÜܺ½½“––ÞÜCæäHðîNûùWòòtÿÿ×æåLfggwyy“––º½½ÙÜÜéííîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòíññäèèÐÔÔ¯²²ÞÜCëéJöôQÿýYÿÿÍÿÿãÿýYrttŽ¯²²ÐÔÔäèèíññîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòîòòëïïãççÊÍÍÞÜCëéJöôQÿýYÿÿÑÿÿåÿýYƒƒ¨««ÊÍÍãççëïïîòòîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòîòòíññëïïÙÜÜÞÜCëéJöôQÿýYÿÿÑÿÿåÿýY‰ŒŒ·ººÙÜÜëïïíññîòòîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòîòòîòòîòòÞâ⃃ƒ›››±±±ÄÄÄÓÓÓüüüÓÓÓŽ½ÁÁÞââîòòîòòîòòîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòîòòîòòîòòÞâ⎎™šš¬¬¬­®®¹ººÙÚÚ½½½’’¿ÃÃÞââîòòîòòîòòîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòîòòîòòîòòßãã‹‹‹ššš¬¬¬½½½ËËËñññÌÌÌ“••ÀÃÃßããîòòîòòîòòîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòîòòîòòîòòàää‘’’š››¤¤¤¶¶¶£¤¤ÐÑÑÂÃÙœœÃÆÆàääîòòîòòîòòîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòîòòîòòîòòâæ涸¸›››®®®ÀÀÀÂÃÃää䧨¨ž  ÆÉÉáååîòòîòòîòòîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòîòòîòòîòòåééÉÍÍ›››±±±ÄÄÄÓÓÓüüü™œœ¦©©ËÏÏãççîòòîòòîòòîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòîòòîòòîòòèììÕØص¸¸“••€‚‚z||„††•˜˜²µµÓÖÖçêêîòòîòòîòòîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòîòòîòòîòòìððßããÈËË«®®›žž”——œžž¬¯¯ÅÈÈÜààêîîîòòîòòîòòîòòîòòîòòîòòðóóîòòîòòîòòîòòîòòîòòîòòîòòíññçëëÜààÍÑÑÃÆÆ¿ÃÃÃÆÆÌÐÐÚÞÞæééíññîòòîòòîòòîòòîòòîòòîòò \ No newline at end of file diff --git a/skeinforge/fabmetheus_utilities/images/dive.ppm b/skeinforge/fabmetheus_utilities/images/dive.ppm deleted file mode 100644 index 39b6e11..0000000 --- a/skeinforge/fabmetheus_utilities/images/dive.ppm +++ /dev/null @@ -1,5 +0,0 @@ -P6 -# CREATOR: The GIMP's PNM Filter Version 1.0 -16 16 -255 -ÿÿÿÿÿÿÿÿÿÿÿÿìôÿØéÿÉáÿ¾Ûÿ¾ÛÿÉáÿØéÿìôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöúÿÙêÿÇÝùÐÞïÕÛãÖØÚÕ×ÙÑØáÍÛìÆÜøÙêÿöúÿÿÿÿÿÿÿÿÿÿöúÿÓæÿÓáòÙÝâèìñóöúûýþûýþòõùåéîÏÔÚÎÜîÓæÿöúÿÿÿÿÿÿÿÙêÿÓáòÖÚà÷øûÿÿÿöùüîóúíóúôøüÿÿÿóöùÇÌÓÍÛìÙêÿÿÿÿìôÿÇÝùÙÝâ÷øûÿÿÿëñùãì÷èïùèïùæïøßéöÿÿÿóöùÄÉÏÃÙõìôÿØéÿÐÝîèìñÿÿÿëñùãì÷YŒÍèïùæïøßéöX‹Ëãì÷ÿÿÿØßçÀÎßØéÿÉáÿÔÚâóöúôøüáë÷S„ÃYŒÍåîøÝèöN{´X‹Ëáë÷ñõûêïö¶½ÅÉáÿ¾ÛÿÔÖØûýþéðùRƒÀRƒÁX‹ËßéöMz³Mz´WŠÊßéöãì÷ùûý«­¯¾Ûÿ¾ÛÿÓÕ×ûýþìòúZŽÑQ€½X‹ËéðùU†ÅP~¹VˆÈÝèöáë÷ñõú§©ª¾ÛÿÉáÿÐ×ßïóøòöûäí÷YÐYŒÏàêöáë÷X‹ËX‹ÍÜçõîóúÛäדּ»ÉáÿØéÿÌÙëáåìþþÿáë÷ãì÷\ÒÝèöÝèößéö[ÑÚåõúüþ¿ÉÖµÃÔØéÿìôÿÄÚ÷ÈÌÒíñ÷ÿÿÿÝèöàêöÜçõÛæõÚåõÛæõþþÿÜä±¾ÔðìôÿÿÿÿÙêÿÉ×è·¾Æèîôþþÿïôûáë÷àêöíóúúüþÛäî–¡¬»ÉÛÙêÿÿÿÿÿÿÿöúÿÓæÿÅÒ䱸¾ÈÑÜáèñòöûîóúÖàí¸ÃÒ¤­ºÈÚÓæÿöúÿÿÿÿÿÿÿÿÿÿöúÿÙêÿÀÖò·ÅÖ¨¯·œŸ˜šœ£ª³±¿Ð¼ÓïÙêÿöúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìôÿØéÿÉáÿ¾Ûÿ¾ÛÿÉáÿØéÿìôÿÿÿÿÿÿÿÿÿÿÿÿÿ \ No newline at end of file diff --git a/skeinforge/fabmetheus_utilities/images/soar.ppm b/skeinforge/fabmetheus_utilities/images/soar.ppm deleted file mode 100644 index 9fb815d..0000000 --- a/skeinforge/fabmetheus_utilities/images/soar.ppm +++ /dev/null @@ -1,5 +0,0 @@ -P6 -# CREATOR: The GIMP's PNM Filter Version 1.0 -16 16 -255 -ÿÿÿÿÿÿÿÿÿÿÿÿìôÿØéÿÉáÿ¾Ûÿ¾ÛÿÉáÿØéÿìôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöúÿÙêÿÇÝùÐÞïÕÛãÖØÚÕ×ÙÑØáÍÛìÆÜøÙêÿöúÿÿÿÿÿÿÿÿÿÿöúÿÓæÿÓáòÙÝâèìñóöúûýþûýþòõùåéîÏÔÚÎÜîÓæÿöúÿÿÿÿÿÿÿÙêÿÓáòÖÚà÷øûÿÿÿöùüîóúíóúôøüÿÿÿóöùÇÌÓÍÛìÙêÿÿÿÿìôÿÇÝùÙÝâ÷øûÿÿÿÜçõéðùèïùèïùÚåõåîøÿÿÿóöùÄÉÏÃÙõìôÿØéÿÐÝîèìñÿÿÿëñùT…ÃÚåõèïùæïøRƒÁÕãóãì÷ÿÿÿØßçÀÎßØéÿÉáÿÔÚâóöúôøüèïùS„ÃS„ÁØåôäí÷RƒÀRƒÀÔâóñõûêïö¶½ÅÉáÿ¾ÛÿÔÖØûýþìòúèïùRƒÁRƒÁVˆÈÛæõRÀR¾U†ÆÛæõùûý«­¯¾Ûÿ¾ÛÿÓÕ×ûýþëñùåîøRƒÁU‡ÆRƒÀìòúQ€¾T…ÃQ€½ìòúñõú§©ª¾ÛÿÉáÿÐ×ßïóøòöûãì÷U‡ÆRÀìòúßéöT…ÃQ€½ëñùîóúÛäדּ»ÉáÿØéÿÌÙëáåìþþÿáë÷R¾ìòúÝèöÝèöQ½éðùÚåõúüþ¿ÉÖµÃÔØéÿìôÿÄÚ÷ÈÌÒíñ÷ÿÿÿëñùÝèöÜçõÛæõéðùØåôþþÿÜä±¾ÔðìôÿÿÿÿÙêÿÉ×è·¾Æèîôþþÿïôûáë÷àêöíóúúüþÛäî–¡¬»ÉÛÙêÿÿÿÿÿÿÿöúÿÓæÿÅÒ䱸¾ÈÑÜáèñòöûîóúÖàí¸ÃÒ¤­ºÈÚÓæÿöúÿÿÿÿÿÿÿÿÿÿöúÿÙêÿÀÖò·ÅÖ¨¯·œŸ˜šœ£ª³±¿Ð¼ÓïÙêÿöúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìôÿØéÿÉáÿ¾Ûÿ¾ÛÿÉáÿØéÿìôÿÿÿÿÿÿÿÿÿÿÿÿÿ \ No newline at end of file diff --git a/skeinforge/fabmetheus_utilities/images/stop.ppm b/skeinforge/fabmetheus_utilities/images/stop.ppm deleted file mode 100644 index d1b9813..0000000 --- a/skeinforge/fabmetheus_utilities/images/stop.ppm +++ /dev/null @@ -1,5 +0,0 @@ -P6 -# CREATOR: The GIMP's PNM Filter Version 1.0 -16 16 -255 -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùâáï³¯íª¦íª¥í¨¤ë¤ží©¥÷ÙØþüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøáàò¹²üÓÂÿÖÁÿѽÿÏ»ÿιüȷퟘòÅÃÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøáàð·±üÔÄÿ£ÿ¯‹ÿ«‰ÿ§„ÿ ~ÿ®‘ûÃ´í¢œöÖÕÿÿÿÿÿÿÿÿÿøáßñµ¯üÑÁÿ¿ ÿª†ÿ§…ÿ¢ÿ|ÿ˜xÿoÿ¡…ûº¬ê—öÓÒÿÿÿÿÿÿüͼÿ»œÿ¥ÿ¢ÿž|ÿ™xÿ“tÿŽoÿ‰iÿ€`ÿ“xû­žå…ÿÿÿÿÿÿê˜ÿ͸ÿ }ÿ|ÿ™xÿ“sÿŽnÿ‰iÿƒeÿ~`ÿxYÿpOÿª˜ârkÿÿÿÿÿÿéš•ÿıÿ˜vÿ“sÿŽnÿ‰iÿƒeÿ~_ÿyZÿsUÿnOÿgHÿ¡áohÿÿÿÿÿÿè”ÿ¾«ÿmÿ‰iÿƒeÿ~_ÿyZÿtUÿoPÿiKÿcFÿ\?ÿ›Šßibÿÿÿÿÿÿ抄ÿ»¦ÿ_ÿ~_ÿyZÿsUÿnPÿiKÿdFÿ^AÿY;ÿO1ÿ™‡Ý^Vÿÿÿÿÿÿ莈ü²¢ÿsÿpOÿnOÿiKÿdFÿ^AÿZ<ÿU7ÿK,ÿgNú“„Þf_ÿÿÿÿÿÿõÒÐ鎇û­Ÿÿgÿ^@ÿ^@ÿY<ÿU7ÿP3ýF(ýeJö–‰áneòÃÁÿÿÿÿÿÿÿÿÿôÌÊç†~ú¥–ÿtZÿP2ÿO0þI,úB%ù`Hô”†âpiñÀ½ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÈÆç|tú—‰ÿ•„üúŽ}÷}ò‹}ÝYQꟛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÆÄàkeÜYRÜ[SÚXPÚRIÜ`Yðº·þúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ \ No newline at end of file diff --git a/skeinforge/fabmetheus_utilities/images/view_move.ppm b/skeinforge/fabmetheus_utilities/images/view_move.ppm deleted file mode 100644 index d566b1e..0000000 Binary files a/skeinforge/fabmetheus_utilities/images/view_move.ppm and /dev/null differ diff --git a/skeinforge/fabmetheus_utilities/images/view_rotate.ppm b/skeinforge/fabmetheus_utilities/images/view_rotate.ppm deleted file mode 100644 index 49ca6be..0000000 Binary files a/skeinforge/fabmetheus_utilities/images/view_rotate.ppm and /dev/null differ diff --git a/skeinforge/fabmetheus_utilities/images/zoom_in.ppm b/skeinforge/fabmetheus_utilities/images/zoom_in.ppm deleted file mode 100644 index 6f4767f..0000000 --- a/skeinforge/fabmetheus_utilities/images/zoom_in.ppm +++ /dev/null @@ -1,5 +0,0 @@ -P6 -# CREATOR: The GIMP's PNM Filter Version 1.0 -16 16 -255 -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôìÜÝÑҮmÏ©eΧcШjÙ»ŒóèÚÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìÜ¿Ô°p×·}æѯ÷ðåöïääάҭwÌ¡gçÓºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôìÜÔ°påÏ©÷úýïõûêòúëóúñöûùûýßţɛcñæØÿÿÿÿÿÿÿÿÿÿÿÿÝ‘׶}÷úýëóúèñùéòùéòúêòúîõûùûýͤqÒ®„ÿÿÿÿÿÿÿÿÿÿÿÿÒ­læÑ®ðöûèñùéòùéòúêòúëóúëóúò÷üßħÒ[ÿÿÿÿÿÿÿÿÿÿÿÿϨc÷ïåëóúéòúêòúêòúëóúg¶\a°W\¨Rôëâ¿‹Pÿÿÿÿÿÿÿÿÿÿÿÿͦböïäìóúêòúêòúëóúëóú_­V¦ÕSžKôë⾇Mÿÿÿÿÿÿÿÿÿÿÿÿͧhä̬ñ÷üëóúëóúc²Y^«Tv·mžÑ•k¬cD‹=>ƒ7ÿÿÿÿÿÿÿÿÿÿÿÿع‹Ñªvùûýïõûìôú\¨RŸÒ—šÏ’†Å}ʈ‹Æƒ5y0ÿÿÿÿÿÿÿÿÿÿÿÿòçÙÊŸeÞÄ£ùûþóøüSžKM–Ee§^‹Ç…Z›S3v..o)ãÍ»ÿÿÿÿÿÿÿÿÿÿÿÿæѹȚ`Ê oÞçôëâôëâ>ƒ7‚Â}2t,ãÌ™ÞļƒOøñíÿÿÿÿÿÿÿÿÿÿÿÿñåØÑ«ƒÁZ¾‡M½…L5y00q+*k&èÕ£é×¥Ú»€¬e?÷ñíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâ˹ÁŽXßÅçÓ àÇ“É›a—aFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáɸ¼„Q×µ}ÖµÑV¶{Qÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáɸ®mH¹€H·yRúöôÿÿÿ \ No newline at end of file diff --git a/skeinforge/fabmetheus_utilities/images/zoom_out.ppm b/skeinforge/fabmetheus_utilities/images/zoom_out.ppm deleted file mode 100644 index 108f893..0000000 --- a/skeinforge/fabmetheus_utilities/images/zoom_out.ppm +++ /dev/null @@ -1,5 +0,0 @@ -P6 -# CREATOR: The GIMP's PNM Filter Version 1.0 -16 16 -255 -ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôìÜÝÑҮmÏ©eΧcШjÙ»ŒóèÚÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìÜ¿Ô°p×·}æѯ÷ðåöïääάҭwÌ¡gçÓºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôìÜÔ°påÏ©÷úýïõûêòúëóúñöûùûýßţɛcñæØÿÿÿÿÿÿÿÿÿÿÿÿÝ‘׶}÷úýëóúèñùéòùéòúêòúîõûùûýͤqÒ®„ÿÿÿÿÿÿÿÿÿÿÿÿÒ­læÑ®ðöûèñùéòùéòúêòúëóúëóúò÷üßħÒ[ÿÿÿÿÿÿÿÿÿÿÿÿϨc÷ïåëóúéòúêòúêòúëóúëóúìóúîõûôëâ¿‹Pÿÿÿÿÿÿÿÿÿÿÿÿͦböïäìóúêòúêòúëóúëóúìóúìôúïõûôë⾇Mÿÿÿÿÿÿÿÿÿÿÿÿͧhä̬ñ÷üëóúëóúþxtüomúcb÷TVôEHñ5:î&.ÿÿÿÿÿÿÿÿÿÿÿÿع‹ÑªvùûýïõûìôúüomøÈ¿÷À·ö¶®ô«¤ó ›ì#ÿÿÿÿÿÿÿÿÿÿÿÿòçÙÊŸeÞÄ£ùûþóøüúcb÷TVôEHñ5:î&.ì#êãÍ»ÿÿÿÿÿÿÿÿÿÿÿÿæѹȚ`Ê oÞçôëâôëâܾ¤ÁSÖ´yãÌ™ÞļƒOøñíÿÿÿÿÿÿÿÿÿÿÿÿñåØÑ«ƒÁZ¾‡M½…L»†R»LÛ¿‡èÕ£é×¥Ú»€¬e?÷ñíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâ˹ÁŽXßÅçÓ àÇ“É›a—aFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáɸ¼„Q×µ}ÖµÑV±rEÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàǶ¥\3¹€H³sKøòïÿÿÿ \ No newline at end of file diff --git a/skeinforge/fabmetheus_utilities/intercircle.py b/skeinforge/fabmetheus_utilities/intercircle.py deleted file mode 100644 index acf5f1c..0000000 --- a/skeinforge/fabmetheus_utilities/intercircle.py +++ /dev/null @@ -1,669 +0,0 @@ -""" -Intercircle is a collection of utilities for intersecting circles, used to get smooth loops around a collection of points and inset & outset loops. - -""" - -from __future__ import absolute_import -try: - import psyco - psyco.full() -except: - pass -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -import math - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalDecreasingRadiusMultipliers = [1.0, 0.55, 0.35, 0.2] - - -def addCircleIntersectionLoop(circleIntersectionLoop, circleIntersections): - """Add a circle intersection loop.""" - firstCircleIntersection = circleIntersectionLoop[0] - circleIntersectionAhead = firstCircleIntersection - for circleIntersectionIndex in xrange(len(circleIntersections) + 1): - circleIntersectionAhead = circleIntersectionAhead.getCircleIntersectionAhead() - if circleIntersectionAhead == firstCircleIntersection or circleIntersectionAhead is None: - firstCircleIntersection.steppedOn = True - return - circleIntersectionAhead.addToList(circleIntersectionLoop) - firstCircleIntersection.steppedOn = True - print( 'addCircleIntersectionLoop would have gone into an endless loop, this should never happen.' ) - print( 'circleIntersectionLoop' ) - for circleIntersection in circleIntersectionLoop: - print(circleIntersection) - print(circleIntersection.circleNodeAhead) - print(circleIntersection.circleNodeBehind) - print('firstCircleIntersection') - print(firstCircleIntersection) - print('circleIntersections') - for circleIntersection in circleIntersections: - print(circleIntersection) - -def addEndCap(begin, end, points, radius): - """Get a pair of side points.""" - endMinusBegin = end - begin - endMinusBeginLength = abs(endMinusBegin) - points.append(begin) - if endMinusBeginLength <= 0.0: - return - endMinusBegin *= radius / endMinusBeginLength - perpendicular = complex(-endMinusBegin.imag, endMinusBegin.real) - beginTowardEnd = begin + endMinusBegin - points.append(beginTowardEnd + perpendicular) - points.append(beginTowardEnd - perpendicular) - beginTowardEndPart = begin + 0.25 * endMinusBegin - perpendicularPart = 0.6 * perpendicular - points.append(beginTowardEndPart + perpendicularPart) - points.append(beginTowardEndPart - perpendicularPart) - -def addInsetPointFromClockwiseTriple(begin, center, end, loop, radius): - """Get inset point with possible intersection from clockwise triple, out from widdershins loop.""" - centerMinusBegin = center - begin - centerMinusBeginLength = abs(centerMinusBegin) - centerMinusBeginClockwise = None - if centerMinusBeginLength > 0.0: - centerMinusBeginClockwise = complex(centerMinusBegin.imag, -centerMinusBegin.real) / centerMinusBeginLength - endMinusCenter = end - center - endMinusCenterLength = abs(endMinusCenter) - endMinusCenterClockwise = None - if endMinusCenterLength > 0.0: - endMinusCenterClockwise = complex(endMinusCenter.imag, -endMinusCenter.real) / endMinusCenterLength - if centerMinusBeginClockwise is None and endMinusCenterClockwise is None: - return None - if centerMinusBeginClockwise is None: - loop.append(center + endMinusCenterClockwise * radius) - if endMinusCenterClockwise is None: - loop.append(center + centerMinusBeginClockwise * radius) - centerClockwise = 0.5 * (centerMinusBeginClockwise + endMinusCenterClockwise) - dotProduct = euclidean.getDotProduct(centerMinusBeginClockwise, centerClockwise) - loop.append(center + centerClockwise * radius / max(0.4, abs(dotProduct))) # 0.4 to avoid pointy corners - -def addOrbits( distanceFeedRate, loop, orbitalFeedRatePerSecond, temperatureChangeTime, z ): - """Add orbits with the extruder off.""" - timeInOrbit = 0.0 - while timeInOrbit < temperatureChangeTime: - for point in loop: - distanceFeedRate.addGcodeMovementZWithFeedRate( 60.0 * orbitalFeedRatePerSecond, point, z ) - timeInOrbit += euclidean.getLoopLength(loop) / orbitalFeedRatePerSecond - -def addOrbitsIfLarge( distanceFeedRate, loop, orbitalFeedRatePerSecond, temperatureChangeTime, z ): - """Add orbits with the extruder off if the orbits are large enough.""" - if orbitsAreLarge( loop, temperatureChangeTime ): - addOrbits( distanceFeedRate, loop, orbitalFeedRatePerSecond, temperatureChangeTime, z ) - -def addPointsFromSegment( pointBegin, pointEnd, points, radius, thresholdRatio=0.9 ): - """Add point complexes between the endpoints of a segment.""" - if radius <= 0.0: - print('This should never happen, radius should never be zero or less in addPointsFromSegment in intercircle.') - thresholdRadius = radius * thresholdRatio # a higher number would be faster but would leave bigger dangling loops and extra dangling loops. - thresholdDiameter = thresholdRadius + thresholdRadius - segment = pointEnd - pointBegin - segmentLength = abs(segment) - extraCircles = int( math.floor( segmentLength / thresholdDiameter ) ) - if extraCircles < 1: - return - if segmentLength == 0.0: - print('This should never happen, segmentLength = 0.0 in intercircle.') - print('pointBegin') - print( pointBegin ) - print( pointEnd ) - return - if extraCircles < 2: - lengthIncrement = segmentLength / ( float(extraCircles) + 1.0 ) - segment *= lengthIncrement / segmentLength - pointBegin += segment - else: - pointBegin += segment * thresholdDiameter / segmentLength - remainingLength = segmentLength - thresholdDiameter - thresholdDiameter - lengthIncrement = remainingLength / ( float(extraCircles) - 1.0 ) - segment *= lengthIncrement / segmentLength - for circleIndex in xrange(extraCircles): - points.append( pointBegin ) - pointBegin += segment - -def directLoop(isWiddershins, loop): - """Direct the loop.""" - if euclidean.isWiddershins(loop) != isWiddershins: - loop.reverse() - -def directLoops(isWiddershins, loops): - """Direct the loops.""" - for loop in loops: - directLoop(isWiddershins, loop) - -def directLoopLists(isWiddershins, loopLists): - """Direct the loop lists.""" - for loopList in loopLists: - directLoops(isWiddershins, loopList) - -def getAroundsFromLoop(loop, radius, thresholdRatio=0.9): - """Get the arounds from the loop.""" - return getAroundsFromPoints(getPointsFromLoop(loop, 1.01 * abs(radius), thresholdRatio), radius) - -def getAroundsFromLoops( loops, radius, thresholdRatio=0.9 ): - """Get the arounds from the loops.""" - return getAroundsFromPoints(getPointsFromLoops(loops, 1.01 * abs(radius), thresholdRatio), radius) - -def getAroundsFromPath(path, radius, thresholdRatio=0.9): - """Get the arounds from the path.""" - return getAroundsFromPoints(getPointsFromPath(path, 1.01 * abs(radius), thresholdRatio), radius) - -def getAroundsFromPaths(paths, radius, thresholdRatio=0.9): - """Get the arounds from the path.""" - points = [] - for path in paths: - points += getPointsFromPath(path, 1.01 * abs(radius), thresholdRatio) - return getAroundsFromPoints(points, radius) - -def getAroundsFromPoints( points, radius ): - """Get the arounds from the points.""" - arounds = [] - radius = abs(radius) - centers = getCentersFromPoints( points, radius ) - for center in centers: - inset = getSimplifiedInsetFromClockwiseLoop( center, radius ) - if isLargeSameDirection( inset, center, radius ): - arounds.append(inset) - return arounds - -def getCentersFromCircleNodes( circleNodes, radius ): - """Get the complex centers of the circle intersection loops from circle nodes.""" - if len( circleNodes ) < 2: - return [] - circleIntersections = getCircleIntersectionsFromCircleNodes( circleNodes ) - circleIntersectionLoops = getCircleIntersectionLoops( circleIntersections ) - return getCentersFromIntersectionLoops( circleIntersectionLoops, radius ) - -def getCentersFromIntersectionLoop(circleIntersectionLoop, radius): - """Get the centers from the intersection loop.""" - loop = [] - for circleIntersection in circleIntersectionLoop: - loop.append(circleIntersection.circleNodeAhead.actualPoint) - return loop - -def getCentersFromIntersectionLoops( circleIntersectionLoops, radius ): - """Get the centers from the intersection loops.""" - centers = [] - for circleIntersectionLoop in circleIntersectionLoops: - centers.append( getCentersFromIntersectionLoop( circleIntersectionLoop, radius ) ) - return centers - -def getCentersFromLoop( loop, radius ): - """Get the centers of the loop.""" - circleNodes = getCircleNodesFromLoop( loop, radius ) - return getCentersFromCircleNodes( circleNodes, radius ) - -def getCentersFromLoopDirection( isWiddershins, loop, radius ): - """Get the centers of the loop which go around in the given direction.""" - centers = getCentersFromLoop( loop, radius ) - return getLoopsFromLoopsDirection( isWiddershins, centers ) - -def getCentersFromPoints(points, radius): - """Get the centers from the points.""" - circleNodes = getCircleNodesFromPoints(points, abs(radius)) - return getCentersFromCircleNodes(circleNodes, abs(radius)) - -def getCircleIntersectionsFromCircleNodes(circleNodes): - """Get all the circle intersections which exist between all the circle nodes.""" - if len( circleNodes ) < 1: - return [] - circleIntersections = [] - index = 0 - pixelTable = {} - for circleNode in circleNodes: - euclidean.addElementToPixelListFromPoint(circleNode, pixelTable, circleNode.dividedPoint) - accumulatedCircleNodeTable = {} - for circleNodeIndex in xrange(len(circleNodes)): - circleNodeBehind = circleNodes[circleNodeIndex] - circleNodeIndexMinusOne = circleNodeIndex - 1 - if circleNodeIndexMinusOne >= 0: - circleNodeAdditional = circleNodes[circleNodeIndexMinusOne] - euclidean.addElementToPixelListFromPoint(circleNodeAdditional, accumulatedCircleNodeTable, 0.5 * circleNodeAdditional.dividedPoint) - withinNodes = circleNodeBehind.getWithinNodes(accumulatedCircleNodeTable) - for circleNodeAhead in withinNodes: - circleIntersectionForward = CircleIntersection(circleNodeAhead, index, circleNodeBehind) - if not circleIntersectionForward.isWithinCircles(pixelTable): - circleIntersections.append(circleIntersectionForward) - circleNodeBehind.circleIntersections.append(circleIntersectionForward) - index += 1 - circleIntersectionBackward = CircleIntersection(circleNodeBehind, index, circleNodeAhead) - if not circleIntersectionBackward.isWithinCircles(pixelTable): - circleIntersections.append(circleIntersectionBackward) - circleNodeAhead.circleIntersections.append(circleIntersectionBackward) - index += 1 - return circleIntersections - -def getCircleIntersectionLoops( circleIntersections ): - """Get all the loops going through the circle intersections.""" - circleIntersectionLoops = [] - for circleIntersection in circleIntersections: - if not circleIntersection.steppedOn: - circleIntersectionLoop = [ circleIntersection ] - circleIntersectionLoops.append( circleIntersectionLoop ) - addCircleIntersectionLoop( circleIntersectionLoop, circleIntersections ) - return circleIntersectionLoops - -def getCircleNodesFromLoop(loop, radius, thresholdRatio=0.9): - """Get the circle nodes from every point on a loop and between points.""" - radius = abs(radius) - points = getPointsFromLoop( loop, radius, thresholdRatio ) - return getCircleNodesFromPoints( points, radius ) - -def getCircleNodesFromPoints(points, radius): - """Get the circle nodes from a path.""" - circleNodes = [] - oneOverRadius = 1.000001 / radius # to avoid problem of accidentally integral radius - points = euclidean.getAwayPoints(points, radius) - for point in points: - circleNodes.append(CircleNode(oneOverRadius, point)) - return circleNodes - -def getInsetLoopsFromLoop(loop, radius, thresholdRatio=0.9): - """Get the inset loops, which might overlap.""" - isInset = radius > 0 - insetLoops = [] - isLoopWiddershins = euclidean.isWiddershins(loop) - arounds = getAroundsFromLoop(loop, radius, thresholdRatio) - for around in arounds: - leftPoint = euclidean.getLeftPoint(around) - shouldBeWithin = (isInset == isLoopWiddershins) - if euclidean.isPointInsideLoop(loop, leftPoint) == shouldBeWithin: - if isLoopWiddershins != euclidean.isWiddershins(around): - around.reverse() - insetLoops.append(around) - return insetLoops - -def getInsetLoopsFromLoops(inset, loops): - """Get the inset loops, which might overlap.""" - insetLoops = [] - for loop in loops: - insetLoops += getInsetLoopsFromLoop(loop, inset) - return insetLoops - -def getInsetLoopsFromVector3Loop(loop, radius, thresholdRatio=0.9): - """Get the inset loops from vector3 loop, which might overlap.""" - if len(loop) < 2: - return [loop] - loopComplex = euclidean.getComplexPath(loop) - loopComplexes = getInsetLoopsFromLoop(loopComplex, radius) - return euclidean.getVector3Paths(loopComplexes, loop[0].z) - -def getInsetSeparateLoopsFromLoops(inset, loops, thresholdRatio=0.9): - """Get the separate inset loops.""" - isInset = inset > 0 - insetSeparateLoops = [] - radius = abs(inset) - arounds = getAroundsFromLoops(loops, radius, thresholdRatio) - for around in arounds: - leftPoint = euclidean.getLeftPoint(around) - if isInset == euclidean.getIsInFilledRegion(loops, leftPoint): - if isInset: - around.reverse() - insetSeparateLoops.append(around) - return insetSeparateLoops - -def getLargestCenterOutsetLoopFromLoop(loop, radius, thresholdRatio=0.9): - """Get the largest circle outset loop from the loop.""" - radius = abs(radius) - points = getPointsFromLoop(loop, 1.01 * radius, thresholdRatio) - centers = getCentersFromPoints(points, radius) - largestCenterOutset = None - largestOutsetArea = -987654321.0 - for center in centers: - outset = getSimplifiedInsetFromClockwiseLoop(center, radius) - if isLargeSameDirection(outset, center, radius): - if euclidean.isPathInsideLoop(loop, outset) != euclidean.isWiddershins(loop): - centerOutset = CenterOutset(center, outset) - outsetArea = abs(euclidean.getAreaLoop(outset)) - if outsetArea > largestOutsetArea: - largestOutsetArea = outsetArea - largestCenterOutset = centerOutset - if largestCenterOutset is None: - return None - largestCenterOutset.center = euclidean.getSimplifiedLoop(largestCenterOutset.center, radius) - return largestCenterOutset - -def getLargestCenterOutsetLoopFromLoopRegardless(loop, radius): - """Get the largest circle outset loop from the loop, even if the radius has to be shrunk and even if there is still no outset loop.""" - global globalDecreasingRadiusMultipliers - for decreasingRadiusMultiplier in globalDecreasingRadiusMultipliers: - decreasingRadius = radius * decreasingRadiusMultiplier - largestCenterOutsetLoop = getLargestCenterOutsetLoopFromLoop(loop, decreasingRadius) - if largestCenterOutsetLoop is not None: - return largestCenterOutsetLoop - return CenterOutset(loop, loop) - -def getLargestInsetLoopFromLoop(loop, radius): - """Get the largest inset loop from the loop.""" - loops = getInsetLoopsFromLoop(loop, radius) - return euclidean.getLargestLoop(loops) - -def getLargestInsetLoopFromLoopRegardless( loop, radius ): - """Get the largest inset loop from the loop, even if the radius has to be shrunk and even if there is still no inset loop.""" - global globalDecreasingRadiusMultipliers - for decreasingRadiusMultiplier in globalDecreasingRadiusMultipliers: - decreasingRadius = radius * decreasingRadiusMultiplier - largestInsetLoop = getLargestInsetLoopFromLoop( loop, decreasingRadius ) - if len( largestInsetLoop ) > 0: - return largestInsetLoop - print('This should never happen, there should always be a largestInsetLoop in getLargestInsetLoopFromLoopRegardless in intercircle.') - print(loop) - return loop - -def getLoopsFromLoopsDirection( isWiddershins, loops ): - """Get the loops going round in a given direction.""" - directionalLoops = [] - for loop in loops: - if euclidean.isWiddershins(loop) == isWiddershins: - directionalLoops.append(loop) - return directionalLoops - -def getPointsFromLoop(loop, radius, thresholdRatio=0.9): - """Get the points from every point on a loop and between points.""" - radius = abs(radius) - points = [] - for pointIndex in xrange(len(loop)): - pointBegin = loop[pointIndex] - pointEnd = loop[(pointIndex + 1) % len(loop)] - points.append( pointBegin ) - addPointsFromSegment( pointBegin, pointEnd, points, radius, thresholdRatio ) - return points - -def getPointsFromLoops(loops, radius, thresholdRatio=0.9): - """Get the points from every point on a loop and between points.""" - points = [] - for loop in loops: - points += getPointsFromLoop(loop, radius, thresholdRatio) - return points - -def getPointsFromPath(path, radius, thresholdRatio=0.9): - """Get the points from every point on a path and between points.""" - radius = abs(radius) - halfRadius = 0.5 * radius - points = [] - for pointIndex in xrange(len(path) - 1): - begin = path[pointIndex] - end = path[pointIndex + 1] - perpendicular = getWiddershinsByLength(begin, end, halfRadius) - if perpendicular is not None: - addPointsFromSegment(begin + perpendicular, end + perpendicular, points, radius, thresholdRatio) - addPointsFromSegment(begin - perpendicular, end - perpendicular, points, radius, thresholdRatio) - for pointIndex in xrange(1,len(path) - 1): - begin = path[pointIndex - 1] - center = path[pointIndex] - end = path[pointIndex + 1] - centerBegin = getWiddershinsByLength(center, begin, halfRadius) - centerEnd = getWiddershinsByLength(end, center, halfRadius) - if centerBegin is not None and centerEnd is not None: - centerPerpendicular = 0.5 * (centerBegin + centerEnd) - points.append(center + centerPerpendicular) - points.append(center - centerPerpendicular) - else: - points.append(center) - if len(path) > 1: - quarterRadius = 0.5 * halfRadius - addEndCap(path[0], path[1], points, halfRadius) - addEndCap(path[-1], path[-2], points, halfRadius) - else: - points.append(path[0]) - return points - -def getSimplifiedInsetFromClockwiseLoop(loop, radius): - """Get loop inset from clockwise loop, out from widdershins loop.""" - inset = [] - for pointIndex, begin in enumerate(loop): - center = loop[(pointIndex + 1) % len(loop)] - end = loop[(pointIndex + 2) % len(loop)] - addInsetPointFromClockwiseTriple(begin, center, end, inset, radius) - return getWithoutIntersections(euclidean.getSimplifiedLoop(inset, radius)) - -def getWiddershinsByLength(begin, end, length): - """Get the widdershins by length.""" - endMinusBegin = end - begin - endMinusBeginLength = abs(endMinusBegin) - if endMinusBeginLength <= 0.0: - return None - endMinusBegin *= length / endMinusBeginLength - return complex(-endMinusBegin.imag, endMinusBegin.real) - -def getWithoutIntersections( loop ): - """Get loop without intersections.""" - lastLoopLength = len( loop ) - while lastLoopLength > 3: - removeIntersection( loop ) - if len( loop ) == lastLoopLength: - return loop - lastLoopLength = len( loop ) - return loop - -def isLargeSameDirection( inset, loop, radius ): - """Determine if the inset is in the same direction as the loop and it is large enough.""" - if euclidean.isWiddershins(inset) != euclidean.isWiddershins(loop): - return False - return euclidean.getMaximumSpan(inset) > 2.01 * abs(radius) - -def isLoopIntersectingLoop( anotherLoop, loop ): - """Determine if the a loop is intersecting another loop.""" - for pointIndex in xrange(len(loop)): - pointFirst = loop[pointIndex] - pointSecond = loop[(pointIndex + 1) % len(loop)] - segment = pointFirst - pointSecond - normalizedSegment = euclidean.getNormalized(segment) - segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) - segmentFirstPoint = segmentYMirror * pointFirst - segmentSecondPoint = segmentYMirror * pointSecond - if euclidean.isLoopIntersectingInsideXSegment( anotherLoop, segmentFirstPoint.real, segmentSecondPoint.real, segmentYMirror, segmentFirstPoint.imag ): - return True - return False - -def orbitsAreLarge( loop, temperatureChangeTime ): - """Determine if the orbits are large enough.""" - if len(loop) < 1: - print('Zero length loop which was skipped over, this should never happen.') - return False - return temperatureChangeTime > 1.5 - -def removeIntersection( loop ): - """Get loop without the first intersection.""" - for pointIndex, ahead in enumerate(loop): - behind = loop[ ( pointIndex + len( loop ) - 1 ) % len( loop ) ] - behindEnd = loop[ ( pointIndex + len( loop ) - 2 ) % len( loop ) ] - behindMidpoint = 0.5 * ( behind + behindEnd ) - aheadEnd = loop[ (pointIndex + 1) % len( loop ) ] - aheadMidpoint = 0.5 * ( ahead + aheadEnd ) - normalizedSegment = behind - behindMidpoint - normalizedSegmentLength = abs( normalizedSegment ) - if normalizedSegmentLength > 0.0: - normalizedSegment /= normalizedSegmentLength - segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) - behindRotated = segmentYMirror * behind - behindMidpointRotated = segmentYMirror * behindMidpoint - aheadRotated = segmentYMirror * ahead - aheadMidpointRotated = segmentYMirror * aheadMidpoint - y = behindRotated.imag - xIntersection = euclidean.getXIntersectionIfExists( aheadRotated, aheadMidpointRotated, y ) - if xIntersection is not None: - if xIntersection > min( behindMidpointRotated.real, behindRotated.real ) and xIntersection < max( behindMidpointRotated.real, behindRotated.real ): - intersectionPoint = normalizedSegment * complex( xIntersection, y ) - loop[ ( pointIndex + len( loop ) - 1 ) % len( loop ) ] = intersectionPoint - del loop[pointIndex] - return - - -class BoundingLoop: - """A class to hold a bounding loop composed of a minimum complex, a maximum complex and an outset loop.""" - def __eq__(self, other): - """Determine whether this bounding loop is identical to other one.""" - if other is None: - return False - return self.minimum == other.minimum and self.maximum == other.maximum and self.loop == other.loop - - def __repr__(self): - """Get the string representation of this bounding loop.""" - return '%s, %s, %s' % ( self.minimum, self.maximum, self.loop ) - - def getFromLoop( self, loop ): - """Get the bounding loop from a path.""" - self.loop = loop - self.maximum = euclidean.getMaximumByComplexPath(loop) - self.minimum = euclidean.getMinimumByComplexPath(loop) - return self - - def getOutsetBoundingLoop( self, outsetDistance ): - """Outset the bounding rectangle and loop by a distance.""" - outsetBoundingLoop = BoundingLoop() - outsetBoundingLoop.maximum = self.maximum + complex( outsetDistance, outsetDistance ) - outsetBoundingLoop.minimum = self.minimum - complex( outsetDistance, outsetDistance ) - greaterThanOutsetDistance = 1.1 * outsetDistance - centers = getCentersFromLoopDirection( True, self.loop, greaterThanOutsetDistance ) - outsetBoundingLoop.loop = getSimplifiedInsetFromClockwiseLoop( centers[0], outsetDistance ) - return outsetBoundingLoop - - def isEntirelyInsideAnother( self, anotherBoundingLoop ): - """Determine if this bounding loop is entirely inside another bounding loop.""" - if self.minimum.imag < anotherBoundingLoop.minimum.imag or self.minimum.real < anotherBoundingLoop.minimum.real: - return False - if self.maximum.imag > anotherBoundingLoop.maximum.imag or self.maximum.real > anotherBoundingLoop.maximum.real: - return False - for point in self.loop: - if euclidean.getNumberOfIntersectionsToLeft( anotherBoundingLoop.loop, point ) % 2 == 0: - return False - return not isLoopIntersectingLoop( anotherBoundingLoop.loop, self.loop ) #later check for intersection on only acute angles - - def isOverlappingAnother( self, anotherBoundingLoop ): - """Determine if this bounding loop is intersecting another bounding loop.""" - if self.isRectangleMissingAnother( anotherBoundingLoop ): - return False - for point in self.loop: - if euclidean.getNumberOfIntersectionsToLeft( anotherBoundingLoop.loop, point ) % 2 == 1: - return True - for point in anotherBoundingLoop.loop: - if euclidean.getNumberOfIntersectionsToLeft( self.loop, point ) % 2 == 1: - return True - return isLoopIntersectingLoop( anotherBoundingLoop.loop, self.loop ) #later check for intersection on only acute angles - - def isOverlappingAnotherInList( self, boundingLoops ): - """Determine if this bounding loop is intersecting another bounding loop in a list.""" - for boundingLoop in boundingLoops: - if self.isOverlappingAnother( boundingLoop ): - return True - return False - - def isRectangleMissingAnother( self, anotherBoundingLoop ): - """Determine if the rectangle of this bounding loop is missing the rectangle of another bounding loop.""" - if self.maximum.imag < anotherBoundingLoop.minimum.imag or self.maximum.real < anotherBoundingLoop.minimum.real: - return True - return self.minimum.imag > anotherBoundingLoop.maximum.imag or self.minimum.real > anotherBoundingLoop.maximum.real - - -class CenterOutset: - """A class to hold a center and an outset.""" - def __init__(self, center, outset): - """Set the center and outset.""" - self.center = center - self.outset = outset - - def __repr__(self): - """Get the string representation of this CenterOutset.""" - return '%s\n%s' % (self.center, self.outset) - - -class CircleIntersection: - """An intersection of two complex circles.""" - def __init__( self, circleNodeAhead, index, circleNodeBehind ): - self.aheadMinusBehind = 0.5 * ( circleNodeAhead.dividedPoint - circleNodeBehind.dividedPoint ) - self.circleNodeAhead = circleNodeAhead - self.circleNodeBehind = circleNodeBehind - self.index = index - self.steppedOn = False - demichordWidth = math.sqrt( 1.0 - self.aheadMinusBehind.real * self.aheadMinusBehind.real - self.aheadMinusBehind.imag * self.aheadMinusBehind.imag ) - rotatedClockwiseQuarter = complex( self.aheadMinusBehind.imag, - self.aheadMinusBehind.real ) - rotatedClockwiseQuarterLength = abs( rotatedClockwiseQuarter ) - if rotatedClockwiseQuarterLength == 0: - print('this should never happen, rotatedClockwiseQuarter in getDemichord in intercircle is 0') - print( circleNodeAhead.dividedPoint ) - print( circleNodeBehind.dividedPoint ) - self.demichord = 0.0 - else: - self.demichord = rotatedClockwiseQuarter * demichordWidth / rotatedClockwiseQuarterLength - self.positionRelativeToBehind = self.aheadMinusBehind + self.demichord - - def __repr__(self): - """Get the string representation of this CircleIntersection.""" - return '%s, %s, %s, %s' % (self.index, self.getAbsolutePosition(), self.circleNodeBehind, self.circleNodeAhead) - - def addToList( self, circleIntersectionPath ): - """Add this to the circle intersection path, setting stepped on to be true.""" - self.steppedOn = True - circleIntersectionPath.append(self) - - def getAbsolutePosition(self): - """Get the absolute position.""" - return self.positionRelativeToBehind + self.circleNodeBehind.dividedPoint - - def getCircleIntersectionAhead(self): - """Get the first circle intersection on the circle node ahead.""" - circleIntersections = self.circleNodeAhead.circleIntersections - circleIntersectionAhead = None - largestDot = -912345678.0 - for circleIntersection in circleIntersections: - if not circleIntersection.steppedOn: - circleIntersectionRelativeToMidpoint = euclidean.getNormalized(circleIntersection.positionRelativeToBehind + self.aheadMinusBehind) - dot = euclidean.getDotProduct(self.demichord, circleIntersectionRelativeToMidpoint) - if dot > largestDot: - largestDot = dot - circleIntersectionAhead = circleIntersection - if circleIntersectionAhead is None: - print('Warning, circleIntersectionAhead in getCircleIntersectionAhead in intercircle is None for:') - print(self.circleNodeAhead.dividedPoint) - print('circleIntersectionsAhead') - for circleIntersection in circleIntersections: - print(circleIntersection.circleNodeAhead.dividedPoint) - print('circleIntersectionsBehind') - for circleIntersection in self.circleNodeBehind.circleIntersections: - print(circleIntersection.circleNodeAhead.dividedPoint) - print('This may lead to a loop not being sliced.') - print('If this is a problem, you may as well send a bug report, even though I probably can not fix this particular problem.') - return circleIntersectionAhead - - def isWithinCircles(self, pixelTable): - """Determine if this circle intersection is within the circle node circles.""" - absolutePosition = self.getAbsolutePosition() - squareValues = euclidean.getSquareValuesFromPoint(pixelTable, absolutePosition) - for squareValue in squareValues: - if abs(squareValue.dividedPoint - absolutePosition) < 1.0: - if squareValue != self.circleNodeAhead and squareValue != self.circleNodeBehind: - return True - return False - - -class CircleNode: - """A complex node of complex circle intersections.""" - def __init__(self, oneOverRadius, point): - self.actualPoint = point - self.circleIntersections = [] - self.dividedPoint = point * oneOverRadius -# self.index = index # when debugging bring back index - - def __repr__(self): - """Get the string representation of this CircleNode.""" -# return '%s, %s, %s' % (self.index, self.dividedPoint, len(self.circleIntersections)) # when debugging bring back index - return '%s, %s' % (self.dividedPoint, len(self.circleIntersections)) - - def getWithinNodes(self, pixelTable): - """Get the nodes this circle node is within.""" - withinNodes = [] - squareValues = euclidean.getSquareValuesFromPoint(pixelTable, 0.5 * self.dividedPoint) - for squareValue in squareValues: - if abs(self.dividedPoint - squareValue.dividedPoint) < 2.0: - withinNodes.append(squareValue) - return withinNodes diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Drill.bsh b/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Drill.bsh deleted file mode 100644 index 413891a..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Drill.bsh +++ /dev/null @@ -1,203 +0,0 @@ -/* - - - -*/ -scene = window.getScene(); - -shapeChoice = new BComboBox (new String [] { - "Round", "Hex (point down)", "Hex (flat down)" }); -slopeField = new ValueField (45, ValueField.POSITIVE); -sizeField = new ValueField (10, ValueField.POSITIVE); -lengthField = new ValueField (20, ValueField.POSITIVE); -errorField = new ValueField (0.05, ValueField.POSITIVE); - -dlg = new ComponentsDialog (window, "Drill Tool", - new Widget [] {shapeChoice, slopeField, sizeField, lengthField, errorField}, - new String [] {"Shape:", "Max slope:", "Size:", "Length:", "Max error:"}); -if (!dlg.clickedOk()) { return; } - -shape = shapeChoice.getSelectedIndex(); -double theta, size, length, maxError; -theta = slopeField.getValue() * Math.PI / 180.0; -size = sizeField.getValue(); -length = lengthField.getValue(); -maxError = errorField.getValue(); -name = ""; - -double phi, angle; -switch (shape) -{ - case 0: // round - { - radius = size / 2; - errorAngle = Math.acos((radius - maxError) / radius); - numberSides = Math.ceil((Math.PI + 2 * theta) / errorAngle); - phi = (Math.PI + 2 * theta) / (numberSides - 2); - angle = ((Math.PI / 2.0) - theta); - y0 = radius / Math.sin(theta); - - name = "Teardrop"; - break; - } - case 1: // hex, point down - { - if (theta > (Math.PI / 3.0)) { theta = Math.PI / 3.0; } - radius = size / Math.sqrt(3); - numberSides = 6; - phi = Math.PI / 3.0; - angle = Math.PI / 3.0; - y0 = (radius / 2.0) + (size / (2.0 * Math.tan(theta))); - smooth = Mesh.NO_SMOOTHING; - - name = "Hexdrop(pointy)"; - break; - } - case 2: // hex, flat down - { - radius = size / Math.sqrt(3); - phi = Math.PI / 3.0; - y0 = radius / Math.tan(theta); - if (theta <= (Math.PI / 6.0)) - { - numberSides = 5; - angle = Math.PI / 2.0; - } - else - { - numberSides = 7; - angle = Math.PI / 6.0; - y0 += size; - y0 /= 2; - } - smooth = Mesh.NO_SMOOTHING; - - name = "Hexdrop(flat)"; - break; - } -} -name += " size " + size; - -// number of faces: -// for each edge in our perimeter, two triangles to connect -// the front and back, so 2*numberSides -// for each end cap, we connect each vertex to the point. The -// first and last vertices are connected by a perimeter edge, -// leaving numberSides-2 edges to connect across the middle, -// creating a face, for numberSides-2 triangles per end cap, -// or (numberSides-2)*2 triangles for both end caps -// Thus: -// 2*numberSides + 2*(numberSides-2) -// 2*numberSides + 2*numberSides - 4 -// 4*numberSides - 4 -Vec3[] v = new Vec3[numberSides * 2]; -int[][] faces = new int[4*numberSides-4][3]; -v[0] = new Vec3(0, y0, 0); -v[1] = new Vec3(0, y0, -length); -for (i = 0; i < (numberSides - 1); i++) -{ - j = i * 2; - x = Math.sin(angle + phi * i); - y = Math.cos(angle + phi * i); - v[j+2] = new Vec3(x, y, 0); - v[j+2].scale (radius); - v[j+3] = new Vec3(x, y, -length/radius); - v[j+3].scale (radius); - - faces[j][0] = j; - faces[j][1] = j+2; - faces[j][2] = j+1; - faces[j+1][0] = j+1; - faces[j+1][1] = j+2; - faces[j+1][2] = j+3; -} -//j = (numberSides-1)*2; -j = i*2; -faces[j][0] = 0; -faces[j][1] = j+1; -faces[j][2] = j; -faces[j+1][0] = 0; -faces[j+1][1] = 1; -faces[j+1][2] = j+1; - -k = j; - -for (i = 1; i < (numberSides - 1); i++) -{ - j = i * 2; - faces[j+k][0] = 0; - faces[j+k][1] = j+2; - faces[j+k][2] = j; - faces[j+k+1][0] = 1; - faces[j+k+1][1] = j+1; - faces[j+k+1][2] = j+3; -} - -mesh = new TriangleMesh (v, faces); -mesh.setSmoothingMethod(Mesh.NO_SMOOTHING); - -/* -// At this point, we've finished constructing the mesh. Now we need -// to set its smoothing properly. -if (shape != 0) // hex -{ - mesh.setSmoothingMethod(Mesh.NO_SMOOTHING); -} -else // round -{ - mesh.setSmoothingMethod(Mesh.APPROXIMATING); - edge = mesh.getEdges(); - face = mesh.getFaces(); - vert = mesh.getVertices(); - cutoffAngle = (theta < (Math.PI/4.0))?(theta*2.0):(Math.PI/2.0); - cutoff = Math.cos (cutoffAngle); - for (int i = 0; i < edge.length; i++) - { - ed = edge[i]; - f1 = face[ed.f1]; - f2 = face[ed.f2]; - norm1 = vert[f1.v1].r.minus(vert[f1.v2].r).cross(vert[f1.v1].r.minus(vert[f1.v3].r)); - norm2 = vert[f2.v1].r.minus(vert[f2.v2].r).cross(vert[f2.v1].r.minus(vert[f2.v3].r)); - norm1.normalize(); - norm2.normalize(); - ed.smoothness = (norm1.dot(norm2) < cutoff)?0.0f:1.0f; - } -} -*/ -window.addObject (mesh, new CoordinateSystem(), name, null); -undo = new UndoRecord (window, false, UndoRecord.DELETE_OBJECT, new Object[] { new Integer(window.getScene().getNumObjects()-1) }); -window.setUndoRecord (undo); diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Export GNU Triangulated Surface.bsh b/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Export GNU Triangulated Surface.bsh deleted file mode 100644 index bf66f5a..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Export GNU Triangulated Surface.bsh +++ /dev/null @@ -1,499 +0,0 @@ -/* - - - -*/ -//later once stable remove unused preferences, all the preferences will be kept in the unused Skeinforge, finish comments for this and import -/** -Get the info for all the selected curves and meshes. -*/ - -ObjectInfo[] getCurvesMeshesInfo() -{ - scene = window.getScene(); - selection = scene.getSelection(); - Vector objectInfoVector = new Vector(); - - for ( int objectIndex = 0; objectIndex < selection.length; objectIndex++ ) { - objectInfo = scene.getObject( selection[ objectIndex ] ); - - if ( objectInfo.object instanceof TriangleMesh ) { - objectInfoVector.add( objectInfo ); - } - } - - if ( objectInfoVector.size() > 0 ) { - return objectInfoVector.toArray( new ObjectInfo[ objectInfoVector.size() ] ); - } - - for ( int objectIndex = 0; objectIndex < scene.getNumObjects(); objectIndex++ ) { - objectInfo = scene.getObject( objectIndex ); - - if ( objectInfo.object instanceof TriangleMesh ) { - return new ObjectInfo[] { objectInfo }; - } - } - - return new ObjectInfo[ 0 ]; -} - -String getEdgeString( edges, edgeTriple, vertexIndexFirst, vertexIndexSecond ) -{ - for ( int edgeTripleIndex = 0; edgeTripleIndex < edgeTriple.length; edgeTripleIndex++ ) { - edgeIndex = edgeTriple[ edgeTripleIndex ]; - edge = edges[ edgeIndex ]; - - if ( edge.v1 == vertexIndexFirst && edge.v2 == vertexIndexSecond ) { - return getPlusOneToString( edgeIndex ); - } - - if ( edge.v1 == vertexIndexSecond && edge.v2 == vertexIndexFirst ) { - return getPlusOneToString( edgeIndex ); - } - } - - print( "Inconsistent triangle mesh." ); - print( edgeTriple ); - print( vertexIndexFirst ); - print( vertexIndexSecond ); -} - -String getPlusOneToString( int number ) -{ - return ( number + 1 ).toString() ; -} - -/** -Get Vec3 rotated around X axis from counterclockwise angle and vector. - -@param angle counterclockwise angle from 1, 0 -@param vector3 Vec3 whose rotation will be returned -@return vector3 rotated around X axis -*/ - -Vec3 getRoundXAxis( double angle, Vec3 vector3 ) -{ - x = Math.cos( angle ); - y = Math.sin( angle ); - - return new Vec3( vector3.x, vector3.y * x - vector3.z * y, vector3.y * y + vector3.z * x ); -} - -/** -Get Vec3 rotated around Y axis from counterclockwise angle and vector. - -@param angle counterclockwise angle from 1, 0 -@param vector3 Vec3 whose rotation will be returned -@return vector3 rotated around Y axis -*/ - -Vec3 getRoundYAxis( double angle, Vec3 vector3 ) -{ - x = Math.cos( angle ); - y = Math.sin( angle ); - - return new Vec3( vector3.x * x - vector3.z * y, vector3.y, vector3.x * y + vector3.z * x ); -} - -/** -Get Vec3 rotated around Z axis from counterclockwise angle and vector. - -@param angle counterclockwise angle from 1, 0 -@param vector3 Vec3 whose rotation will be returned -@return vector3 rotated around Z axis -*/ - -Vec3 getRoundZAxis( double angle, Vec3 vector3 ) -{ - x = Math.cos( angle ); - y = Math.sin( angle ); - - return new Vec3( vector3.x * x - vector3.y * y, vector3.x * y + vector3.y * x, vector3.z ); -} - -/** -Output the curves and/or meshes. -*/ - -void outputCurvesMeshes( ObjectInfo[] objectInfoArray ) -{ - if ( objectInfoArray.length < 1 ) { - return; - } - - for ( int objectIndex = 0; objectIndex < objectInfoArray.length; objectIndex++ ) { - objectInfo = objectInfoArray[ objectIndex ]; - - if ( objectInfoArray.length > 1 && exportSelectionCheckbox.getState() ) { - - if ( bufferedWriter != null ) { - //Close the output stream - bufferedWriter.close(); - bufferedWriter = null; - } - - file = null; - parentFile = new File( gnuSurfaceFilenameTextField.getText() ).getParentFile(); - - if ( parentFile != null ) { - file = new File( parentFile, objectInfo.name + ".gts" ); - } - - if ( file != null ) { - bufferedWriter = new BufferedWriter( new FileWriter( file ) ); - } - } - - if ( file != null && bufferedWriter != null ) { - print( objectInfo.name + " is being saved as the GNU Triangulated Surface file " + file.getAbsolutePath() ); - } - - outputCurveMesh( objectInfo ); - - if ( bufferedWriter != null ) { - //Close the output stream - bufferedWriter.close(); - bufferedWriter = null; - } - } -} - -/** -Output the curve and/or mesh. -Quoted from http://gts.sourceforge.net/reference/gts-surfaces.html#GTS-SURFACE-WRITE -"All the lines beginning with GTS_COMMENTS (#!) are ignored. The first line contains three unsigned integers separated by spaces. The first integer is the number of vertices, nv, the second is the number of edges, ne and the third is the number of faces, nf. - -Follows nv lines containing the x, y and z coordinates of the vertices. Follows ne lines containing the two indices (starting from one) of the vertices of each edge. Follows nf lines containing the three ordered indices (also starting from one) of the edges of each face. - -The format described above is the least common denominator to all GTS files. Consistent with an object-oriented approach, the GTS file format is extensible. Each of the lines of the file can be extended with user-specific attributes accessible through the read() and write() virtual methods of each of the objects written (surface, vertices, edges or faces). When read with different object classes, these extra attributes are just ignored." -*/ - -void outputCurveMesh( ObjectInfo objectInfo ) -{ - triangleMesh = objectInfo.object; - edges = triangleMesh.getEdges(); - faces = triangleMesh.getFaces(); - vertexPositions = triangleMesh.getVertexPositions(); - origin = objectInfo.coords.getOrigin(); - orientation = objectInfo.coords.getRotationAngles(); - orientationXRadians = orientation[ 0 ] * Math.PI / 180.0; - orientationYRadians = orientation[ 1 ] * Math.PI / 180.0; - orientationZRadians = orientation[ 2 ] * Math.PI / 180.0; - outputString( vertexPositions.length + " " + edges.length + " " + faces.length + " Number of Vertices, Number of Edges, Number of Faces" ); - - for ( int vertexIndex = 0; vertexIndex < vertexPositions.length; vertexIndex++ ) { - vertexPosition = vertexPositions[ vertexIndex ]; - vertexPosition = getRoundZAxis( - orientationZRadians, vertexPosition ); - vertexPosition = getRoundXAxis( - orientationXRadians, vertexPosition ); - vertexPosition = getRoundYAxis( orientationYRadians, vertexPosition ); - vertexPosition.add( origin ); - vertexLine = vertexPosition.x.toString() + " " + vertexPosition.y.toString() + " " + vertexPosition.z.toString(); - - if ( vertexIndex == 0 ) { - vertexLine += " Vertex Coordinates XYZ"; - } - - outputString( vertexLine ); - } - - for ( int edgeIndex = 0; edgeIndex < edges.length; edgeIndex++ ) { - edge = edges[ edgeIndex ]; - edgeLine = getPlusOneToString( edge.v1 ) + " " + getPlusOneToString( edge.v2 ); - - if ( edgeIndex == 0 ) { - edgeLine += " Edge Vertex Indices Starting from 1"; - } - - outputString( edgeLine ); - } - - for ( int faceIndex = 0; faceIndex < faces.length; faceIndex++ ) { - face = faces[ faceIndex ]; - int[] edgeTriple = { face.e1, face.e2, face.e3 }; - - faceLine = getEdgeString( edges, edgeTriple, face.v1, face.v2 ) + " " + getEdgeString( edges, edgeTriple, face.v2, face.v3 ) + " " + getEdgeString( edges, edgeTriple, face.v3, face.v1 ); - - if ( faceIndex == 0 ) { - faceLine += " Face Edge Indices Starting from 1"; - } - - outputString( faceLine ); - } -} - -/** -Output comma separated strings followed by a linefeed. -*/ - -void outputString( string ) -{ - if ( printSelectionCheckbox.getState() ) { - print( string ); - } - - if ( bufferedWriter != null ) { - bufferedWriter.write( string.replace( ", ", "," ) + "\n" ); - } -} - -/** -Add radio button groups to the preference widgets. - -@param radioButtonGroups radio button groups which will be added to the memorable widgets -@param widgetVector memorable widgets -*/ - -void preferencesAddRadioButtonGroups( RadioButtonGroup[] radioButtonGroups, Vector widgetVector ) -{ - for ( int radioIndex = 0; radioIndex < radioButtonGroups.length; radioIndex++ ) { - radioButtonGroup = radioButtonGroups[ radioIndex ]; - radioButtonGroupIterator = radioButtonGroup.getRadioButtons(); - - while ( radioButtonGroupIterator.hasNext() ) { - radioButton = radioButtonGroupIterator.next(); - preferencesAddWidgetWithString( radioButton, radioButton.getText(), widgetVector ); - } - } -} - -/** -Add widgets which have titles. - -@param widgets widgets which have titles -@param widgetStrings widget titles -@param widgetVector memorable widgets -*/ - -void preferencesAddWidgetsWithStrings( Widget[] widgets, String[] widgetStrings, Vector widgetVector ) -{ - for ( int widgetIndex = 0; widgetIndex < widgets.length; widgetIndex++ ) { - widget = widgets[ widgetIndex ]; - - if ( widget instanceof BCheckBox || widget instanceof BOutline || widget instanceof BTextField || widget instanceof ValueField ) { - preferencesAddWidgetWithString( widget, widgetStrings[ widgetIndex ], widgetVector ); - } - } -} - -/** -Give the widget a name and add it to the widget vector. - -@param widget widget which will be given a name -@param widgetStrings widget name -@param widgetVector memorable widgets -*/ - -void preferencesAddWidgetWithString( Widget widget, String widgetString, Vector widgetVector ) -{ - widget.setName( widgetString ); - widgetVector.add( widget ); -} - -/** -Read widget settings from preferences file. - -@param preferencesFilename preferences filename -@param widgetVector memorable widgets -*/ - -void preferencesRead( String preferencesFilename, Vector widgetVector ) -{ - preferencesFile = new File( preferencesFilename ); - - if ( !preferencesFile.canRead() ) { - return; - } - - BufferedReader preferencesReader = new BufferedReader( new FileReader( preferencesFile ) ); - - line = preferencesReader.readLine(); - - while ( line != null ) { - preferencesReadLine( line, widgetVector ); - line = preferencesReader.readLine(); - } -} - -/** -Read line of preferences and set widget to that line. - -@param line line of preferences -@param widgetVector memorable widgets -*/ - -void preferencesReadLine( String line, Vector widgetVector ) -{ - splitLine = line.split( "\t" ); - - if ( splitLine.length < 2 ) { - return; - } - - name = splitLine[ 0 ]; - - for ( int widgetIndex = 0; widgetIndex < widgetVector.size(); widgetIndex++ ) { - widget = widgetVector.elementAt( widgetIndex ); - - if ( widget.getName().equals( name ) ) { - preferencesReadWidget( splitLine[ 1 ], widget ); - - return; - } - } -} - -/** -Set widget to preferences value. - -@param value preferences value -@param widget widget to be set to value -*/ - -void preferencesReadWidget( String value, Widget widget ) -{ - if ( widget instanceof BCheckBox || widget instanceof BRadioButton ) { - widget.setState( Boolean.valueOf( value ) ); - - return; - } - - if ( widget instanceof BOutline ) { // it would be better to save the value instead of index because the list might change, but I'm lazy - bList = widget.getContent().getContent(); - selectedIndex = Integer.valueOf( value ); - bList.setSelected( selectedIndex, true ); - bList.scrollToItem( selectedIndex ); - - return; - } - - if ( widget instanceof BTextField ) { - widget.setText( value ); - - return; - } - - if ( widget instanceof ValueField ) { - widget.setValue( Double.valueOf( value ) ); - } -} - -/** -Write widget settings to preferences file. - -@param preferencesFilename preferences filename -@param widgetVector memorable widgets -*/ - -void preferencesWrite( String preferencesFilename, Vector widgetVector ) -{ - preferencesFile = new File( preferencesFilename ); - - if ( preferencesFile == null ) { - print( "Can not write preferences to " + preferencesFilename ); - - return; - } - - BufferedWriter preferencesWriter = new BufferedWriter( new FileWriter( preferencesFile ) ); - - for ( int widgetIndex = 0; widgetIndex < widgetVector.size(); widgetIndex++ ) { - widget = widgetVector.elementAt( widgetIndex ); - preferencesWriteWidget( preferencesWriter, widget ); - } - - //Close the output stream - preferencesWriter.close(); -} - -/** -Write widget settings to line of preferences. - -@param preferencesWriter buffered preferences file writer -@param widget widget to be written -*/ - -void preferencesWriteWidget( BufferedWriter preferencesWriter, Widget widget ) -{ - widgetString = widget.getName() + "\t"; - - if ( widget instanceof BCheckBox || widget instanceof BRadioButton ) { - preferencesWriter.write( widgetString + widget.getState().toString() + "\n" ); - - return; - } - - if ( widget instanceof BOutline ) { // it would be better to save the value because the list might change, but I'm lazy - BList bList = widget.getContent().getContent(); - bList = widget.getContent().getContent(); - preferencesWriter.write( widgetString + bList.getSelectedIndex().toString() + "\n" ); - - return; - } - - if ( widget instanceof BTextField ) { - preferencesWriter.write( widgetString + widget.getText() + "\n" ); - - return; - } - - if ( widget instanceof ValueField ) { - preferencesWriter.write( widgetString + widget.getValue().toString() + "\n" ); - } -} - -// Set default parameters. -bufferedWriter = null; -exportSelectionCheckbox = new BCheckBox( "", false ); -file = null; -gnuSurfaceFilenameTextField = new BTextField( "triangle_mesh.gts" ); -String preferencesFilename = "gnu_triangulated_surface_preferences.csv"; -printSelectionCheckbox = new BCheckBox( "", true ); - -Widget[] widgets = new Widget[] { exportSelectionCheckbox, - printSelectionCheckbox }; - -String[] widgetStrings = new String[] { "Export Selection:", - "Print Selection:" }; - -// change the user interface parameters from default to preferences -Vector widgetVector = new Vector(); -preferencesAddWidgetsWithStrings( widgets, widgetStrings, widgetVector ); -preferencesAddWidgetWithString( gnuSurfaceFilenameTextField, "GNU Triangulated Surface Filename:", widgetVector ); -preferencesRead( preferencesFilename, widgetVector ); - -curvesMeshesInfo = getCurvesMeshesInfo(); - -if ( curvesMeshesInfo.length < 1 ) { - print( "There is no triangle mesh in the scene, so nothing will be done." ); - print( "It may be that there is a solid shape which is not a triangle mesh, in which case convert that shape to a triangle mesh." ); - - return; -} - -dialog = new ComponentsDialog( window, "Export and/or Print Selection", widgets, widgetStrings ); - -if ( !dialog.clickedOk() ) return; - -if ( exportSelectionCheckbox.getState() ) { - fileDescriptor = new BFileChooser( BFileChooser.SAVE_FILE, "Select name for the GNU Triangulated Surface file."); - fileDescriptor.setSelectedFile( new File( gnuSurfaceFilenameTextField.getText() ) ); - fileDescriptor.showDialog( window ); - file = fileDescriptor.getSelectedFile(); - - if ( file != null ) { - gnuSurfaceFilenameTextField.setText( file.getAbsolutePath() ); - bufferedWriter = new BufferedWriter( new FileWriter( file ) ); - } -} - -preferencesWrite( preferencesFilename, widgetVector ); -outputCurvesMeshes( curvesMeshesInfo ); diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Export Topology.bsh b/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Export Topology.bsh deleted file mode 100644 index d2a2050..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Export Topology.bsh +++ /dev/null @@ -1,170 +0,0 @@ -/* - - - -*/ - -/** -Get the info for all the selected curves and meshes. -*/ - -ObjectInfo[] getCurvesMeshesInfo() -{ - scene = window.getScene(); - selection = scene.getSelection(); - Vector objectInfoVector = new Vector(); - - for ( int objectIndex = 0; objectIndex < selection.length; objectIndex++ ) { - objectInfo = scene.getObject( selection[ objectIndex ] ); - - if ( objectInfo.object instanceof Curve || objectInfo.object instanceof TriangleMesh ) { - objectInfoVector.add( objectInfo ); - } - } - - if ( objectInfoVector.size() > 0 ) { - return objectInfoVector.toArray( new ObjectInfo[ objectInfoVector.size() ] ); - } - - for ( int objectIndex = 0; objectIndex < scene.getNumObjects(); objectIndex++ ) { - objectInfo = scene.getObject( objectIndex ); - - if ( objectInfo.object instanceof Curve || objectInfo.object instanceof TriangleMesh ) { - return new ObjectInfo[] { objectInfo }; - } - } - - return new ObjectInfo[ 0 ]; -} - -/** -Output the curves and/or meshes. -*/ - -void outputCurvesMeshes( ObjectInfo[] objectInfoArray ) -{ - if ( objectInfoArray.length < 1 ) { - return; - } - - outputCurveMesh( objectInfoArray[ 0 ] ); - - for ( int objectIndex = 1; objectIndex < objectInfoArray.length; objectIndex++ ) { - outputString( "" ); - outputCurveMesh( objectInfoArray[ objectIndex ] ); - } - - if ( bufferedWriter != null ) { - //Close the output stream - bufferedWriter.close(); - } -} - -/** -Output the curve and/or mesh. -*/ - -void outputCurveMesh( ObjectInfo objectInfo ) -{ - className = objectInfo.object.getClass().getName(); - classNameEnd = className.substring( className.lastIndexOf( "." ) + 1 ); - outputString( "Class, " + classNameEnd ); - outputString( "Name, " + objectInfo.name ); - origin = objectInfo.coords.getOrigin(); - outputString( "Origin, Vector (xyz), " + origin.x + ", " + origin.y + ", " + origin.z ); - orientation = objectInfo.coords.getRotationAngles(); - outputString( "Orientation, Vector (xyz), " + orientation[ 0 ] + ", " + orientation[ 1 ] + ", " + orientation[ 2 ] ); - outputVertexPositions( objectInfo ); - - if ( objectInfo.object instanceof Curve ) { - return; - } - - outputString( "Faces, Face Index, Vertex 1, Vertex 2, Vertex 3" ); - faces = objectInfo.object.getFaces(); - - for ( int faceIndex = 0; faceIndex < faces.length; faceIndex++ ) { - face = faces[ faceIndex ]; - outputString( "Face, " + faceIndex.toString() + ", " + face.v1 + ", " + face.v2 + ", " + face.v3 ); - } - - outputString( "Edges, Edge Index, Face 1, Face 2, Smoothness, Vertex 1, Vertex 2" ); - edges = objectInfo.object.getEdges(); - - for ( int edgeIndex = 0; edgeIndex < edges.length; edgeIndex++ ) { - edge = edges[ edgeIndex ]; - outputString( "Edge, " + edgeIndex.toString() + ", " + edge.f1 + ", " + edge.f2 + ", " + edge.smoothness + ", " + edge.v1 + ", " + edge.v2 ); - } -} - -/** -Output comma separated strings followed by a linefeed. -*/ - -void outputString( string ) -{ - if ( printSelection.getState() || exportPrintSelection.getState() ) { - print( string ); - } - - if ( bufferedWriter != null ) { - bufferedWriter.write( string.replace( ", ", "," ) + "\n" ); - } -} - -/** -Output the vertex positions. -*/ - -void outputVertexPositions( ObjectInfo objectInfo ) -{ - outputString( "VertexPositions, Vertex Index, x, y, z" ); - vertexPositions = objectInfo.object.getVertexPositions(); - - for ( int vertexIndex = 0; vertexIndex < vertexPositions.length; vertexIndex++ ) { - vertexPosition = vertexPositions[ vertexIndex ]; - outputString( "Vertex Position, " + vertexIndex.toString() + ", " + vertexPosition.x + ", " + vertexPosition.y + ", " + vertexPosition.z ); - } -} - -// Get parameters. - -actionRadioButtonGroup = new RadioButtonGroup(); -exportSelection = new BRadioButton( "Export Selection", false, actionRadioButtonGroup ); -exportPrintSelection = new BRadioButton( "Export and Print Selection", true, actionRadioButtonGroup ); -printSelection = new BRadioButton( "Print Selection", false, actionRadioButtonGroup ); -actionGridContainer = new GridContainer( 1, 3 ); -actionGridContainer.setDefaultLayout( new LayoutInfo( LayoutInfo.WEST, LayoutInfo.NONE, new Insets( 2, 2, 2, 2 ), null ) ); -actionGridContainer.add( exportSelection, 0, 0 ); -actionGridContainer.add( exportPrintSelection, 0, 1 ); -actionGridContainer.add( printSelection, 0, 2 ); - -bufferedWriter = null; -dlg = new ComponentsDialog( window, "Export and/or Print Selection", -new Widget [] { actionGridContainer }, -new String [] { "Action:" } ); - -if ( !dlg.clickedOk() ) return; - -if ( exportSelection.getState() || exportPrintSelection.getState() ) { - fileDescriptor = new BFileChooser( BFileChooser.SAVE_FILE, "Select name for the topology file."); - fileDescriptor.setSelectedFile( new File( "polygon.csv" ) ); - fileDescriptor.showDialog( window ); - filename = fileDescriptor.getSelectedFile(); - - if ( filename != null ) { - bufferedWriter = new BufferedWriter( new FileWriter( filename ) ); - } -} - -curvesMeshesInfo = getCurvesMeshesInfo(); -outputCurvesMeshes( curvesMeshesInfo ); \ No newline at end of file diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Gearweaver.bsh b/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Gearweaver.bsh deleted file mode 100644 index 93d1cb7..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Gearweaver.bsh +++ /dev/null @@ -1,1290 +0,0 @@ -/* - - - -*/ - -/** -Add a side to the bottom of the truncated shaft. - -@param bisectionRadius outer radius of shaft -@param bottomShaftPolygon bottom shaft polygon -@param currentAngle angle around the polygon -@param nodeVector nodes of the trimesh -@param sideAngle angle subtended by one side -*/ - -void addBottomSide( bisectionRadius, bottomShaftPolygon, currentAngle, nodeVector, sideAngle ) -{ - bottom = - shaftRadius * ( 1.0 - shaftTruncationBottom ); - currentSide = getPolar( currentAngle, bisectionRadius ); - nextSide = getPolar( currentAngle + sideAngle, bisectionRadius ); - - if ( bottom > nextSide.y ) { - return; - } - - if ( currentSide.y > bottom ) { - node = new Vec3( currentSide.x, currentSide.y, 0 ); - bottomShaftPolygon.add( nodeVector.size() ); - nodeVector.add( node ); - - return; - } - - shaftMinusCurrent = bottom - currentSide.y; - shaftMinusCurrent /= nextSide.y - currentSide.y; - intersection = nextSide.minus( currentSide ); - intersection.scale( shaftMinusCurrent ); - intersection.add( currentSide ); - node = new Vec3( intersection.x, intersection.y, 0 ); - bottomShaftPolygon.add( nodeVector.size() ); - nodeVector.add( node ); -} - -/** -Adds a clockwise triangle to the face array. - -@param face three index array -@param beginIndex beginning index of the triangle -@param centerIndex center index of the triangle -@param endIndex end index of the triangle -*/ - -void addFace( int beginIndex, int centerIndex, int endIndex, Vector faces ) -{ - int[] face = new int[ 3 ]; - faces.add( face ); - face[ 0 ] = beginIndex; - face[ 1 ] = centerIndex; - face[ 2 ] = endIndex; -} - -/** -Add faces between two layers of a convex concentric clockwise polygon and a convex anticlockwise polygon, both of which go around the origin. - -@param bottomOuterPolygon bottom outer polygon -@param bottomInnerPolygon bottom inner polygon -@param faceVector faces of the trimesh -@param nodeVector nodes of the trimesh -@param topOuterPolygon top outer polygon -@param topInnerPolygon top inner polygon -*/ - -void addFacesBetweenConcentricPolygons( Vector bottomInnerPolygon, Vector bottomOuterPolygon, Vector faceVector, Vector nodeVector, Vector topInnerPolygon, Vector topOuterPolygon ) -{ - oldClosestIndex = getClosestInnerIndex( bottomInnerPolygon, nodeVector, bottomOuterPolygon.elementAt( bottomOuterPolygon.size() - 1 ), bottomOuterPolygon.elementAt( 0 ) ); - - for ( int pointIndex = 0; pointIndex < bottomOuterPolygon.size(); pointIndex++ ) { - rimPlusOneRemainder = ( pointIndex + 1 ) % bottomOuterPolygon.size(); - bottomRimFirst = bottomOuterPolygon.elementAt( pointIndex ); - bottomRimSecond = bottomOuterPolygon.elementAt( rimPlusOneRemainder ); - topRimFirst = topOuterPolygon.elementAt( pointIndex ); - closestInnerIndex = getClosestInnerIndex( bottomInnerPolygon, nodeVector, bottomRimFirst, bottomRimSecond ); - addFace( bottomInnerPolygon.elementAt( closestInnerIndex ), bottomRimFirst, bottomRimSecond, faceVector ); - addFace( topInnerPolygon.elementAt( closestInnerIndex ), topOuterPolygon.elementAt( rimPlusOneRemainder ), topRimFirst, faceVector ); - - if ( closestInnerIndex > oldClosestIndex ) { - closestInnerIndex -= bottomInnerPolygon.size(); - } - - for ( int sideIndex = closestInnerIndex; sideIndex < oldClosestIndex; sideIndex++ ) { - sideRemainder = ( sideIndex + bottomInnerPolygon.size() ) % bottomInnerPolygon.size(); - sidePlusOneRemainder = ( sideIndex + bottomInnerPolygon.size() + 1 ) % bottomInnerPolygon.size(); - addFace( bottomInnerPolygon.elementAt( sidePlusOneRemainder ), bottomRimFirst, bottomInnerPolygon.elementAt( sideRemainder ), faceVector ); - addFace( topInnerPolygon.elementAt( sidePlusOneRemainder ), topInnerPolygon.elementAt( sideRemainder ), topRimFirst, faceVector ); - } - - oldClosestIndex = closestInnerIndex; - } - - return faceIndex; -} - -/** -Add faces between a bottom and top polygon. - -@param bottomPolygon bottom polygon -@param faceVector faces of the trimesh -@param topPolygon top polygon -*/ - -void addFacesBetweenPolygons( Vector bottomPolygon, Vector faceVector, Vector topPolygon ) -{ - for ( int beginIndex = 0; beginIndex < bottomPolygon.size(); beginIndex++ ) { - beginBottomIndex = bottomPolygon.elementAt( beginIndex ); - beginTopIndex = topPolygon.elementAt( beginIndex ); - endBottomIndex = bottomPolygon.elementAt( ( beginIndex + 1 ) % bottomPolygon.size() ); - endTopIndex = topPolygon.elementAt( ( beginIndex + 1 ) % bottomPolygon.size() ); - addFace( beginBottomIndex, beginTopIndex, endTopIndex, faceVector ); - addFace( beginBottomIndex, endTopIndex, endBottomIndex, faceVector ); - } -} - -/** -Add gear outline to scene. - -@param coordinateSystem coordinate system of the gear -@param name name of the gear -@param numberOfTeeth number of teeth in the gear -@param toothProfile profile of one of the teeth of the gear -*/ - -void addGear( CoordinateSystem coordinateSystem, String name, double numberOfTeeth, Vec2[] toothProfile ) -{ - int numberOfCircumferencePoints = toothProfile.length * numberOfTeeth; - Vec3[] gearVertexPositions = new Vec3[ numberOfCircumferencePoints ]; - float[] smoothness = new float[ numberOfCircumferencePoints ]; - int index = 0; - double toothAngleRadian = 2.0 * Math.PI / numberOfTeeth; - - for ( int tooth = 0; tooth < numberOfTeeth; tooth++ ) { - double totalToothAngle = - toothAngleRadian * tooth; - - for ( int toothSurface = 0; toothSurface < toothProfile.length; toothSurface++ ) { - rotatedVector = getRotatedVector( totalToothAngle, toothProfile[ toothSurface ] ); - gearVertexPositions[ index ] = new Vec3( rotatedVector.x, rotatedVector.y, 0 ); - smoothness[ index ] = 0; - index++; - } - } - - curve = new Curve( gearVertexPositions, smoothness, Mesh.APPROXIMATING, true ); - window.addObject( curve, coordinateSystem, name, null ); -} - -/** -Add the top side of the truncated shaft. - -@param bisectionRadius outer radius of the shaft -@param bottomShaftPolygon bottom shaft polygon -@param currentAngle current angle of the polygon point -@param nodeVector nodes of the trimesh -@param sideAngle angle subtended by a side of the polygon -*/ - -void addTopSide( bisectionRadius, bottomShaftPolygon, currentAngle, nodeVector, sideAngle ) -{ - top = shaftRadius; - - if ( shaftSides % 2 == 1 ) { - top = bisectionRadius; - } - - top *= ( 1.0 - shaftTruncationTop ); - currentSide = getPolar( currentAngle, bisectionRadius ); - lastSide = getPolar( currentAngle - sideAngle, bisectionRadius ); - - if ( lastSide.y > top ) { - return; - } - - if ( currentSide.y < top ) { - gearNode = new Vec3( currentSide.x, currentSide.y, 0 ); - bottomShaftPolygon.add( nodeVector.size() ); - nodeVector.add( gearNode ); - return; - } - - shaftMinusLast = top - lastSide.y; - shaftMinusLast /= currentSide.y - lastSide.y; - intersection = currentSide.minus( lastSide ); - intersection.scale( shaftMinusLast ); - intersection.add( lastSide ); - node = new Vec3( intersection.x, intersection.y, 0 ); - bottomShaftPolygon.add( nodeVector.size() ); - nodeVector.add( node ); -} - -/** -Add triangle pairs in two layers of a convex polygon. - -@param bottomPolygon bottom polygon -@param faceVector faces of the trimesh -@param topPolygon top polygon -*/ - -void addTrianglePairsInPolygon( Vector bottomPolygon, Vector faceVector, Vector topPolygon ) -{ - for ( int begin = 0; begin < ( bottomPolygon.size() - 1 ) / 2; begin++ ) { - end = bottomPolygon.size() - begin - 1; - centerIndex = bottomPolygon.elementAt( end - 1 ); - quadrilateralBegin = bottomPolygon.elementAt( begin ); - addFace( quadrilateralBegin, centerIndex, bottomPolygon.elementAt( end ), faceVector ); - centerIndex = topPolygon.elementAt( end - 1 ); - quadrilateralBegin = topPolygon.elementAt( begin ); - addFace( quadrilateralBegin, topPolygon.elementAt( end ), centerIndex, faceVector ); - } - - for ( int begin = 0; begin < bottomPolygon.size() / 2 - 1; begin++ ) { - end = bottomPolygon.size() - begin - 1; - centerIndex = bottomPolygon.elementAt( end - 1 ); - quadrilateralBegin = bottomPolygon.elementAt( begin ); - addFace( quadrilateralBegin, bottomPolygon.elementAt( begin + 1 ), centerIndex, faceVector ); - centerIndex = topPolygon.elementAt( end - 1 ); - quadrilateralBegin = topPolygon.elementAt( begin ); - addFace( quadrilateralBegin, centerIndex, topPolygon.elementAt( begin + 1 ), faceVector ); - } -} - -/** -Convert gear profile to thick gear. - -@param coordinateSystem coordinate system of the gear -@param numberOfTeeth number of teeth in the gear -@param pitchRadius pitch radius of the gear -@param shovelDirection direction that the teeth curve -@param thickName name of the solid gear, the name of the gear profile is the name of the solid gear plus " Profile" -*/ - -void convertToSolid( CoordinateSystem coordinateSystem, int numberOfTeeth, double pitchRadius, double shovelDirection, String thickName ) -{ - scene = window.getScene(); - - gearProfile = scene.getObject( thickName + " Profile" ); - gearVertexPositions = gearProfile.object.getVertexPositions(); - innerRadius = getInnerRadius( numberOfTeeth, pitchRadius ); - layers = 1 + shovelSegments; - topVertexPositionOffsets = gearVertexPositions.length * shovelSegments; - - Vector gearFaceVector = new Vector(); - Vector gearNodeVector = new Vector(); - - for ( int vertexIndex = 0; vertexIndex < gearVertexPositions.length; vertexIndex++ ) { - gearNode = new Vec3( gearVertexPositions[ vertexIndex ] ); - gearNodeVector.add( gearNode ); - } - - for ( int segmentIndex = 1; segmentIndex < layers; segmentIndex++ ) { - polarShovel = getPolar( shovelAngle, 1.0 ); - shovelWidth = 2.0 * polarShovel.y; - upRatio = ( double )segmentIndex / ( double )shovelSegments; - digY = polarShovel.y - upRatio * shovelWidth; - digRatio = Math.sqrt( 1.0 - digY * digY ) - polarShovel.x; - digRotation = shovelDirection * digRatio * thickness / pitchRadius; - up = upRatio * thickness; - - for ( int vertexIndex = 0; vertexIndex < gearVertexPositions.length; vertexIndex++ ) { - gearNode = gearNodeVector.elementAt( vertexIndex ); - rotatedGearNode = getRotatedVector( digRotation, new Vec2( gearNode.x, gearNode.y ) ); - layerNode = new Vec3( rotatedGearNode.x, rotatedGearNode.y, up ); - gearNodeVector.add( layerNode ); - } - } - - Vector bottomShaftVector = new Vector(); - Vector topShaftVector = new Vector(); - bisectionRadius = shaftRadius; - - if ( bisectionRadius > innerRadius ) { - bisectionRadius = 0.0; - shaftRadius = 0.0; - print( "The requested shaft is larger than the gear, so the shaft will not be removed." ); - } - - if ( shaftRadius > 0.0 ) { - halfSideAngle = Math.PI / shaftSides; - shaftStart = 1.5 * Math.PI + halfSideAngle; - sideAngle = 2.0 * halfSideAngle; - bisectionRadius /= Math.cos( halfSideAngle ); - int sideIndex = 0; - - for ( ; shaftStart + sideIndex * sideAngle < 2 * Math.PI; sideIndex++ ) { - currentAngle = shaftStart + sideIndex * sideAngle; - addBottomSide( bisectionRadius, bottomShaftVector, currentAngle, gearNodeVector, sideAngle ); - } - - for ( ; shaftStart + sideIndex * sideAngle < 2.5 * Math.PI + halfSideAngle / 2; sideIndex++ ) { - currentAngle = shaftStart + sideIndex * sideAngle; - addTopSide( bisectionRadius, bottomShaftVector, currentAngle, gearNodeVector, sideAngle ); - } - - originalHalfShaftLength = bottomShaftVector.size(); - mirrorStart = originalHalfShaftLength; - - if ( Math.abs( gearNodeVector.elementAt( bottomShaftVector.elementAt( originalHalfShaftLength - 1 ) ).x ) < 0.00001 ) { - mirrorStart++; - } - - for ( int sideIndex = mirrorStart; sideIndex < 2 * originalHalfShaftLength; sideIndex++ ) { - gearShaftNode = gearNodeVector.elementAt( bottomShaftVector.elementAt( 2 * originalHalfShaftLength - sideIndex - 1 ) ); - bottomShaftVector.add( gearNodeVector.size() ); - gearNodeVector.add( new Vec3( - gearShaftNode.x, gearShaftNode.y, gearShaftNode.z ) ); - } - - copyHigh( bottomShaftVector, gearNodeVector, thickness, topShaftVector ); - } - - pointsPerTooth = ( int )Math.round( gearVertexPositions.length / numberOfTeeth ); - - // Add faces around the perimeter. - - for ( int segmentIndex = 0; segmentIndex < shovelSegments; segmentIndex++ ) { - vertexPositionOffset = segmentIndex * gearVertexPositions.length; - Vector bottomPerimeter = new Vector(); - Vector topPerimeter = new Vector(); - - for ( int beginIndex = vertexPositionOffset; beginIndex < vertexPositionOffset + gearVertexPositions.length; beginIndex++ ) { - bottomPerimeter.add( beginIndex ); - topPerimeter.add( beginIndex + gearVertexPositions.length ); - } - - addFacesBetweenPolygons( bottomPerimeter, gearFaceVector, topPerimeter ); - } - - // Add faces to the top and bottom. - - Vector bottomRim = new Vector(); - Vector topRim = new Vector(); - - for ( int tooth = 0; tooth < numberOfTeeth; tooth++ ) { - toothStart = tooth * pointsPerTooth; - bottomRim.add( toothStart ); - topRim.add( toothStart + topVertexPositionOffsets ); - - Vector bottomTooth = new Vector(); - Vector topTooth = new Vector(); - - for ( int beginIndex = 0; beginIndex <= pointsPerTooth; beginIndex++ ) { - toothStartBegin = ( toothStart + beginIndex ) % gearVertexPositions.length; - bottomTooth.add( toothStartBegin ); - topTooth.add( toothStartBegin + topVertexPositionOffsets ); - } - - addTrianglePairsInPolygon( bottomTooth, gearFaceVector, topTooth ); - } - - // Add faces around cutout circles. - - rimThickness = minimumRimThickness * innerRadius; - centerThickness = bisectionRadius + rimThickness; - remainingCutout = ( 1.0 - 2 * minimumRimThickness ); - holeRadius = ( innerRadius - rimThickness - centerThickness ) / 2; - - if ( holeRadius > minimumRimCutoutRadius ) { - int cutoutCircles = 5; - int cutoutSides = 9; - double cutoutCircleAngle = 2.0 * Math.PI / ( double )cutoutCircles; - int sideBetweenStart = ( int )Math.round( ( double )cutoutSides / 7.0 ); - int sideBetweenStartMirror = cutoutSides - sideBetweenStart; - int sideBetweenEnd = ( int )Math.round( 3.0 * ( double )cutoutSides / 8.0 ); - int sideBetweenEndMirror = cutoutSides - sideBetweenEnd; - double cutoutSideAngle = 2.0 * Math.PI / ( double )cutoutSides; - double holeY = innerRadius - rimThickness - holeRadius; - double sinHalfCutoutCircleAngle = Math.sin( cutoutCircleAngle / 2 ); - double overlap = holeRadius + rimThickness / 2 - holeY * sinHalfCutoutCircleAngle; - Vector[] bottomCutoutVector = new Vector[ cutoutCircles ]; - Vector[] topCutoutVector = new Vector[ cutoutCircles ]; - - if ( overlap > 0.0 ) { - holeRadius -= overlap / ( 1.0 + sinHalfCutoutCircleAngle ); - holeY = innerRadius - rimThickness - holeRadius; - } - - for ( int circle = 0; circle < cutoutCircles; circle++ ) { - bottomCutoutVector[ circle ] = new Vector(); - topCutoutVector[ circle ] = new Vector(); - - for ( int side = 0; side < cutoutSides; side++ ) { - cutoutPlanePoint = getPolar( Math.PI * 1.5 + cutoutSideAngle * side, holeRadius ); - cutoutPlanePoint.y += holeY; - cutoutPlanePoint = getRotatedVector( - cutoutCircleAngle * circle, cutoutPlanePoint ); - gearNode = new Vec3( cutoutPlanePoint.x, cutoutPlanePoint.y, 0.0 ); - bottomCutoutVector[ circle ].add( gearNodeVector.size() ); - gearNodeVector.add( gearNode ); - } - - copyHigh( bottomCutoutVector[ circle ], gearNodeVector, thickness, topCutoutVector[ circle ] ); - - addFacesBetweenPolygons( bottomCutoutVector[ circle ], gearFaceVector, topCutoutVector[ circle ] ); - } - - Vector bottomOuterVector = new Vector(); - Vector topOuterVector = new Vector(); - - for ( int circle = cutoutCircles - 1; circle >= 0; circle-- ) { - - for ( int side = sideBetweenEnd; side <= sideBetweenEndMirror; side++ ) { - bottomOuterVector.add( bottomCutoutVector[ circle ].elementAt( side ) ); - topOuterVector.add( topCutoutVector[ circle ].elementAt( side ) ); - } - } - - addFacesBetweenConcentricPolygons( bottomOuterVector, bottomRim, gearFaceVector, gearNodeVector, topOuterVector, topRim ); - - // Add outside of cutout circles. - - bottomRim = new Vector(); - topRim = new Vector(); - - for ( int side = 0; side <= sideBetweenStart; side++ ) { - bottomRim.add( bottomCutoutVector[ 0 ].elementAt( side ) ); - topRim.add( topCutoutVector[ 0 ].elementAt( side ) ); - } - - for ( int circle = 1; circle < cutoutCircles; circle++ ) { - - for ( int side = sideBetweenStartMirror; side <= sideBetweenStart + cutoutSides; side++ ) { - sideRemainder = side % cutoutSides; - bottomRim.add( bottomCutoutVector[ circle ].elementAt( sideRemainder ) ); - topRim.add( topCutoutVector[ circle ].elementAt( sideRemainder ) ); - } - } - - for ( int side = sideBetweenStartMirror; side < cutoutSides; side++ ) { - bottomRim.add( bottomCutoutVector[ 0 ].elementAt( side ) ); - topRim.add( topCutoutVector[ 0 ].elementAt( side ) ); - } - - for ( int circle = 0; circle < cutoutCircles; circle++ ) { - Vector bottomSides = new Vector(); - Vector topSides = new Vector(); - - for ( int side = sideBetweenStart; side <= sideBetweenEnd; side++ ) { - bottomSides.add( bottomCutoutVector[ circle ].elementAt( side ) ); - topSides.add( topCutoutVector[ circle ].elementAt( side ) ); - } - - for ( int side = sideBetweenEndMirror; side <= sideBetweenStartMirror; side++ ) { - nextCircle = ( circle + 1 ) % cutoutCircles; - bottomSides.add( bottomCutoutVector[ nextCircle ].elementAt( side ) ); - topSides.add( topCutoutVector[ nextCircle ].elementAt( side ) ); - } - - addTrianglePairsInPolygon( bottomSides, gearFaceVector, topSides ); - } - } - - if ( shaftRadius == 0.0 ) { - addTrianglePairsInPolygon( bottomRim, gearFaceVector, topRim ); - } - else { - addFacesBetweenConcentricPolygons( bottomShaftVector, bottomRim, gearFaceVector, gearNodeVector, topShaftVector, topRim ); - addFacesBetweenPolygons( bottomShaftVector, gearFaceVector, topShaftVector ); - } - - int[][] gearFaceArray = gearFaceVector.toArray( new int[ gearFaceVector.size() ][ 3 ] ); - Vec3[] gearNodeArray = gearNodeVector.toArray( new Vec3[ gearNodeVector.size() ] ); - mesh = new TriangleMesh ( gearNodeArray, gearFaceArray ); - mesh.setSmoothingMethod( Mesh.NO_SMOOTHING ); - window.addObject( mesh, coordinateSystem, thickName, null ); - window.removeObject( scene.indexOf( gearProfile ), null ); -} - -/** -Copy the bottom polygon into a top polygon which is thickness high. - -@param bottomPolygon bottom polygon -@param nodeVector nodes of the trimesh -@param thickness height of the top polygon -@param topPolygon top polygon -*/ - -void copyHigh( Vector bottomPolygon, Vector nodeVector, double thickness, Vector topPolygon ) -{ - for ( int pointIndex = 0; pointIndex < bottomPolygon.size(); pointIndex++ ) { - node = nodeVector.elementAt( bottomPolygon.elementAt( pointIndex ) ); - topPolygon.add( nodeVector.size() ); - nodeVector.add( new Vec3( node.x, node.y, thickness ) ); - } -} - -/** -End the turning gear profile simulation and create the finished gear. -*/ - -void endTurnGear() -{ - scene = window.getScene(); - timer.cancel(); - firstGearCoordinateSystem.copyCoords( firstGearCoordinateSystemOld ); - secondGearCoordinateSystem.copyCoords( secondGearCoordinateSystemOld ); - - if ( sceneCameraInfo != null ) { - sceneCameraInfo.coords.copyCoords( sceneCameraCoordsOld ); - - for ( propertyIndex = 0; propertyIndex < sceneCameraPropertiesOld.length; propertyIndex++ ) { - sceneCameraInfo.object.setPropertyValue( propertyIndex, sceneCameraPropertiesOld[ propertyIndex ] ); - } - - scene.objectModified( sceneCameraInfo.object ); - } - - window.updateImage(); - - if ( thickness > 0.0 ) { - convertToSolid( firstGearCoordinateSystemOld, ( int )numberOfTeethFirstGear, pitchRadiusFirstGear, 1.0, "First Gear" ); - convertToSolid( secondGearCoordinateSystemOld, ( int )numberOfTeethSecondGear, pitchRadiusSecondGear, - 1.0, "Second Gear" ); - } - - undoAdd = new UndoRecord ( window, false, UndoRecord.DELETE_OBJECT, new Object[] { new Integer( scene.getNumObjects() - 2 ) } ); - window.setUndoRecord( undoAdd ); - undoAdd = new UndoRecord ( window, false, UndoRecord.DELETE_OBJECT, new Object[] { new Integer( scene.getNumObjects() - 1 ) } ); - window.setUndoRecord( undoAdd ); - window.updateImage(); - -// number of faces: -// for each edge in our perimeter, two triangles to connect -// the front and back, so 2*numberSides -// for each end cap, we connect each vertex to the point. The -// first and last vertices are connected by a perimeter edge, -// leaving numberSides-2 edges to connect across the middle, -// creating a face, for numberSides-2 triangles per end cap, -// or (numberSides-2)*2 triangles for both end caps -// Thus: -// 2*numberSides + 2*(numberSides-2) -// 2*numberSides + 2*numberSides - 4 -// 4*numberSides - 4 -//Vec3[] v = new Vec3[numberSides * 2]; -//int[][] faces = new int[4*numberSides-4][3]; -//v[0] = new Vec3(0, y0, 0); -//v[1] = new Vec3(0, y0, -length); -} - -/** -Get the Camera Info from the first camera in the scene. -*/ - -ObjectInfo getCameraInfo() -{ - scene = window.getScene(); - for ( int objectIndex = 0; objectIndex < scene.getNumObjects(); objectIndex++ ) { - objectInfo = scene.getObject( objectIndex ); - if ( objectInfo.object instanceof SceneCamera ) { - return objectInfo; - } - } - - return null; -} - -/** -Get the index of the point on the inner polygon which is closest to the average angle of the first and second points on the outer polygon. - -@param innerPolygon inner polygon index array -@param nodes Vector of nodes -@param outerPolygonFirstIndex index of first point on outer polygon -@param outerPolygonSecondIndex index of second point on outer polygon -@return closest index on the inner polygon to the average angle of the first and second points on the outer polygon -*/ - -int getClosestInnerIndex( Vector innerPolygon, Vector nodes, int outerPolygonFirstIndex, int outerPolygonSecondIndex ) -{ - closestIndex = 0; - largestDot = - 9999999.0; - rimFirstPlane = nodes.elementAt( outerPolygonFirstIndex ).dropAxis( 2 ); - rimSecondPlane = nodes.elementAt( outerPolygonSecondIndex ).dropAxis( 2 ); - rimFirstPlane.normalize(); - rimSecondPlane.normalize(); - rimFirstPlane.add( rimSecondPlane ); - rimFirstPlane.normalize(); - - for ( int innerIndex = 0; innerIndex < innerPolygon.size(); innerIndex++ ) { - innerPlane = nodes.elementAt( innerPolygon.elementAt( innerIndex ) ).dropAxis( 2 ); - innerPlane.normalize(); - innerDot = innerPlane.dot( rimFirstPlane ); - - if ( innerDot > largestDot ) { - largestDot = innerDot; - closestIndex = innerIndex; - } - } - - return closestIndex; -} - -/** -Get number of teeth from the field value if it is not zero bounded to a minimum of 3, otherwise get number from the prime list. - -@param primeList scroll list of prime numbers -@param numberOfTeethValueField number of gear teeth value field -@return number of gear teeth -*/ - -double getNumberOfTeeth( BList primeList, ValueField numberOfTeethValueField ) -{ - if ( numberOfTeethValueField.getValue() < 1.0 ) { - return Double.valueOf( primeList.getSelectedValue() ); - } - - return Math.max( 2, Math.round( numberOfTeethValueField.getValue() ) ); -} - -/** -Get gear inner radius. - -@param numberOfTeeth number of gear teeth -@param pitchRadius pitch radius of the gear -@return gear inner radius -*/ - -double getInnerRadius( double numberOfTeeth, double pitchRadius ) -{ - return pitchRadius * ( 1 - Math.PI / numberOfTeeth ); -} - -/** -Get ratio outside of the pitch. - -@param numberOfTeeth number of gear teeth -@param pitchRadius pitch radius of the gear -@return ratio outside of the pitch -*/ - -double getOutsidePitch( double numberOfTeeth ) -{ - return 2.0 / numberOfTeeth; -} - -/** -Get ratio of second gear according to the number of teeth. - -@param numberOfTeethFirstGear number of gear teeth on the first gear -@param numberOfTeethSecondGear number of gear teeth on the second gear -@param pitchRadiusFirstGear pitch radius of the first gear -@return ratio of second gear -*/ - -double getPitchRadiusSecondGear( double numberOfTeethFirstGear, double numberOfTeethSecondGear, double pitchRadiusFirstGear ) -{ - return pitchRadiusFirstGear * numberOfTeethSecondGear / numberOfTeethFirstGear;; -} - -/** -Get polar Vec2 from counterclockwise angle from 1, 0 and radius. - -@param angle counterclockwise angle from 1, 0 -@param radius radius of vector -@return polar vector -*/ - -Vec2 getPolar( double angle, double radius ) -{ - return new Vec2( radius * Math.cos( angle ), radius * Math.sin( angle ) ); -} - -/** -Get scroll list of prime numbers, with visible selection. - -@param selectedIndex selected index of the scroll list -@return scroll list of prime numbers -*/ - -BList getPrimeList( int selectedIndex ) -{ - String[] primeNumberStrings = new String[ primeNumbers.length ]; - - for ( int primeIndex = 0; primeIndex < primeNumbers.length; primeIndex++ ) { - primeNumberStrings[ primeIndex ] = primeNumbers[ primeIndex ].toString(); - } - - primeList = new BList( primeNumberStrings ); - primeList.setPreferredVisibleRows( ( int )Math.max( 4.0, selectedIndex + 1 ) ); - primeList.setMultipleSelectionEnabled( false ); - primeList.setSelected( selectedIndex, true ); - primeList.scrollToItem( selectedIndex ); - - return primeList; -} - -/** -Get rotated Vec2 from counterclockwise angle and vector. - -@param angle counterclockwise angle from 1, 0 -@param vector2 plane vector -@return rotated vector -*/ - -Vec2 getRotatedVector( double angle, Vec2 vector2 ) -{ - x = Math.cos( angle ); - y = Math.sin( angle ); - - return new Vec2( vector2.x * x - vector2.y * y, vector2.x * y + vector2.y * x ); -} - -/** -Get profile for one tooth. - -@param numberOfTeeth number of gear teeth -@param pitchRadius pitch radius of the gear -@param pressureAngle pressure angle of the gear tooth -@param profileDefinitionSurfaces profile definition surfaces, which should be at least six -@return profile for one tooth -*/ - -Vec2[] getToothProfile( double numberOfTeeth, double pitchRadius, double pressureAngle, int profileDefinitionSurfaces ) -{ - double toothAngleRadian = 2.0 * Math.PI / numberOfTeeth; - double innerRadius = getInnerRadius( numberOfTeeth, pitchRadius ); - double outerRadius = pitchRadius * ( 1 + getOutsidePitch( numberOfTeeth ) ); - double bevelRadius = pitchRadius * Math.cos( pressureAngle ); - double angleBeginRadian = Math.PI / 2 - toothAngleRadian / 4 + pressureAngle - pitchRadius * Math.sin( pressureAngle ) / bevelRadius; - double angleEndRadian = Math.sqrt( outerRadius * outerRadius - bevelRadius * bevelRadius ) / bevelRadius + angleBeginRadian; - double angleDifferenceRadian = ( angleEndRadian - angleBeginRadian ) / ( profileDefinitionSurfaces - 1 ); - Vector toothProfileVector = new Vector(); - - toothProfileVector.add( getPolar( Math.PI - angleBeginRadian, innerRadius ) ); - - angleRadian = angleBeginRadian; - abovePoint = null; - pointMoved = false; - - for ( int profileIndex = 0; profileIndex < profileDefinitionSurfaces; profileIndex++ ) { - length = bevelRadius * ( angleRadian - angleBeginRadian ); - toothPoint = new Vec2( - bevelRadius, length ); - toothPoint = getRotatedVector( angleRadian, toothPoint ); - toothPoint.y = - toothPoint.y; - toothProfileVector.add( toothPoint ); - angleRadian = angleRadian + angleDifferenceRadian; - - if ( toothPoint.length() > innerRadius ) { - - if ( abovePoint == null ) { - abovePoint = toothPoint; - } - } - } - - // Move out, remove or replace the points which are inside the inner radius. - - for ( int profileIndex = profileDefinitionSurfaces-1; profileIndex >= 1; profileIndex-- ) { - toothProfileLength = toothProfileVector.elementAt( profileIndex ).length(); - - if ( toothProfileLength < innerRadius ) { - - if ( pointMoved ) { - toothProfileVector.removeElementAt( profileIndex ); - } - else { - lengthBelow = innerRadius - toothProfileLength; - toothPoint = toothProfileVector.elementAt( profileIndex ); - lastMinusShort = abovePoint.minus( toothPoint ); - lastMinusShort.scale( lengthBelow / lastMinusShort.length() ); - toothPoint.add( lastMinusShort ); - pointMoved = true; - } - } - } - - if ( pointMoved ) { - toothProfileVector.removeElementAt( 0 ); - } - - // Mirror the tooth profile. - - int toothProfileLimit = toothProfileVector.size() - 1; - - for ( int profileIndex = toothProfileLimit; profileIndex >= 0; profileIndex-- ) { - toothPoint = toothProfileVector.elementAt( profileIndex ); - toothProfileVector.add( new Vec2( - toothPoint.x, toothPoint.y ) ); - } - - return toothProfileVector.toArray( new Vec2[ toothProfileVector.size() ] ); -} - -/** -Add radio button groups to the preference widgets. - -@param radioButtonGroups radio button groups which will be added to the memorable widgets -@param widgetVector memorable widgets -*/ - -void preferencesAddRadioButtonGroups( RadioButtonGroup[] radioButtonGroups, Vector widgetVector ) -{ - for ( int radioIndex = 0; radioIndex < radioButtonGroups.length; radioIndex++ ) { - radioButtonGroup = radioButtonGroups[ radioIndex ]; - radioButtonGroupIterator = radioButtonGroup.getRadioButtons(); - - while ( radioButtonGroupIterator.hasNext() ) { - radioButton = radioButtonGroupIterator.next(); - preferencesAddWidgetWithString( radioButton, radioButton.getText(), widgetVector ); - } - } -} - -/** -Add widgets which have titles. - -@param widgets widgets which have titles -@param widgetStrings widget titles -@param widgetVector memorable widgets -*/ - -void preferencesAddWidgetsWithStrings( Widget[] widgets, String[] widgetStrings, Vector widgetVector ) -{ - for ( int widgetIndex = 0; widgetIndex < widgets.length; widgetIndex++ ) { - widget = widgets[ widgetIndex ]; - - if ( widget instanceof BCheckBox || widget instanceof BOutline || widget instanceof BTextField || widget instanceof ValueField ) { - preferencesAddWidgetWithString( widget, widgetStrings[ widgetIndex ], widgetVector ); - } - } -} - -/** -Give the widget a name and add it to the widget vector. - -@param widget widget which will be given a name -@param widgetStrings widget name -@param widgetVector memorable widgets -*/ - -void preferencesAddWidgetWithString( Widget widget, String widgetString, Vector widgetVector ) -{ - widget.setName( widgetString ); - widgetVector.add( widget ); -} - -/** -Read widget settings from preferences file. - -@param preferencesFilename preferences filename -@param widgetVector memorable widgets -*/ - -void preferencesRead( String preferencesFilename, Vector widgetVector ) -{ - preferencesFile = new File( preferencesFilename ); - - if ( !preferencesFile.canRead() ) { - return; - } - - BufferedReader preferencesReader = new BufferedReader( new FileReader( preferencesFile ) ); - - line = preferencesReader.readLine(); - - while ( line != null ) { - preferencesReadLine( line, widgetVector ); - line = preferencesReader.readLine(); - } -} - -/** -Read line of preferences and set widget to that line. - -@param line line of preferences -@param widgetVector memorable widgets -*/ - -void preferencesReadLine( String line, Vector widgetVector ) -{ - splitLine = line.split( "\t" ); - - if ( splitLine.length < 2 ) { - return; - } - - name = splitLine[ 0 ]; - - for ( int widgetIndex = 0; widgetIndex < widgetVector.size(); widgetIndex++ ) { - widget = widgetVector.elementAt( widgetIndex ); - - if ( widget.getName().equals( name ) ) { - preferencesReadWidget( splitLine[ 1 ], widget ); - - return; - } - } -} - -/** -Set widget to preferences value. - -@param value preferences value -@param widget widget to be set to value -*/ - -void preferencesReadWidget( String value, Widget widget ) -{ - if ( widget instanceof BCheckBox || widget instanceof BRadioButton ) { - widget.setState( Boolean.valueOf( value ) ); - - return; - } - - if ( widget instanceof BOutline ) { // it would be better to save the value instead of index because the list might change, but I'm lazy - bList = widget.getContent().getContent(); - selectedIndex = Integer.valueOf( value ); - bList.setSelected( selectedIndex, true ); - bList.scrollToItem( selectedIndex ); - - return; - } - - if ( widget instanceof BTextField ) { - widget.setText( value ); - - return; - } - - if ( widget instanceof ValueField ) { - widget.setValue( Double.valueOf( value ) ); - } -} - -/** -Write widget settings to preferences file. - -@param preferencesFilename preferences filename -@param widgetVector memorable widgets -*/ - -void preferencesWrite( String preferencesFilename, Vector widgetVector ) -{ - preferencesFile = new File( preferencesFilename ); - - if ( preferencesFile == null ) { - print( "Can not write preferences to " + preferencesFilename ); - - return; - } - - BufferedWriter preferencesWriter = new BufferedWriter( new FileWriter( preferencesFile ) ); - - for ( int widgetIndex = 0; widgetIndex < widgetVector.size(); widgetIndex++ ) { - widget = widgetVector.elementAt( widgetIndex ); - preferencesWriteWidget( preferencesWriter, widget ); - } - - //Close the output stream - preferencesWriter.close(); -} - -/** -Write widget settings to line of preferences. - -@param preferencesWriter buffered preferences file writer -@param widget widget to be written -*/ - -void preferencesWriteWidget( BufferedWriter preferencesWriter, Widget widget ) -{ - widgetString = widget.getName() + "\t"; - - if ( widget instanceof BCheckBox || widget instanceof BRadioButton ) { - preferencesWriter.write( widgetString + widget.getState().toString() + "\n" ); - - return; - } - - if ( widget instanceof BOutline ) { // it would be better to save the value because the list might change, but I'm lazy - BList bList = widget.getContent().getContent(); - bList = widget.getContent().getContent(); - preferencesWriter.write( widgetString + bList.getSelectedIndex().toString() + "\n" ); - - return; - } - - if ( widget instanceof BTextField ) { - preferencesWriter.write( widgetString + widget.getText() + "\n" ); - - return; - } - - if ( widget instanceof ValueField ) { - preferencesWriter.write( widgetString + widget.getValue().toString() + "\n" ); - } -} - -/** -Set the coordinate system to a rotation around the z axis in degrees. - -@param coordinateSystem coordinate system with rotations defined around the x, y, z axes in degrees -@param rotationDegree axis rotation angle in degrees -*/ - -void setCoordinateSystemToRotationDegree( CoordinateSystem coordinateSystem, double rotationDegree ) -{ - coordinateSystem.setOrientation( 0.0, 0.0, rotationDegree ); -} - -// Trim outer tooth of the first gear which collides with the second gear. - -void trimCollision( double numberOfTeethFirstGear, double numberOfTeethSecondGear, double pitchRadiusFirstGear, Vec2[] toothProfileFirstGear, Vec2[] toothProfileSecondGear ) -{ - maximumAngle = Math.PI / 8; - - if ( numberOfTeethFirstGear > numberOfTeethSecondGear ) { - maximumAngle *= numberOfTeethSecondGear / numberOfTeethFirstGear; - } - - for ( double angle = 0.0; angle < maximumAngle; angle += 0.01 ) { - trimCollisionAtAngle( angle, numberOfTeethFirstGear, numberOfTeethSecondGear, pitchRadiusFirstGear, toothProfileFirstGear, toothProfileSecondGear ); - } -} - -// Trim outer tooth of the first gear which collides with the second gear at an angle. - -void trimCollisionAtAngle( double angle, double numberOfTeethFirstGear, double numberOfTeethSecondGear, double pitchRadiusFirstGear, Vec2[] toothProfileFirstGear, Vec2[] toothProfileSecondGear ) -{ - double pitchRadiusSecondGear = getPitchRadiusSecondGear( numberOfTeethFirstGear, numberOfTeethSecondGear, pitchRadiusFirstGear ); - - toothProfileSecondGearRotated = new Vec2[ toothProfileSecondGear.length ]; - rotationSecondGear = Math.PI - Math.PI / numberOfTeethSecondGear - angle * numberOfTeethFirstGear / numberOfTeethSecondGear; - - for ( int profilePointIndex = 0; profilePointIndex < toothProfileSecondGear.length; profilePointIndex++ ) { - rotated = getRotatedVector( rotationSecondGear, toothProfileSecondGear[ profilePointIndex ] ); - rotated.y += pitchRadiusFirstGear + pitchRadiusSecondGear; - toothProfileSecondGearRotated[ profilePointIndex ] = getRotatedVector( - angle, rotated ); - } - - for ( int profilePointIndex = 0; profilePointIndex < toothProfileFirstGear.length; profilePointIndex++ ) { - trimCollisionProfilePoint( profilePointIndex, toothProfileFirstGear, toothProfileSecondGearRotated ); - } -} - -// Trim point from first gear which collides with the second gear. - -void trimCollisionProfilePoint( int profilePointIndex, Vec2[] toothProfileFirstGear, Vec2[] toothProfileSecondGearRotated ) -{ - firstGearProfilePoint = toothProfileFirstGear[ profilePointIndex ]; - - if ( firstGearProfilePoint.length() < pitchRadiusFirstGear ) { - return; - } - - if ( firstGearProfilePoint.x > 0.0 ) { - return; - } - - for ( int secondGearPointIndex = 0; secondGearPointIndex < toothProfileSecondGearRotated.length - 1; secondGearPointIndex++ ) { - firstPointSecondGear = toothProfileSecondGearRotated[ secondGearPointIndex ]; - secondPointSecondGear = toothProfileSecondGearRotated[ secondGearPointIndex + 1 ]; - firstPointAbove = firstPointSecondGear.y - firstGearProfilePoint.y; - secondPointAbove = secondPointSecondGear.y - firstGearProfilePoint.y; - - if ( firstPointAbove * secondPointAbove <= 0.0 ) { - verticalSeparation = firstPointSecondGear.y - secondPointSecondGear.y; - horizontalToothAxisIntersection = firstPointSecondGear.minus( secondPointSecondGear ); - horizontalToothAxisIntersection.scale( - secondPointAbove / verticalSeparation ); - horizontalToothAxisIntersection.add( secondPointSecondGear ); - collision = horizontalToothAxisIntersection.x - firstGearProfilePoint.x; - - if ( collision > 0.0 ) { - firstGearProfilePoint.x += collision; - mirrorPointIndex = toothProfileFirstGear.length - 1 - profilePointIndex; - toothProfileFirstGear[ mirrorPointIndex ].x -= collision; - } - } - } -} - -// Trim outer tooth by tolerance. - -void trimTolerance( double numberOfTeeth, double pitchRadius, double tolerance, Vec2[] toothProfile ) -{ - if ( tolerance == 0.0 ) { - return; - } - - double otherGearStart = pitchRadius * ( 1 - getOutsidePitch( numberOfTeeth ) ) - tolerance; - double innerRadius = getInnerRadius( numberOfTeeth, pitchRadius ); - - for ( int profilePointIndex = 0; profilePointIndex < toothProfile.length; profilePointIndex++ ) { - toothProfilePoint = toothProfile[ profilePointIndex ]; - toothProfilePointLength = toothProfilePoint.length(); - shortenRatio = 1.0; - - if ( toothProfilePointLength < otherGearStart ) { - shortenRatio = ( toothProfilePointLength - innerRadius ) / ( otherGearStart - innerRadius ); - shortenRatio = Math.max( 0.0, shortenRatio ); - } - - xAbsolute = Math.abs( toothProfilePoint.x ); - xAbsoluteTrimmed = xAbsolute - tolerance * shortenRatio; - xAbsoluteTrimmed = Math.max( 0.0, xAbsoluteTrimmed ); - - if ( xAbsolute > 0.0 ) { - toothProfilePoint.x *= xAbsoluteTrimmed / xAbsolute; - } - } -} - -// Get parameters. - -int[] primeNumbers = { 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149 }; -firstGearPrimeList = getPrimeList( 6 ); -numberOfTeethFirstGearValueField = new ValueField( 0, ValueField.NONNEGATIVE ); -pitchRadiusFirstGearValueField = new ValueField( 75, ValueField.NONNEGATIVE ); -secondGearPrimeList = getPrimeList( 1 ); -numberOfTeethSecondGearValueField = new ValueField( 0, ValueField.NONNEGATIVE ); -minimumRimCutoutRadiusValueField = new ValueField( 2.0, ValueField.NONNEGATIVE ); -minimumRimThicknessValueField = new ValueField( 0.2, ValueField.NONNEGATIVE ); -String preferencesFilename = "gearweaver_preferences.csv"; -pressureAngleDegreeValueField = new ValueField( 20, ValueField.NONNEGATIVE ); -profileDefinitionValueField = new ValueField( 9, ValueField.NONNEGATIVE ); -shaftRadiusValueField = new ValueField( 5.0, ValueField.NONNEGATIVE); -shaftSidesValueField = new ValueField( 4.0, ValueField.NONNEGATIVE); -shaftTruncationBottomValueField = new ValueField( 0.0, ValueField.NONNEGATIVE); -shaftTruncationTopValueField = new ValueField( 0.0, ValueField.NONNEGATIVE); -shovelAngleValueField = new ValueField( 20.0, ValueField.NONNEGATIVE); -shovelSegmentsValueField = new ValueField( 3, ValueField.NONNEGATIVE); -//simulationDurationValueField = new ValueField( 10, ValueField.NONNEGATIVE); -simulationDurationValueField = new ValueField( 0, ValueField.NONNEGATIVE); -simulationRotationRateValueField = new ValueField( 0.1, ValueField.NONNEGATIVE ); -thicknessValueField = new ValueField( 30.0, ValueField.NONNEGATIVE ); -//thicknessValueField = new ValueField( 0.0, ValueField.NONNEGATIVE ); -toleranceValueField = new ValueField( 0.0, ValueField.NONNEGATIVE ); - -Widget[] widgets = new Widget [] { UIUtilities.createScrollingList( firstGearPrimeList ), - numberOfTeethFirstGearValueField, - pitchRadiusFirstGearValueField, - UIUtilities.createScrollingList( secondGearPrimeList ), - numberOfTeethSecondGearValueField, - minimumRimCutoutRadiusValueField, - minimumRimThicknessValueField, - pressureAngleDegreeValueField, - profileDefinitionValueField, - shaftRadiusValueField, - shaftSidesValueField, - shaftTruncationBottomValueField, - shaftTruncationTopValueField, - shovelAngleValueField, - shovelSegmentsValueField, - simulationDurationValueField, - simulationRotationRateValueField, - thicknessValueField, - toleranceValueField }; - -String[] widgetStrings = new String [] { "Number of Teeth for First Gear (prime):", - "or Number of Teeth for First Gear (integer):", - "Pitch Radius First Gear (mm):", - "Number of Teeth for Second Gear (prime):", - "or Number of Teeth for Second Gear (integer):", - "Minimum Rim Cutout Radius (mm):", - "Minimum Rim Thickness (ratio):", - "Pressure Angle (degrees):", - "Profile Definition (surfaces):", - "Shaft Radius (mm):", - "Shaft Sides (surfaces):", - "Shaft Truncation Bottom (ratio):", - "Shaft Truncation Top (ratio):", - "Shovel Angle (degrees):", - "Shovel Segments (surfaces):", - "Simulation Duration (seconds):", - "Simulation Rotation Rate (teeth / second):", - "Thickness (mm):", - "Tolerance (mm):" }; - -// change the user interface parameters from default to preferences -Vector widgetVector = new Vector(); -preferencesAddWidgetsWithStrings( widgets, widgetStrings, widgetVector ); -preferencesRead( preferencesFilename, widgetVector ); - -dialog = new ComponentsDialog( window, "Gearweaver Generator", widgets, widgetStrings ); - -if ( !dialog.clickedOk() ) return; - -preferencesWrite( preferencesFilename, widgetVector ); - -double numberOfTeethFirstGear = getNumberOfTeeth( firstGearPrimeList, numberOfTeethFirstGearValueField ); -double numberOfTeethSecondGear = getNumberOfTeeth( secondGearPrimeList, numberOfTeethSecondGearValueField ); -double pitchRadiusFirstGear = pitchRadiusFirstGearValueField.getValue(); -double pitchRadiusSecondGear = getPitchRadiusSecondGear( numberOfTeethFirstGear, numberOfTeethSecondGear, pitchRadiusFirstGear ); -double minimumRimCutoutRadius = minimumRimCutoutRadiusValueField.getValue(); -double minimumRimThickness = minimumRimThicknessValueField.getValue(); -int profileDefinitionSurfaces = ( int )Math.max( 1.0, Math.min( 30.0, profileDefinitionValueField.getValue() ) ); -double pressureAngle = pressureAngleDegreeValueField.getValue() * Math.PI / 180.0; -double shaftRadius = shaftRadiusValueField.getValue(); -int shaftSides = ( int )Math.max( 3.0, shaftSidesValueField.getValue() ); -double shaftTruncationBottom = shaftTruncationBottomValueField.getValue(); -double shaftTruncationTop = shaftTruncationTopValueField.getValue(); -double shovelAngle = shovelAngleValueField.getValue() * Math.PI / 180.0; -int shovelSegments = ( int )Math.max( 1.0, shovelSegmentsValueField.getValue() ); -double simulationDuration = simulationDurationValueField.getValue(); -double simulationRotationRate = simulationRotationRateValueField.getValue(); -double thickness = thicknessValueField.getValue(); -double tolerance = toleranceValueField.getValue(); - -// Create gear pair. - -toothProfileFirstGear = getToothProfile( numberOfTeethFirstGear, pitchRadiusFirstGear, pressureAngle, profileDefinitionSurfaces ); -toothProfileSecondGear = getToothProfile( numberOfTeethSecondGear, pitchRadiusSecondGear, pressureAngle, profileDefinitionSurfaces ); - -trimCollision( numberOfTeethFirstGear, numberOfTeethSecondGear, pitchRadiusFirstGear, toothProfileFirstGear, toothProfileSecondGear ); -trimCollision( numberOfTeethSecondGear, numberOfTeethFirstGear, pitchRadiusSecondGear, toothProfileSecondGear, toothProfileFirstGear ); - -firstGearCoordinateSystem = new CoordinateSystem(); -firstGearCoordinateSystemOld = firstGearCoordinateSystem.duplicate(); -trimTolerance( numberOfTeethFirstGear, pitchRadiusFirstGear, tolerance, toothProfileFirstGear ); -addGear( firstGearCoordinateSystem, "First Gear Profile", numberOfTeethFirstGear, toothProfileFirstGear ); - -secondGearCoordinateSystem = new CoordinateSystem(); -secondGearCoordinateSystem.setOrigin( new Vec3( 0.0, pitchRadiusFirstGear + pitchRadiusSecondGear, 0.0 ) ); -secondGearCoordinateOffsetDegree = 180.0 * ( numberOfTeethSecondGear % 2 + 1 ) / numberOfTeethSecondGear; -setCoordinateSystemToRotationDegree( secondGearCoordinateSystem, secondGearCoordinateOffsetDegree ); -secondGearCoordinateSystemOld = secondGearCoordinateSystem.duplicate(); -trimTolerance( numberOfTeethSecondGear, pitchRadiusSecondGear, tolerance, toothProfileSecondGear ); -addGear( secondGearCoordinateSystem, "Second Gear Profile", numberOfTeethSecondGear, toothProfileSecondGear ); - -import java.util.Timer; -import java.util.TimerTask; - -Timer timer = new Timer(); - -startTime = System.currentTimeMillis(); -sceneCameraInfo = getCameraInfo(); -sceneCameraCoordsOld = null; -sceneCameraPropertiesOld = null; - -if ( sceneCameraInfo != null ) { - sceneCameraCoordsOld = sceneCameraInfo.coords.duplicate(); - sceneCamera = sceneCameraInfo.object; - properties = sceneCamera.getProperties(); - propertiesLength = properties.length; - sceneCameraPropertiesOld = new double[ propertiesLength ]; - - for ( propertyIndex = 0; propertyIndex < propertiesLength; propertyIndex++ ) { - sceneCameraPropertiesOld[ propertyIndex ] = sceneCamera.getPropertyValue( propertyIndex ); - propertyName = properties[ propertyIndex ].getName(); - - if ( propertyName.equals( "Depth of Field" ) ) { - sceneCamera.setPropertyValue( propertyIndex, 10.0 ); - } - - if ( propertyName.equals( "Field of View" ) ) { - sceneCamera.setPropertyValue( propertyIndex, 30.0 ); - } - - if ( propertyName.equals( "Focal Distance" ) ) { - sceneCamera.setPropertyValue( propertyIndex, 20.0 ); - } - } - sceneCameraInfo.coords.setOrigin( new Vec3( 0.0, pitchRadiusFirstGear, 15.0 * pitchRadiusFirstGear / numberOfTeethFirstGear ) ); - sceneCameraInfo.coords.setOrientation( 0.0, 180.0, 0.0 ); - sceneCameraInfo.coords.setOrientation( 0.0, 180.0, 0.0 ); -} - -public final class TurnGear extends TimerTask { - /** - * Implements TimerTask's abstract run method. - */ - public void run() { - elapsed = ( System.currentTimeMillis() - startTime ) / 1000.0; - elapsedRotation = 360.0 * elapsed * simulationRotationRate; - setCoordinateSystemToRotationDegree( firstGearCoordinateSystem, - elapsedRotation / numberOfTeethFirstGear ); - setCoordinateSystemToRotationDegree( secondGearCoordinateSystem, elapsedRotation / numberOfTeethSecondGear + secondGearCoordinateOffsetDegree ); - scene = window.getScene(); - scene.objectModified( scene.getObject( "First Gear Profile" ).object ); - scene.objectModified( scene.getObject( "Second Gear Profile" ).object ); - window.updateImage(); - - if ( elapsed > simulationDuration ) { - endTurnGear(); - } - } -} - -TimerTask turnGear = new TurnGear(); -timer.scheduleAtFixedRate( turnGear, 0, 13 ); \ No newline at end of file diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Import GNU Triangulated Surface.bsh b/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Import GNU Triangulated Surface.bsh deleted file mode 100644 index 09c7633..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Import GNU Triangulated Surface.bsh +++ /dev/null @@ -1,399 +0,0 @@ -/* - - - -*/ - -/** -Add a delete the last object of the scene undo record, to the scene. -*/ - -void addUndoRecord() { - scene = window.getScene(); - undoAdd = new UndoRecord ( window, false, UndoRecord.DELETE_OBJECT, new Object[] { new Integer( scene.getNumObjects() - 1 ) } ); - window.setUndoRecord( undoAdd ); -} - -int getSameVertexIndex( edgeFirst, edgeSecond ) -{ - for ( int endpointIndex = 0; endpointIndex < 2; endpointIndex++ ) { - endpoint = edgeFirst[ endpointIndex ]; - - if ( endpoint == edgeSecond[ 0 ] ) { - return endpoint; - } - - if ( endpoint == edgeSecond[ 1 ] ) { - return endpoint; - } - } - - print( "Inconsistent GNU Triangulated Surface" ); - print( edgeFirst ); - print( edgeSecond ); - return 0; -} - -/** -Import GNU Triangulated Surface from a file. -Quoted from http://gts.sourceforge.net/reference/gts-surfaces.html#GTS-SURFACE-WRITE -"All the lines beginning with GTS_COMMENTS (#!) are ignored. The first line contains three unsigned integers separated by spaces. The first integer is the number of vertices, nv, the second is the number of edges, ne and the third is the number of faces, nf. - -Follows nv lines containing the x, y and z coordinates of the vertices. Follows ne lines containing the two indices (starting from one) of the vertices of each edge. Follows nf lines containing the three ordered indices (also starting from one) of the edges of each face. - -The format described above is the least common denominator to all GTS files. Consistent with an object-oriented approach, the GTS file format is extensible. Each of the lines of the file can be extended with user-specific attributes accessible through the read() and write() virtual methods of each of the objects written (surface, vertices, edges or faces). When read with different object classes, these extra attributes are just ignored." -*/ - -void importFile( gnuFile ) -{ - bufferedReader = new BufferedReader( new FileReader( gnuFile ) ); - Vector lineVector = new Vector(); - line = bufferedReader.readLine(); - name = gnuFile.getName(); - int lastIndexOfDot = name.lastIndexOf( '.' ); - - if ( lastIndexOfDot > 0 ) { - name = name.substring( 0, lastIndexOfDot ); - } - - while ( line != null ) { - - if ( line.length() > 0 ) { - firstCharacter = line.charAt( 0 ); - - if ( firstCharacter != '#' && firstCharacter != '!' ) { - lineVector.add( line ); - } - } - - line = bufferedReader.readLine(); - } - - splitLine = lineVector.get( 0 ).split( " " ); - int numberOfVertices = Integer.valueOf( splitLine[ 0 ] ); - int numberOfEdges = Integer.valueOf( splitLine[ 1 ] ); - int numberOfFaces = Integer.valueOf( splitLine[ 2 ] ); - edges = new int[ numberOfEdges ][ 2 ]; - faces = new int[ numberOfFaces ][ 3 ]; - vertices = new Vec3[ numberOfVertices ]; - - for ( int vertexIndex = 0; vertexIndex < numberOfVertices; vertexIndex++ ) { - line = lineVector.get( vertexIndex + 1 ); - splitLine = line.split( " " ); - vertex = new Vec3( Double.valueOf( splitLine[ 0 ] ), Double.valueOf( splitLine[ 1 ] ), Double.valueOf( splitLine[ 2 ] ) ); - vertices[ vertexIndex ] = vertex; - } - - int edgeStart = numberOfVertices + 1; - - for ( int edgeIndex = 0; edgeIndex < numberOfEdges; edgeIndex++ ) { - line = lineVector.get( edgeIndex + edgeStart ); - splitLine = line.split( " " ); - int[] edge = { Integer.valueOf( splitLine[ 0 ] ) - 1, Integer.valueOf( splitLine[ 1 ] ) - 1 }; - edges[ edgeIndex ] = edge; - } - - int faceStart = edgeStart + numberOfEdges; - - for ( int faceIndex = 0; faceIndex < numberOfFaces; faceIndex++ ) { - line = lineVector.get( faceIndex + faceStart ); - splitLine = line.split( " " ); - edgeFirst = edges[ Integer.valueOf( splitLine[ 0 ] ) - 1 ]; - edgeSecond = edges[ Integer.valueOf( splitLine[ 1 ] ) - 1 ]; - edgeThird = edges[ Integer.valueOf( splitLine[ 2 ] ) - 1 ]; - int[] vertexIndices = { getSameVertexIndex( edgeFirst, edgeSecond ), getSameVertexIndex( edgeSecond, edgeThird ), getSameVertexIndex( edgeThird, edgeFirst ) }; - faces[ faceIndex ] = vertexIndices; - } - - CoordinateSystem coordinateSystem = new CoordinateSystem(); - - while ( window.getScene().getObject( name ) != null ) { - name += "2"; - } - - mesh = new TriangleMesh ( vertices, faces ); - mesh.setSmoothingMethod( Mesh.NO_SMOOTHING ); - window.addObject( mesh, coordinateSystem, name, null ); - addUndoRecord(); -} - -/** -Import GNU Triangulated Surface from a file or from files in a directory. -*/ - -void importFiles() -{ - if ( openFileButton.getState() ) { - importFile( file ); - return; - } - - filesInDirectory = file.getParentFile().listFiles(); - - for ( int fileIndex = 0; fileIndex < filesInDirectory.length; fileIndex++ ) { - directoryFile = filesInDirectory[ fileIndex ]; - String directoryFileName = directoryFile.getName(); - - if ( directoryFileName.endsWith( ".gts" ) ) { - importFile( directoryFile ); - } - } -} - -/** -Add radio button groups to the preference widgets. - -@param radioButtonGroups radio button groups which will be added to the memorable widgets -@param widgetVector memorable widgets -*/ - -void preferencesAddRadioButtonGroups( RadioButtonGroup[] radioButtonGroups, Vector widgetVector ) -{ - for ( int radioIndex = 0; radioIndex < radioButtonGroups.length; radioIndex++ ) { - radioButtonGroup = radioButtonGroups[ radioIndex ]; - radioButtonGroupIterator = radioButtonGroup.getRadioButtons(); - - while ( radioButtonGroupIterator.hasNext() ) { - radioButton = radioButtonGroupIterator.next(); - preferencesAddWidgetWithString( radioButton, radioButton.getText(), widgetVector ); - } - } -} - -/** -Add widgets which have titles. - -@param widgets widgets which have titles -@param widgetStrings widget titles -@param widgetVector memorable widgets -*/ - -void preferencesAddWidgetsWithStrings( Widget[] widgets, String[] widgetStrings, Vector widgetVector ) -{ - for ( int widgetIndex = 0; widgetIndex < widgets.length; widgetIndex++ ) { - widget = widgets[ widgetIndex ]; - - if ( widget instanceof BCheckBox || widget instanceof BOutline || widget instanceof BTextField || widget instanceof ValueField ) { - preferencesAddWidgetWithString( widget, widgetStrings[ widgetIndex ], widgetVector ); - } - } -} - -/** -Give the widget a name and add it to the widget vector. - -@param widget widget which will be given a name -@param widgetStrings widget name -@param widgetVector memorable widgets -*/ - -void preferencesAddWidgetWithString( Widget widget, String widgetString, Vector widgetVector ) -{ - widget.setName( widgetString ); - widgetVector.add( widget ); -} - -/** -Read widget settings from preferences file. - -@param preferencesFilename preferences filename -@param widgetVector memorable widgets -*/ - -void preferencesRead( String preferencesFilename, Vector widgetVector ) -{ - preferencesFile = new File( preferencesFilename ); - - if ( !preferencesFile.canRead() ) { - return; - } - - BufferedReader preferencesReader = new BufferedReader( new FileReader( preferencesFile ) ); - - line = preferencesReader.readLine(); - - while ( line != null ) { - preferencesReadLine( line, widgetVector ); - line = preferencesReader.readLine(); - } -} - -/** -Read line of preferences and set widget to that line. - -@param line line of preferences -@param widgetVector memorable widgets -*/ - -void preferencesReadLine( String line, Vector widgetVector ) -{ - splitLine = line.split( "\t" ); - - if ( splitLine.length < 2 ) { - return; - } - - name = splitLine[ 0 ]; - - for ( int widgetIndex = 0; widgetIndex < widgetVector.size(); widgetIndex++ ) { - widget = widgetVector.elementAt( widgetIndex ); - - if ( widget.getName().equals( name ) ) { - preferencesReadWidget( splitLine[ 1 ], widget ); - - return; - } - } -} - -/** -Set widget to preferences value. - -@param value preferences value -@param widget widget to be set to value -*/ - -void preferencesReadWidget( String value, Widget widget ) -{ - if ( widget instanceof BCheckBox || widget instanceof BRadioButton ) { - widget.setState( Boolean.valueOf( value ) ); - - return; - } - - if ( widget instanceof BOutline ) { // it would be better to save the value instead of index because the list might change, but I'm lazy - bList = widget.getContent().getContent(); - selectedIndex = Integer.valueOf( value ); - bList.setSelected( selectedIndex, true ); - bList.scrollToItem( selectedIndex ); - - return; - } - - if ( widget instanceof BTextField ) { - widget.setText( value ); - - return; - } - - if ( widget instanceof ValueField ) { - widget.setValue( Double.valueOf( value ) ); - } -} - -/** -Write widget settings to preferences file. - -@param preferencesFilename preferences filename -@param widgetVector memorable widgets -*/ - -void preferencesWrite( String preferencesFilename, Vector widgetVector ) -{ - preferencesFile = new File( preferencesFilename ); - - if ( preferencesFile == null ) { - print( "Can not write preferences to " + preferencesFilename ); - - return; - } - - BufferedWriter preferencesWriter = new BufferedWriter( new FileWriter( preferencesFile ) ); - - for ( int widgetIndex = 0; widgetIndex < widgetVector.size(); widgetIndex++ ) { - widget = widgetVector.elementAt( widgetIndex ); - preferencesWriteWidget( preferencesWriter, widget ); - } - - //Close the output stream - preferencesWriter.close(); -} - -/** -Write widget settings to line of preferences. - -@param preferencesWriter buffered preferences file writer -@param widget widget to be written -*/ - -void preferencesWriteWidget( BufferedWriter preferencesWriter, Widget widget ) -{ - widgetString = widget.getName() + "\t"; - - if ( widget instanceof BCheckBox || widget instanceof BRadioButton ) { - preferencesWriter.write( widgetString + widget.getState().toString() + "\n" ); - - return; - } - - if ( widget instanceof BOutline ) { // it would be better to save the value because the list might change, but I'm lazy - BList bList = widget.getContent().getContent(); - bList = widget.getContent().getContent(); - preferencesWriter.write( widgetString + bList.getSelectedIndex().toString() + "\n" ); - - return; - } - - if ( widget instanceof BTextField ) { - preferencesWriter.write( widgetString + widget.getText() + "\n" ); - - return; - } - - if ( widget instanceof ValueField ) { - preferencesWriter.write( widgetString + widget.getValue().toString() + "\n" ); - } -} - -// Set default parameters. -directoryRadioButtonGroup = new RadioButtonGroup(); -openDirectoryButton = new BRadioButton( "Import All GNU Triangulated Surface Files in a Directory", false, directoryRadioButtonGroup ); -openFileButton = new BRadioButton( "Import File", true, directoryRadioButtonGroup ); -directoryGridContainer = new GridContainer( 1, 2 ); -directoryGridContainer.setDefaultLayout( new LayoutInfo( LayoutInfo.WEST, LayoutInfo.NONE, new Insets( 2, 2, 2, 2 ), null ) ); -directoryGridContainer.add( openDirectoryButton, 0, 0 ); -directoryGridContainer.add( openFileButton, 0, 1 ); -gnuSurfaceFilenameTextField = new BTextField( "" ); -String preferencesFilename = "import_gnu_triangulated_surface_preferences.csv"; - -Widget[] widgets = new Widget[] { directoryGridContainer }; -String[] widgetStrings = new String[] { "Open File or Directory:" }; - -// change the user interface parameters from default to preferences -Vector widgetVector = new Vector(); -RadioButtonGroup[] radioButtonGroups = new RadioButtonGroup[] { directoryRadioButtonGroup }; -preferencesAddRadioButtonGroups( radioButtonGroups, widgetVector ); -preferencesAddWidgetsWithStrings( widgets, widgetStrings, widgetVector ); -preferencesAddWidgetWithString( gnuSurfaceFilenameTextField, "GCode Filename:", widgetVector ); -preferencesRead( preferencesFilename, widgetVector ); - -dialog = new ComponentsDialog( window, "Import GNU Triangulated Surface File or Directory", widgets, widgetStrings ); - -if ( !dialog.clickedOk() ) return; - -fileChooser = new BFileChooser( BFileChooser.OPEN_FILE, "Import GNU Triangulated Surface File"); -gnuSurfaceFile = new File( gnuSurfaceFilenameTextField.getText() ); - -if ( gnuSurfaceFile.canRead() ) { - fileChooser.setSelectedFile( gnuSurfaceFile ); -} - -fileChooser.showDialog( window ); -file = fileChooser.getSelectedFile(); - -if ( file == null ) { - return; -} - -gnuSurfaceFilenameTextField.setText( file.getAbsolutePath() ); -preferencesWrite( preferencesFilename, widgetVector ); -importFiles(); diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Import Topology.bsh b/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Import Topology.bsh deleted file mode 100644 index 203229b..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Import Topology.bsh +++ /dev/null @@ -1,225 +0,0 @@ -/* - - - -*/ - -String addShape( BufferedReader bufferedReader, String line ) -{ - importShape = ImportShape(); - importShape.setBufferedReaderLine( bufferedReader, line ); - - while ( importShape.splitLine.length > 1 ) { - importShape.shouldRead = true; - - switch( importShape.firstLower ) { - - case "class": - importShape.setClass(); - break; - - case "faces": - importShape.setFaces(); - break; - - case "name": - importShape.setName(); - break; - - case "orientation": - importShape.setOrientation(); - break; - - case "origin": - importShape.setOrigin(); - break; - - case "vertexpositions": - importShape.setVertexPositions(); - break; - } - - if ( importShape.shouldRead ) { - importShape.readLine(); - } - } - - importShape.addShapeIfParametersSet(); - - return importShape.bufferedReader.readLine(); -} - -/** -Add curves and/or meshes from the file through the buffered reader. -*/ - -void addShapes( BufferedReader bufferedReader ) -{ - line = bufferedReader.readLine(); - - while ( line != null ) { - line = addShape( bufferedReader, line ); - } -} - -/** -Get a Vec3 from a string array. -*/ - -Vec3 getFromStringArray( String[] stringArray ) -{ - return new Vec3( Double.valueOf( stringArray[ 2 ] ), Double.valueOf( stringArray[ 3 ] ), Double.valueOf( stringArray[ 4 ] ) ); -} - -/** -Import the topology of a shape from the file through the buffered reader. -*/ - -ImportShape() { - BufferedReader bufferedReader = null; - String className = null; - Vector facesVector = null; - String firstLower = null; - String line = null; - String name = null; - Vec3 orientation = null; - Vec3 origin = null; - boolean shouldRead = true; - String[] splitLine = null; - Vector vertexPositionsVector = null; - -/** -Add the topology of a shape from the file through the buffered reader if all the parameters have been set. -*/ - - addShapeIfParametersSet() { - if ( className == null || name == null || orientation == null || origin == null || vertexPositionsVector == null ) { - print( "Shape has a null parameter and was not imported." ); - print( className ); - print( name ); - print( orientation ); - print( origin ); - print( vertexPositionsVector ); - return; - } - - vertexPositionsArray = vertexPositionsVector.toArray( new Vec3[ vertexPositionsVector.size() ] ); - CoordinateSystem coordinateSystem = new CoordinateSystem(); - coordinateSystem.setOrientation( orientation.x, orientation.y, orientation.z ); - coordinateSystem.setOrigin( origin ); - - while ( window.getScene().getObject( name ) != null ) { - name += "a"; - } - - if ( className.equals( "curve" ) ) { - float[] smoothness = new float[ vertexPositionsArray.length ]; - curve = new Curve( vertexPositionsArray, smoothness, Mesh.APPROXIMATING, true ); - window.addObject( curve, coordinateSystem, name, null ); - addUndoRecord(); - return; - } - - if ( facesVector == null ) { - return; - } - - if ( className.equals( "trianglemesh" ) ) { - facesArray = facesVector.toArray( new int[ facesVector.size() ][ 3 ] ); - mesh = new TriangleMesh ( vertexPositionsArray, facesArray ); - mesh.setSmoothingMethod( Mesh.NO_SMOOTHING ); - window.addObject( mesh, coordinateSystem, name, null ); - addUndoRecord(); - } - } - - addUndoRecord() { - scene = window.getScene(); - undoAdd = new UndoRecord ( window, false, UndoRecord.DELETE_OBJECT, new Object[] { new Integer( scene.getNumObjects() - 1 ) } ); - window.setUndoRecord( undoAdd ); - } - - readLine() { - line = bufferedReader.readLine(); - setSplitLine(); - } - - setBufferedReaderLine( BufferedReader argumentBufferedReader, String argumentLine ) { - bufferedReader = argumentBufferedReader; - line = argumentLine; - setSplitLine(); - } - - setClass() { - className = splitLine[ 1 ].toLowerCase(); - } - - setFaces() { - readLine(); - shouldRead = false; - facesVector = new Vector(); - - while ( splitLine[ 0 ].toLowerCase().equals( "face" ) ) { - int[] face = { Integer.valueOf( splitLine[ 2 ] ), Integer.valueOf( splitLine[ 3 ] ), Integer.valueOf( splitLine[ 4 ] ) }; - facesVector.add( face ); - readLine(); - } - } - - setName() { - name = splitLine[ 1 ]; - } - - setOrientation() { - orientation = getFromStringArray( splitLine ); - } - - setOrigin() { - origin = getFromStringArray( splitLine ); - } - - setSplitLine() { - if ( line == null ) { - splitLine = new String[] { "" }; - return; - } - - splitLine = line.split( "," ); - firstLower = splitLine[ 0 ].toLowerCase(); - } - - setVertexPositions() { - readLine(); - shouldRead = false; - vertexPositionsVector = new Vector(); - - while ( splitLine[ 0 ].toLowerCase().equals( "vertex position" ) ) { - vertexPositionsVector.add( getFromStringArray( splitLine ) ); - readLine(); - } - } - - return this; -} - -// Get parameters. - -fileChooser = new BFileChooser( BFileChooser.OPEN_FILE, "Import Comma Separated Values Topology"); -fileChooser.showDialog( window ); -filename = fileChooser.getSelectedFile(); - -if ( filename == null ) { - return; -} - -bufferedReader = new BufferedReader( new FileReader( filename ) ); -addShapes( bufferedReader ); \ No newline at end of file diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Platonic Solid.bsh b/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Platonic Solid.bsh deleted file mode 100644 index 6913a27..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Platonic Solid.bsh +++ /dev/null @@ -1,391 +0,0 @@ -/* - - - -*/ - -/* Copyright (C) 2004 by Fran�ois Guillet - - This program is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - PARTICULAR PURPOSE. See the GNU General Public License for more details. */ - -//Script localization test - -HashMap translations = new HashMap(); -if (Translate.getLocale().equals(Locale.FRENCH)) -{ - translations.put("Hexahedron", "Hexah\u00E8dre (6)"); - translations.put("Tetrahedron", "Tetrah\u00E8dre (4)"); - translations.put("Octahedron", "Octah\u00E8dre (8)"); - translations.put("Dodecahedron", "Dodecah\u00E8dre (12)"); - translations.put("Icosahedron", "Icosah\u00E8dre (20)"); - translations.put("centeredFaces", "sommets aux centres des faces"); - translations.put("selectPolyhedron", "S\u00E9lectionnez un polyh\u00E8dre :"); - translations.put("noSmoothing", "Pas de lissage" ); - translations.put("smoothShading", "Ombrage doux" ); - translations.put("interpolating", "Interpolation" ); - translations.put("approximating", "Approximation" ); - translations.put("polyhedron", "Polyh\u00E8dre:" ); - translations.put("faceCenteredMesh", "Maillage face centr\u00E9e" ); - translations.put("radius", "Rayon :" ); - translations.put("smoothingMethod", "M\u00E9thode de lissage:"); - translations.put("verticesSmoothness", "Lissage des sommets :"); - translations.put("edgesSmoothness", "Lissages des ar\u00EAtes :"); - translations.put("texture", "Texture :"); - translations.put("material", "Mat\u00E9riau :"); - translations.put("hexahedron", "Hexah\u00E8dre"); - translations.put("tetrahedron", "Tetrah\u00E8dre"); - translations.put("octahedron", "Octah\u00E8dre"); - translations.put("dodecahedron", "Dodecah\u00E8dre"); - translations.put("icosahedron", "Icosah\u00E8dre"); -} -else -{ - translations.put("Hexahedron", "Hexahedron (6)"); - translations.put("Tetrahedron", "Tetrahedron (4)"); - translations.put("Octahedron", "Octahedron (8)"); - translations.put("Dodecahedron", "Dodecahedron (12)"); - translations.put("Icosahedron", "Icosahedron (20)"); - translations.put("centeredFaces", "vertices at faces centers"); - translations.put("selectPolyhedron", "Select a polyhedron:"); - translations.put("noSmoothing", "No Smoothing" ); - translations.put("smoothShading", "Smooth Shading" ); - translations.put("interpolating", "Interpolating" ); - translations.put("approximating", "Approximating" ); - translations.put("polyhedron", "Polyhedron:" ); - translations.put("faceCenteredMesh", "Face centered mesh" ); - translations.put("radius", "Radius:" ); - translations.put("smoothingMethod", "Smoothing Method:"); - translations.put("verticesSmoothness", "Vertices Smoothness:"); - translations.put("edgesSmoothness", "Edges smoothness:"); - translations.put("texture", "Texture:"); - translations.put("material", "Material:"); - translations.put("hexahedron", "Hexahedron"); - translations.put("tetrahedron", "Tetrahedron"); - translations.put("octahedron", "Octahedron"); - translations.put("dodecahedron", "Dodecahedron"); - translations.put("icosahedron", "Icosahedron"); -} -//end of script localization test - - -//given a set of faces, this function computes the centers of the faces and adds them to the list of vertices -Vec3[] completeVertices(Vec3[] vert, int[][] polyFaces, int vertNum) -{ vertices = new Vec3[vert.length + polyFaces.length]; - - for (i = 0 ; i < vert.length ; ++i) - vertices[i] = vert[i]; - - for (i = vertNum; i < vertNum + polyFaces.length; ++i) - { v = new Vec3(); - for (j = 0 ; j < polyFaces[i - vertNum].length; ++j) - v.add(vertices[polyFaces[i - vertNum][j]]); - v.scale(1.0/polyFaces[i - vertNum].length); - vertices[i] = v; - } - - return vertices; -} - -//given a set of faces and a set of vertices, -//this function computes centered faces to form a triangular mesh -//presumably equivalent to subdivide face command in the mesh editor -TriangleMesh triangulateFaces(Vec3[] vertices, int[][] polyFaces, int vertNum) -{ vertices = completeVertices(vertices, polyFaces, vertNum); - - faces = new int[polyFaces.length * polyFaces[0].length][3]; - - f = 0; - for (i = 0 ; i < polyFaces.length ; ++i) - { for (j = 0; j < polyFaces[i].length ; ++j) - { if (j < polyFaces[i].length-1) - { faces[f][0] = polyFaces[i][j]; - faces[f][1] = polyFaces[i][j+1]; - faces[f][2] = vertNum + i; - } - else - { faces[f][0] = polyFaces[i][j]; - faces[f][1] = polyFaces[i][0]; - faces[f][2] = vertNum + i; - } - ++f; - } - } - mesh = new TriangleMesh(vertices, faces); - return mesh; -} - - -scene = window.getScene(); - -//setup the list of polyhedra -polyList = new BList(new String [] { - translations.get("Tetrahedron"), - translations.get("Hexahedron"), - translations.get("Octahedron"), - translations.get("Dodecahedron"), - translations.get("Icosahedron") -}); -polyList.setPreferredVisibleRows(5); -polyList.setSelected(0, true); - -//face centered checkbox -centeredCheckbox = new BCheckBox(translations.get("centeredFaces"), false); - -//radius value field -radiusValueField = new ValueField(1.0, ValueField.NONNEGATIVE); - -//smoothing method -smoothList = new BList(new String [] { - translations.get("noSmoothing"), - translations.get("smoothShading"), - translations.get("interpolating"), - translations.get("approximating") -}); -smoothList.setPreferredVisibleRows(4); -smoothList.setSelected(0, true); - -//vertices smoothness value field -vertSmoothnessValueField = new ValueField(1.0, ValueField.NONNEGATIVE); - -//edges smoothness value field -edgesSmoothnessValueField = new ValueField(1.0, ValueField.NONNEGATIVE); - -// get list of scene textures -numTex=scene.getNumTextures(); -textureList=new BList(); -textureList.setPreferredVisibleRows(3 < numTex ? 3 : numTex); -for (i = 0 ; i < numTex ; i++) -{ - iTex=scene.getTexture(i); - name=iTex.getName(); - textureList.add(name); -} -textureList.setSelected(0, true); - -// get list of materials -numMat=scene.getNumMaterials(); -materialList=new BList(); -materialList.setPreferredVisibleRows(3 < numMat + 1 ? 3 : numMat + 1); -materialList.add("none"); -for (i = 0 ; i < numMat ; i++) -{ - iMat=scene.getMaterial(i); - name=iMat.getName(); - materialList.add(name); -} -materialList.setSelected(0, true); - - -dlg = new ComponentsDialog(window, translations.get("selectPolyhedron"), -new Widget [] { UIUtilities.createScrollingList(polyList), centeredCheckbox, radiusValueField, UIUtilities.createScrollingList(smoothList), vertSmoothnessValueField, edgesSmoothnessValueField, UIUtilities.createScrollingList(textureList), UIUtilities.createScrollingList(materialList)}, -new String [] { translations.get("polyhedron"), translations.get("faceCenteredMesh"), translations.get("radius"), translations.get("smoothingMethod"), translations.get("verticesSmoothness"), translations.get("edgesSmoothness"), translations.get("texture"), translations.get("material") } ); - -if (!dlg.clickedOk()) return; - -centered = centeredCheckbox.getState(); - -switch (polyList.getSelectedIndex()) -{ case 0 : //tetrahedra - vertices = new Vec3[4]; // 4 vertices + 4 faces - vertices[0] = new Vec3(0, 0, 1); - vertices[1] = new Vec3(2*Math.sqrt(2)/3, 0, -1.0/3.0); - vertices[2] = new Vec3(-Math.sqrt(2)/3, Math.sqrt(6)/3, -1.0/3.0); - vertices[3] = new Vec3(-Math.sqrt(2)/3, -Math.sqrt(6)/3, -1.0/3.0); - int[][] faces = {{ 0, 1, 2 }, { 0, 2, 3 }, { 0, 3, 1 }, { 1, 3, 2 }}; - if (centered) - mesh = triangulateFaces(vertices, faces, 4); - else - mesh = new TriangleMesh(vertices, faces); - name = translations.get("tetrahedron") + (centered ? " FC" : ""); - break; - - case 1 : //hexahedron - vertices = new Vec3[8]; // 8 vertices + 6 faces - vertices[0] = new Vec3(-1, -1, -1); - vertices[1] = new Vec3(1, -1, -1); - vertices[2] = new Vec3(1, 1, -1); - vertices[3] = new Vec3(-1, 1, -1); - vertices[4] = new Vec3(-1, -1, 1); - vertices[5] = new Vec3(1, -1, 1); - vertices[6] = new Vec3(1, 1, 1); - vertices[7] = new Vec3(-1, 1, 1); - for (i = 0 ; i < 8 ; ++i) - vertices[i].scale(1.0/Math.sqrt(3)); - - //polygon faces when different from triangular faces - int[][] hexaFaces = {{ 0, 3, 2, 1 }, { 0, 1, 5, 4 }, { 0, 4, 7, 3 }, - { 6, 5, 1, 2 }, { 6, 2, 3, 7 }, { 6, 7, 4, 5 } }; - - //triangular faces - int[][] faces = {{ 0, 3, 2}, { 0, 2, 1}, { 0, 1, 5}, { 0, 5, 4}, { 0, 4, 7}, {0, 7, 3}, - { 6, 5, 1}, { 6, 1, 2}, { 6, 2, 3}, { 6, 3, 7}, { 6, 7, 4}, {6, 4, 5}}; - if (centered) - mesh = triangulateFaces(vertices, hexaFaces, 8); - else - mesh = new TriangleMesh(vertices, faces); - name = translations.get("hexahedron") + (centered ? " FC" : ""); - break; - - case 2 : //octahedron - vertices = new Vec3[6]; // 6 vertices + 8 faces - vertices[0] = new Vec3(1, 0, 0); - vertices[1] = new Vec3(-1, 0, 0); - vertices[2] = new Vec3(0, 1, 0); - vertices[3] = new Vec3(0, -1, 0); - vertices[4] = new Vec3(0, 0, 1); - vertices[5] = new Vec3(0, 0, -1); - - int[][] faces = { - { 4, 0, 2 }, { 4, 2, 1 }, { 4, 1, 3 }, { 4, 3, 0 }, - { 5, 2, 0 }, { 5, 1, 2 }, { 5, 3, 1 }, { 5, 0, 3 } - }; - - if (centered) - mesh = triangulateFaces(vertices, faces, 6); - else - mesh = new TriangleMesh(vertices, faces); - - name = translations.get("octahedron") + (centered ? " FC" : ""); - break; - - case 3 : //dodecahedron - vertices = new Vec3[20]; // 20 vertices + 12 faces - a = 1/Math.sqrt(3); - b = Math.sqrt( (3.0 - Math.sqrt(5)) /6.0); - c = Math.sqrt( (3.0 + Math.sqrt(5)) /6.0); - vertices[0] = new Vec3(a, a, a); - vertices[1] = new Vec3(a, a, -a); - vertices[2] = new Vec3(a, -a, a); - vertices[3] = new Vec3(a, -a, -a); - vertices[4] = new Vec3(-a, a, a); - vertices[5] = new Vec3(-a, a, -a); - vertices[6] = new Vec3(-a, -a, a); - vertices[7] = new Vec3(-a, -a, -a); - vertices[8] = new Vec3(b, c, 0); - vertices[9] = new Vec3(-b, c, 0); - vertices[10] = new Vec3(b, -c, 0); - vertices[11] = new Vec3(-b, -c, 0); - vertices[12] = new Vec3(c, 0, b); - vertices[13] = new Vec3(c, 0, -b); - vertices[14] = new Vec3(-c, 0, b); - vertices[15] = new Vec3(-c, 0, -b); - vertices[16] = new Vec3(0, b, c); - vertices[17] = new Vec3(0, -b, c); - vertices[18] = new Vec3(0, b, -c); - vertices[19] = new Vec3(0, -b, -c); - - int[][] faces = { //*quite* dull - { 0, 8, 9 }, { 0, 12, 13 }, { 0, 16, 17 }, { 8, 1, 18 }, - { 12, 2, 10 }, { 16, 4, 14 }, { 9, 5, 15 }, { 6, 11, 10 }, - { 3, 19, 18 }, { 7, 15, 5 }, { 7, 11, 6 }, { 7, 19, 3 }, - { 0, 9, 4 }, { 0, 13, 1 }, { 0, 17, 2 }, { 8, 18, 5 }, - { 12, 10, 3 }, { 16, 14, 6 }, { 9, 15, 14 }, { 6, 10, 2 }, - { 3, 18, 1 }, { 7, 5, 18 }, { 7, 6, 14 }, { 7, 3, 10 }, - { 0, 4, 16 }, { 0, 1, 8 }, { 0, 2, 12 }, { 8, 5, 9 }, - { 12, 3, 13 }, { 16, 6, 17 }, { 9, 14, 4 }, { 6, 2, 17 }, - { 3, 1, 13 }, { 7, 18, 19 }, { 7, 14, 15 }, { 7, 10, 11 } - }; - - int[][] dodeFaces = { - { 0, 8, 9, 4, 16}, { 0, 16, 17, 2, 12}, { 12, 2, 10, 3, 13}, - { 9, 5, 15, 14, 4}, { 3, 19, 18, 1, 13}, { 7, 11, 6, 14, 15}, - { 0, 12, 13, 1, 8}, { 8, 1, 18, 5, 9}, { 16, 4, 14, 6, 17}, - { 6, 11, 10, 2, 17}, { 7, 15, 5, 18, 19}, { 7, 19, 3, 10, 11} - }; - - if (centered) - mesh = triangulateFaces(vertices, dodeFaces, 20); - else - mesh = new TriangleMesh(vertices, faces); - - name = translations.get("dodecahedron") + (centered ? " FC" : ""); - break; - - case 4 : //icosahedron - vertices = new Vec3[12]; // 12 vertices + 20 faces - t = ( 1.0 + Math.sqrt(5) )/2.0; - vertices[0] = new Vec3(t, 1, 0); - vertices[1] = new Vec3(-t, 1, -0); - vertices[2] = new Vec3(t, -1, 0); - vertices[3] = new Vec3(-t, -1, 0); - vertices[4] = new Vec3(1, 0, t); - vertices[5] = new Vec3(1, 0, -t); - vertices[6] = new Vec3(-1, 0, t); - vertices[7] = new Vec3(-1, 0, -t); - vertices[8] = new Vec3(0, t, 1); - vertices[9] = new Vec3(0, -t, 1); - vertices[10] = new Vec3(0, t, -1); - vertices[11] = new Vec3(0, -t, -1); - for (i = 0 ; i < 12 ; ++i) - vertices[i].scale( 1.0 / Math.sqrt( 1.0 + t*t) ); - - int[][] faces = { - { 0, 8, 4 }, { 0, 5, 10 }, { 2, 4, 9 }, { 2, 11, 5 }, - { 1, 6, 8 }, { 1, 10, 7 }, { 3, 9, 6 }, { 3, 7, 11 }, - { 0, 10, 8 }, { 1, 8, 10 }, { 2, 9, 11 }, { 3, 11, 9 }, - { 4, 2, 0 }, { 5, 0, 2 }, { 6, 1, 3 }, { 7, 3, 1 }, - { 8, 6, 4 }, { 9, 4, 6 }, { 10, 5, 7 }, { 11, 7, 5 } - }; - - - if (centered) - mesh = triangulateFaces(vertices, faces, 12); - else - mesh = new TriangleMesh(vertices, faces); - - name = translations.get("icosahedron") + (centered ? " FC" : ""); - break; - default : - return; -} - -//set vertices smoothness and scale mesh in the process -meshVertices = mesh.getVertices(); -radius = radiusValueField.getValue(); -for ( i = 0 ; i < meshVertices.length ; ++i) -{ meshVertices[i].smoothness = (float) vertSmoothnessValueField.getValue(); - meshVertices[i].r.scale(radius); -} - -//set edges smoothness -meshEdges = mesh.getEdges(); -for ( i = 0 ; i < meshEdges.length ; ++i) - meshEdges[i].smoothness = (float) edgesSmoothnessValueField.getValue(); - -//set mesh smoothing method -mesh.setSmoothingMethod(smoothList.getSelectedIndex()); - -//set texture -//tex = scene.getTexture(textureList.getSelectedIndex()); -//mesh.setTexture(tex, tex.getDefaultMapping()); - -//set material -matIndex = materialList.getSelectedIndex(); -if ( matIndex > 0 ) -{ mat = scene.getMaterial(matIndex-1); - mesh.setMaterial(mat, mat.getDefaultMapping()); -} - -//we're done -window.addObject(mesh, new CoordinateSystem(), name, null); - - diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Truncated Teardrop Shaper.bsh b/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Truncated Teardrop Shaper.bsh deleted file mode 100644 index 766c3ac..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/Art of Illusion Scripts/Truncated Teardrop Shaper.bsh +++ /dev/null @@ -1,119 +0,0 @@ -/* - - -*/ - -do -{ - scene = window.getScene(); - - directionType = new RadioButtonGroup(); - up = new BRadioButton("Up", false, directionType); - down = new BRadioButton("Down", false, directionType); - left = new BRadioButton("Left", false, directionType); - right = new BRadioButton("Right", false, directionType); - - directional = new GridContainer(2, 2); - directional.setDefaultLayout(new LayoutInfo(LayoutInfo.WEST, LayoutInfo.NONE, new Insets(2, 2, 2, 2), null)); - directional.add(up, 0, 0); - directional.add(down, 0, 1); - directional.add(left, 1, 0); - directional.add(right, 1, 1); - - vertexValueField = new ValueField(45, ValueField.NONNEGATIVE); - radiusValueField = new ValueField(1.0, ValueField.NONNEGATIVE); - maxErrorValueField = new ValueField(0.05, ValueField.NONNEGATIVE); - directionValueField = new ValueField(0.0, ValueField.NONNEGATIVE); - truncationValueField = new ValueField(0.0, ValueField.NONNEGATIVE); - - dlg = new ComponentsDialog(window, "TearDrop Tool" , - new Widget [] { directional, directionValueField, vertexValueField, truncationValueField, radiusValueField, maxErrorValueField }, - new String [] { "Orientation about z-axis: ", "or specific rotation about z-axis (degrees): ", "Vertex angle (degrees): ", "Truncation: ", "Radius: ", "Max error: " } ); - - if (!dlg.clickedOk()) return; - - theta = vertexValueField.getValue() / 180 * Math.PI; - radius = radiusValueField.getValue(); - maxError = maxErrorValueField.getValue(); - directionAngle = directionValueField.getValue() / 180 * Math.PI; - - errorAngle = Math.acos((radius - maxError) / radius); // inverse cosine - -// numberSides = Math.ceil(((2 * Math.PI) - 2 * (Math.PI / 2 - theta)) / errorAngle); // rounded up - numberSides = Math.ceil(((2 * Math.PI) - 2 * (Math.PI / 2 - theta)) / errorAngle) + 1; // rounded up - - if (numberSides <= 10) - new MessageDialog(window, "Please decrease the value of the maximum error"); -} -while (numberSides < 10); - - -// Setting the orientation of the teardrop shape depending on the outcome of Radio Buttons -if (up.getState()) - directionAngle = Math.PI / 2; - -if (down.getState()) - directionAngle = (3 * Math.PI) / 2; - -if (left.getState()) - directionAngle = Math.PI; - -if (right.getState()) - directionAngle = 0; - - -Vec3[] v = new Vec3[numberSides]; -float[] smoothness = new float[numberSides]; - -//double phi = ((2.0 * Math.PI) - (2.0 * ((Math.PI / 2) - theta))) / (numberSides - 2); -double phi = ((2.0 * Math.PI) - (2.0 * ((Math.PI / 2) - theta))) / (numberSides - 3); - -double angle = ((Math.PI / 2.0) - theta); - -//for (int i = 0 ; i < (numberSides - 1) ; i++) -for (int i = 0 ; i < (numberSides - 2) ; i++) -{ - x1 = Math.cos(angle + phi * i); - y1 = Math.sin(angle + phi * i); - x2 = x1 * Math.cos(directionAngle) - y1 * Math.sin(directionAngle); // rotational vectors - x - y2 = y1 * Math.cos(directionAngle) + x1 * Math.sin(directionAngle); // rotational vectors - y - v[i] = new Vec3(x2, y2, 0); - v[i].scale(radius); - smoothness[i] = 0; -} - -// final vertex point at the sharp tip -//x3 = Math.cos(directionAngle) * (radius / Math.sin(theta)); -//y3 = Math.sin(directionAngle) * (radius / Math.sin(theta)); -//v[numberSides - 2.0] = new Vec3(x3, y3, 0); -truncationToVertex = truncationValueField.getValue() * (2 - Math.sqrt(2)); -xTip = Math.cos(directionAngle) * (radius / Math.sin(theta)); -yTip = Math.sin(directionAngle) * (radius / Math.sin(theta)); -vTip = new Vec3(xTip, yTip, 0); -vLast = v[numberSides - 3.0]; -vFromTipToLast = vLast.minus( vTip ); -vFromTipToLast.scale( truncationToVertex ); -v[numberSides - 2.0] = vTip.plus( vFromTipToLast ); -vStart = v[0]; -vFromTipToStart = vStart.minus( vTip ); -vFromTipToStart.scale( truncationToVertex ); -x4 = xTip + 0.2; -y4 = yTip + 0.3; -v[numberSides - 1.0] = vTip.plus( vFromTipToStart ); - -name = "Truncated Teardrop (" + numberSides + " sides)"; - -tolerance = 0.02; //surface accuracy - -curve = new Curve(v, smoothness, Mesh.APPROXIMATING, true); -window.addObject(curve, new CoordinateSystem(), name, null); - -// Finished \ No newline at end of file diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/RepRapArduinoSerialSender.py b/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/RepRapArduinoSerialSender.py deleted file mode 100644 index d5ce0ba..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/RepRapArduinoSerialSender.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -""" -Extrude requires pySerial installed for this module to work. If you are using Fedora it is available on yum -(run "sudo yum install pyserial"). To actually control the reprap requires write access to the serial device, -running as root is one way to get that access. - -Created by Brendan Erwin on 2008-05-21. -Copyright (c) 2008 Brendan Erwin. All rights reserved. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -""" - -try: - import serial # Import the pySerial modules. -except: - print('You do not have pySerial installed, which is needed to control the serial port.') - print('Information on pySerial is at:\nhttp://pyserial.wiki.sourceforge.net/pySerial') - -import os -import sys -import time - - -class RepRapArduinoSerialSender: - """ - A utility class for communication with the Arduino from python. - Intended for g-code only. Raises ValueException if the arduino - returns an unexpected response. Usually caused by sending invalid - g-code. - """ - - _verbose = False - block = "empty" - - def __init__(self, port, baud, verbose=False): - """ - Opens the serial port and prepares for writing. - port MUST be set, and values are operating system dependant. - """ - self._verbose = verbose - - if self._verbose: - print >> sys.stdout, "Opening serial port: " + port - - #Timeout value 10" max travel, 1RPM, 20 threads/in = 200 seconds - self.ser = serial.Serial(port, baud, timeout=200) - - if self._verbose: - print >> sys.stdout, "Serial Open?: " + str(self.ser.isOpen()) - print >> sys.stdout, "Baud Rate: " + str(self.ser.baudrate) - - def reset(self): - """ - Resets the arduino by droping DTR for 1 second - This will then wait for a response ("ready") and return. - """ - #Reboot the arduino, and wait for it's response - if self._verbose: - print "Resetting arduino..." - - self.ser.setDTR(0) - # There is presumably some latency required. - time.sleep(1) - self.ser.setDTR(1) - self.read("Start") - - def write(self, block): - """ - Writes one block of g-code out to arduino and waits for an "ok". - This version will wait for an "ok" before returning and prints any intermediate output received. - No error will be raised if non-ok response is received. Loop in read() is infinite if "ok" - does not come back! - This routine also removes all whitespace before sending it to the arduino, - which is handy for gcode, but will screw up if you try to do binary communications. - """ - if self._verbose: - print "> " + block - - # The arduino GCode interperter firmware doesn't like whitespace - # and if there's anything other than space and tab, we have other problems. - block=block.strip() - block=block.replace(' ','') - block=block.replace("\t",'') - #Skip blank blocks. - if len(block) == 0: - return - - self.ser.write(block + "\n") - self.read("OK") - - def read(self, expect=None): - """ - This routine should never be called directly. It's used by write() and reset() - to read a one-line response from the Arduino. - This version will wait for an "ok" before returning and prints any intermediate output received. - No error will be raised if non-ok response is received. Loop is infinite if "ok" - does not come back! - """ - #The g-code firmware returns exactly ONE line per block of gcode sent. - #Unless it is M104, M105 or other code that returns info!! - #It WILL return "ok" once the command has finished sending and completed. - while True: - response = self.ser.readline().strip() - if expect is None: - return - - if expect.lower() in response.lower(): - if self._verbose: - print "< " + response - return - else: - #Just print the response since it is useful data or an error message - print "< " + response - - - def close(): - """ - Closes the serial port, terminating communications with the arduino. - """ - if self._verbose: - print >> sys.stdout, "Closing serial port." - self.ser.close() - - if self._verbose: - print >> sys.stdout, "Serial Open?: " + str(self.ser.isOpen()) diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/__init__.py b/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/__init__.py deleted file mode 100644 index 036c122..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. - -import os -import sys - -numberOfLevelsDeepInPackageHierarchy = 2 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/demo.py b/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/demo.py deleted file mode 100644 index c5cb182..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/demo.py +++ /dev/null @@ -1,24 +0,0 @@ -try: - import serial -except: - print('You do not have pySerial installed, which is needed to control the serial port.') - print('Information on pySerial is at:\nhttp://pyserial.wiki.sourceforge.net/pySerial') -import reprap, time # Import the reprap and pySerial modules. - -reprap.serial = serial.Serial(0, 19200, timeout = reprap.snap.messageTimeout) # Initialise serial port, here the first port (0) is used. -reprap.cartesian.x.active = True # These devices are present in network, will automatically scan in the future. -reprap.cartesian.y.active = True -reprap.cartesian.z.active = True -reprap.extruder.active = True -# The module is now ready to recieve commands # -moveSpeed = 220 -reprap.cartesian.homeReset( moveSpeed, True ) # Send all axies to home position. Wait until arrival. -reprap.cartesian.seek( (1000, 1000, 0), moveSpeed, True ) # Seek to (1000, 1000, 0). Wait until arrival. -time.sleep(2) # Pause. -reprap.cartesian.seek( (500, 1000, 0), moveSpeed, True ) # Seek to (500, 1000, 0). Wait until arrival. -time.sleep(2) -reprap.cartesian.seek( (1000, 500, 0), moveSpeed, True ) # Seek to (1000, 500, 0). Wait until arrival. -time.sleep(2) -reprap.cartesian.seek( (100, 100, 0), moveSpeed, True ) # Seek to (100, 100, 0). Wait until arrival. -reprap.cartesian.homeReset( moveSpeed, True ) # Send all axies to home position. Wait until arrival. -reprap.cartesian.free() # Shut off power to all motors. diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/example.py b/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/example.py deleted file mode 100644 index 640bf8d..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/example.py +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/python -try: - import serial -except: - print('You do not have pySerial installed, which is needed to control the serial port.') - print('Information on pySerial is at:\nhttp://pyserial.wiki.sourceforge.net/pySerial') - -import reprap, time, sys - -#reprap.snap.printOutgoingPackets = True -#reprap.snap.printIncomingPackets = True -#reprap.snap.printFailedPackets = True -#reprap.printDebug = True - -#work surface approx x 2523, y 2743 - -#reprap.serial = serial.Serial(0, 19200, timeout = reprap.snap.messageTimeout) -reprap.serial = serial.Serial(0, 19200, timeout = 60) - -reprap.cartesian.x.active = True # these devices are present in network -reprap.cartesian.y.active = True -reprap.cartesian.z.active = True -reprap.extruder.active = True - -reprap.cartesian.x.setNotify() -reprap.cartesian.y.setNotify() -reprap.cartesian.z.setNotify() -reprap.cartesian.x.limit = 2523 -#reprap.cartesian.y.limit = 2743 -reprap.cartesian.y.limit = 2000 - -def printPos(): - x, y, z = reprap.cartesian.getPos() - print "Location [" + str(x) + ", " + str(y) + ", " + str(z) + "]" - - -print "================================================================" - - -########### control of cartesian frame as a whole ######### - -#stop all steppers -if sys.argv[1] == "stop": - reprap.cartesian.stop() - -#goto 0,0 -if sys.argv[1] == "reset": - reprap.cartesian.homeReset( 200, True ) - #time.sleep(2) - printPos() - -#print current positon -if sys.argv[1] == "pos": - printPos() - -#goto a specific location -if sys.argv[1] == "goto": - reprap.cartesian.seek( ( int(sys.argv[2]), int(sys.argv[3]), 0 ), 200, False) - printPos() - -#goto a specific location (use sync) -if sys.argv[1] == "gotos": - reprap.cartesian.syncSeek( ( int(sys.argv[2]), int(sys.argv[3]), 0 ), 200, False) - printPos() - -if sys.argv[1] == "power": - reprap.cartesian.setPower( int( sys.argv[2] ) ) # This is a value from 0 to 63 (6 bits) - - -#test routine -if sys.argv[1] == "go": #stepper test - reprap.cartesian.seek( (1000, 1000, 0), 200, True ) - time.sleep(2) - reprap.cartesian.seek( (500, 1000, 0), 200, True ) - time.sleep(2) - reprap.cartesian.seek( (500, 500, 0), 200, True ) - time.sleep(2) - reprap.cartesian.seek( (10, 10, 0), 200, True ) - -#free motors (switch off all coils) -if sys.argv[1] == "free": - reprap.axies.free(reprap.axisX) - reprap.axies.free(reprap.axisY) - -############## control of individual steppers ############# - -#spin stepper -if sys.argv[1] == "run": # run axis - if sys.argv[2] == "x": - reprap.cartesian.x.forward( int(sys.argv[3]) ) - elif sys.argv[2] == "y": - reprap.cartesian.y.forward( int(sys.argv[3]) ) - -#spin stepper in reverse -if sys.argv[1] == "runb": #runb axis - if sys.argv[2] == "x": - reprap.axies.backward( reprap.axisX, int(sys.argv[3]) ) - elif sys.argv[2] == "y": - reprap.axies.backward( reprap.axisY, int(sys.argv[3]) ) - -if sys.argv[1] == "step": - if sys.argv[2] == "x": - reprap.cartesian.x.forward1() - elif sys.argv[2] == "y": - reprap.cartesian.y.forward1() - -################# control of extruder ##################### - -#test extrder motor -elif sys.argv[1] == "motor": - nn = 0 - while 1: - if nn > 0: - nn = 0 - else: - nn = 150 - reprap.extruder.setMotor(reprap.CMD_REVERSE, nn) - time.sleep(1) - -elif sys.argv[1] == "getinfo": - mtype = reprap.extruder.getModuleType() - version = reprap.extruder.getVersion() - print "module", mtype, "version", version - -elif sys.argv[1] == "heat": - reprap.extruder.setHeat(255, 255, 255, 255) - -#setHeat(self, lowHeat, highHeat, tempTarget, tempMax - -elif sys.argv[1] == "temp": - print "Temp is ", reprap.extruder.getTemp() - -elif sys.argv[1] == "setref": - reprap.extruder.setVoltateReference( int(sys.argv[2]) ) - - - - -############### scan network for devices ################### - -#scan snap network -elif sys.argv[1] == "scan": - reprap.scanNetwork() - diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/extrude.py b/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/extrude.py deleted file mode 100644 index 52fda3e..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/extrude.py +++ /dev/null @@ -1,390 +0,0 @@ -""" -Extrude is a script to display and extrude a gcode file. - -It controls the extruder and movement. It can read linear and helical move commands. It saves a log file with the suffix _log. - -To run extrude, install python 2.x on your machine, which is avaliable from http://www.python.org/download/ - -Then in the folder which extrude is in, type 'python' in a shell to run the python interpreter. Finally type 'import extrude' to import -this program. Extrude requires pySerial installed for this module to work. If you are using Fedora it is available on yum -(run "sudo yum install pyserial"). To actually control the reprap requires write access to the serial device, running as root is -one way to get that access. - - -This example displays and extrudes a gcode file. This example is run in a terminal as root in the folder which contains -Hollow Square.gcode, and extrude.py. - ->>> import extrude -Extrude has been imported. -The gcode files in this directory that are not log files are the following: -['Hollow Square.gcode'] - - ->>> extrude.display() -File Hollow Square.gcode is being displayed. -reprap.serial = serial.Serial(0, 19200, timeout = 60) -reprap.cartesian.x.active = True -reprap.cartesian.y.active = True -reprap.cartesian.z.active = True -reprap.extruder.active = True -reprap.cartesian.x.setNotify() -reprap.cartesian.y.setNotify() -reprap.cartesian.z.setNotify() -reprap.cartesian.x.limit = 2523 -reprap.cartesian.y.limit = 2000 -reprap.cartesian.homeReset( 200, True ) -( GCode generated by March 29,2007 Skeinforge ) -( Extruder Initialization ) -M100 P210 -M103 -reprap.extruder.setMotor(reprap.CMD_REVERSE, 0) -.. -many lines of gcode and extruder commands -.. -reprap.cartesian.homeReset( 600, True ) -reprap.cartesian.free() -The gcode log file is saved as Hollow Square_log.gcode - - ->>> extrude.displayFile("Hollow Square.gcode") -File Hollow Square.gcode is being displayed. -.. -The gcode log file is saved as Hollow Square_log.gcode - - ->>> extrude.displayFiles(["Hollow Square.gcode"]) -File Hollow Square.gcode is being displayed. -.. -The gcode log file is saved as Hollow Square_log.gcode - - ->>> extrude.displayText(" -( GCode generated by March 29,2007 Skeinforge ) -( Extruder Initialization ) -.. -many lines of gcode -.. -") - -reprap.serial = serial.Serial(0, 19200, timeout = 60) -reprap.cartesian.x.active = True -reprap.cartesian.y.active = True -reprap.cartesian.z.active = True -reprap.extruder.active = True -reprap.cartesian.x.setNotify() -reprap.cartesian.y.setNotify() -reprap.cartesian.z.setNotify() -reprap.cartesian.x.limit = 2523 -reprap.cartesian.y.limit = 2000 -reprap.cartesian.homeReset( 200, True ) -( GCode generated by March 29,2007 Skeinforge ) -( Extruder Initialization ) -M100 P210 -M103 -reprap.extruder.setMotor(reprap.CMD_REVERSE, 0) -.. -many lines of gcode and extruder commands -.. -reprap.cartesian.homeReset( 600, True ) -reprap.cartesian.free() - - -Note: On my system the reprap is not connected, so I get can not connect messages, like: - ->>> extrude.extrude() -File Hollow Square.gcode is being extruded. -reprap.serial = serial.Serial(0, 19200, timeout = 60) -reprap.cartesian.x.active = True -reprap.cartesian.y.active = True -reprap.cartesian.z.active = True -reprap.extruder.active = True -reprap.cartesian.x.setNotify() -Error: Serial timeout -Error: ACK not recieved -.. - -On a system where a reprap is connected to the serial port, you should get the following: - ->>> extrude.extrude() -File Hollow Square.gcode is being extruded. -.. -The gcode log file is saved as Hollow Square_log.gcode - - ->>> extrude.extrudeFile("Hollow Square.gcode") -File Hollow Square.gcode is being extruded. -.. -The gcode log file is saved as Hollow Square_log.gcode - - ->>> extrude.extrudeFiles(["Hollow Square.gcode"]) -File Hollow Square.gcode is being extruded. -.. -The gcode log file is saved as Hollow Square_log.gcode - - ->>> extrude.extrudeText(" -( GCode generated by March 29,2007 Skeinforge ) -( Extruder Initialization ) -.. -many lines of gcode -.. -") - -reprap.serial = serial.Serial(0, 19200, timeout = 60) -reprap.cartesian.x.active = True -reprap.cartesian.y.active = True -reprap.cartesian.z.active = True -reprap.extruder.active = True -reprap.cartesian.x.setNotify() -reprap.cartesian.y.setNotify() -reprap.cartesian.z.setNotify() -reprap.cartesian.x.limit = 2523 -reprap.cartesian.y.limit = 2000 -reprap.cartesian.homeReset( 200, True ) -( GCode generated by March 29,2007 Skeinforge ) -( Extruder Initialization ) -M100 P210 -M103 -reprap.extruder.setMotor(reprap.CMD_REVERSE, 0) -.. -many lines of gcode and extruder commands -.. -reprap.cartesian.homeReset( 600, True ) -reprap.cartesian.free() -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -try: - import serial # Import the pySerial modules. -except: - print('You do not have pySerial installed, which is needed to control the serial port.') - print('Information on pySerial is at:\nhttp://pyserial.wiki.sourceforge.net/pySerial') - -from skeinforge_tools.skeinforge_utilities.vector3 import Vector3 -from skeinforge_tools.skeinforge_utilities import archive -from skeinforge_tools.skeinforge_utilities import euclidean -from skeinforge_tools.skeinforge_utilities import gcodec -import math -import os -import reprap # Import the reprap module. -import time - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'greenarrow ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def display( filename = ''): - """Parse a gcode file and display the commands. If no filename is specified, parse all the gcode files which are not log files in this folder.""" - if filename == '': - displayFiles( getGCodeFilesWhichAreNotLogFiles() ) - return - displayFile( filename ) - -def displayFile( filename ): - """Parse a gcode file and display the commands.""" - print('File ' + filename + ' is being displayed.') - fileText = archive.getFileText( filename ) - gcodec.writeFileMessageSuffix( filename, displayText(fileText), 'The gcode log file is saved as ', '_log') - -def displayFiles( filenames ): - """Parse gcode files and display the commands.""" - for filename in filenames: - displayFile( filename ) - -def displayText(gcodeText): - """Parse a gcode text and display the commands.""" - skein = displaySkein() - skein.parseText(gcodeText) - return skein.output - -def extrude( filename = ''): - """Parse a gcode file and send the commands to the extruder. If no filename is specified, parse all the gcode files which are not log files in this folder. - This function requires write access to the serial device, running as root is one way to get that access.""" - if filename == '': - extrudeFiles( getGCodeFilesWhichAreNotLogFiles() ) - return - extrudeFile( filename ) - -def extrudeFile( filename ): - """Parse a gcode file and send the commands to the extruder. - This function requires write access to the serial device, running as root is one way to get that access.""" - print('File ' + filename + ' is being extruded.') - fileText = archive.getFileText( filename ) - gcodec.writeFileMessageSuffix( filename, extrudeText(fileText), 'The gcode log file is saved as ', '_log') - -def extrudeFiles( filenames ): - """Parse gcode files and send the commands to the extruder. - This function requires write access to the serial device, running as root is one way to get that access.""" - for filename in filenames: - extrudeFile( filename ) - -def extrudeText(gcodeText): - """Parse a gcode text and send the commands to the extruder. - This function requires write access to the serial device, running as root is one way to get that access.""" - skein = extrudeSkein() - skein.parseText(gcodeText) - return skein.output - -def getGCodeFilesWhichAreNotLogFiles(): - """Get gcode files which are not log files.""" - return archive.getFilesWithFileTypeWithoutWords('gcode', ['_log'] ) - -def getIntegerString(number): - """Get integer as string.""" - return str( int(number) ) - - -class displaySkein: - """A class to display a gcode skein of extrusions.""" - def __init__(self): - self.extruderActive = 0 - self.feedrateMinute = 200.0 - self.oldLocation = None - self.output = '' - - def addToOutput(self, line): - """Add line with a newline at the end to the output.""" - print(line) - self.output += line + '\n' - - def evaluateCommand( self, command ): - """Add an extruder command to the output.""" - self.addToOutput( command ) - - def helicalMove( self, isCounterclockwise, splitLine ): - """Parse a helical move gcode line and send the commands to the extruder.""" - if self.oldLocation is None: - return - location = Vector3( self.oldLocation ) - self.setFeedrate(splitLine) - setPointToSplitLine( location, splitLine ) - location = location + self.oldLocation - center = Vector3( self.oldLocation ) - indexOfR = getIndexOfStartingWithSecond( "R", splitLine ) - if indexOfR > 0: - radius = getDoubleAfterFirstLetter( splitLine[ indexOfR ] ) - halfLocationMinusOld = location - self.oldLocation - halfLocationMinusOld *= 0.5 - halfLocationMinusOldLength = halfLocationMinusOld.length() - centerMidpointDistance = math.sqrt( radius * radius - halfLocationMinusOldLength * halfLocationMinusOldLength ) - centerMinusMidpoint = getRotatedWiddershinsQuarterAroundZAxis( halfLocationMinusOld ) - centerMinusMidpoint.normalize() - centerMinusMidpoint *= centerMidpointDistance - if isCounterclockwise: - center.setToVec3( halfLocationMinusOld + centerMinusMidpoint ) - else: - center.setToVec3( halfLocationMinusOld - centerMinusMidpoint ) - else: - center.x = getDoubleForLetter( "I", splitLine ) - center.y = getDoubleForLetter( "J", splitLine ) - curveSection = 0.5 - center += self.oldLocation - afterCenterSegment = location - center - beforeCenterSegment = self.oldLocation - center - afterCenterDifferenceAngle = getAngleAroundZAxisDifference( afterCenterSegment, beforeCenterSegment ) - absoluteDifferenceAngle = abs( afterCenterDifferenceAngle ) - steps = int( math.ceil( max( absoluteDifferenceAngle * 2.4, absoluteDifferenceAngle * beforeCenterSegment.length() / curveSection ) ) ) - stepPlaneAngle = getPolar( afterCenterDifferenceAngle / steps, 1.0 ) - zIncrement = ( afterCenterSegment.z - beforeCenterSegment.z ) / float( steps ) - for step in range( 1, steps ): - beforeCenterSegment = getRoundZAxisByPlaneAngle( stepPlaneAngle, beforeCenterSegment ) - beforeCenterSegment.z += zIncrement - arcPoint = center + beforeCenterSegment - self.moveExtruder( arcPoint ) - self.moveExtruder( location ) - self.oldLocation = location - - def homeReset(self): - """Send all axies to home position. Wait until arrival.""" - homeCommandString = 'reprap.cartesian.homeReset(' + getIntegerString( self.feedrateMinute ) + ', True )' - self.evaluateCommand( homeCommandString ) - - def linearMove( self, splitLine ): - """Parse a linear move gcode line and send the commands to the extruder.""" - location = Vector3() - if self.oldLocation is not None: - location = self.oldLocation - self.setFeedrate(splitLine) - setPointToSplitLine( location, splitLine ) - self.moveExtruder( location ) - self.oldLocation = location - - def moveExtruder(self, location): - """Seek to location. Wait until arrival.""" - moveSpeedString = getIntegerString( self.feedrateMinute ) - xMoveString = getIntegerString(location.x) - yMoveString = getIntegerString(location.y) - zMoveString = getIntegerString(location.z) - moveCommandString = 'reprap.cartesian.seek( (' + xMoveString + ', ' + yMoveString + ', ' + zMoveString + '), ' + moveSpeedString + ', True )' - self.evaluateCommand( moveCommandString ) - - def parseGCode(self, lines): - """Parse gcode and send the commands to the extruder.""" - self.evaluateCommand('reprap.serial = serial.Serial(0, 19200, timeout = 60)') # Initialise serial port, here the first port (0) is used. - self.evaluateCommand('reprap.cartesian.x.active = True') # These devices are present in network, will automatically scan in the future. - self.evaluateCommand('reprap.cartesian.y.active = True') - self.evaluateCommand('reprap.cartesian.z.active = True') - self.evaluateCommand('reprap.extruder.active = True') - self.evaluateCommand('reprap.cartesian.x.setNotify()') - self.evaluateCommand('reprap.cartesian.y.setNotify()') - self.evaluateCommand('reprap.cartesian.z.setNotify()') - self.evaluateCommand('reprap.cartesian.x.limit = 2523') - self.evaluateCommand('reprap.cartesian.y.limit = 2000') - self.homeReset() # The module is now ready to receive commands - for line in lines: - self.parseLine(line) - self.homeReset() - self.evaluateCommand('reprap.cartesian.free()') # Shut off power to all motors. - - def parseLine(self, line): - """Parse a gcode line and send the command to the extruder.""" - self.addToOutput(line) - splitLine = line.split(' ') - if len(splitLine) < 1: - return 0 - firstWord = splitLine[0] - if firstWord == 'G1': - self.linearMove(splitLine) - if firstWord == 'G2': - self.helicalMove( False, splitLine ) - if firstWord == 'G3': - self.helicalMove( True, splitLine ) - if firstWord == 'M101': - self.extruderActive = 1 - self.evaluateCommand('reprap.extruder.setMotor(reprap.CMD_REVERSE, 150)') - if firstWord == 'M103': - self.extruderActive = 0 - self.evaluateCommand('reprap.extruder.setMotor(reprap.CMD_REVERSE, 0)') - self.oldActiveLocation = None - - def parseText( self, text ): - """Parse a gcode text and evaluate the commands.""" - textLines = getTextLines(text) - self.parseGCode( textLines ) - - def setFeedrate( self, splitLine ): - """Set the feedrate to the gcode split line.""" - indexOfF = getIndexOfStartingWithSecond( "F", splitLine ) - if indexOfF > 0: - self.feedrateMinute = getDoubleAfterFirstLetter( splitLine[indexOfF] ) - - -class extrudeSkein( displaySkein ): - """A class to extrude a gcode skein of extrusions.""" - def evaluateCommand( self, command ): - """Add an extruder command to the output and evaluate the extruder command. - Display the entire command, but only evaluate the command after the first equal sign.""" - self.addToOutput( command ) - firstEqualIndex = command.find('=') - exec command - - -print('Extrude has been imported.') -print('The gcode files in this directory that are not log files are the following:') -print( getGCodeFilesWhichAreNotLogFiles() ) diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/frank_davies/bring_to_temp.py b/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/frank_davies/bring_to_temp.py deleted file mode 100644 index 48101ad..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/frank_davies/bring_to_temp.py +++ /dev/null @@ -1,47 +0,0 @@ -# bring reprap to temperature -# Frank Davies -import serial -import time -import sys - -def out_rep(out_string): - ser.write(out_string) - print out_string - #print "waiting for OK" - start_time=time.clock() - while (ser.inWaiting()==0) and (time.clock()temp.gcode # make temporary file with extra at the beginning -ascii-xfr -sv temp.gcode >/dev/ttyUSB0 # transfer the file -#cp $1 /dev/ttyUSB0 # alternate transfer method commented out. -echo DONE diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/reprap.py b/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/reprap.py deleted file mode 100644 index fdceb4b..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/reprap.py +++ /dev/null @@ -1,467 +0,0 @@ -""" - pyRepRap is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - pyRepRap is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with pyRepRap. If not, see . -""" -""" - This is the main user imported module containing all end user functions -""" - -# add commands to switch to gcode mode to allow any script using this library to write gcode too. - -try: - import serial # Import the pySerial modules. -except: - print('You do not have pySerial installed, which is needed to control the serial port.') - print('Information on pySerial is at:\nhttp://pyserial.wiki.sourceforge.net/pySerial') - -import snap -import time - - -printDebug = False # print debug info - -# SNAP Control Commands - Taken from PIC code # - -# extruder commands # -CMD_VERSION = 0 -CMD_FORWARD = 1 -CMD_REVERSE = 2 -CMD_SETPOS = 3 -CMD_GETPOS = 4 -CMD_SEEK = 5 -CMD_FREE = 6 -CMD_NOTIFY = 7 -CMD_ISEMPTY = 8 -CMD_SETHEAT = 9 -CMD_GETTEMP = 10 -CMD_SETCOOLER = 11 -CMD_PWMPERIOD = 50 -CMD_PRESCALER = 51 -CMD_SETVREF = 52 -CMD_SETTEMPSCALER = 53 -CMD_GETDEBUGINFO = 54 -CMD_GETTEMPINFO = 55 - -# stepper commands # -CMD_VERSION = 0 -CMD_FORWARD = 1 -CMD_REVERSE = 2 -CMD_SETPOS = 3 -CMD_GETPOS = 4 -CMD_SEEK = 5 -CMD_FREE = 6 -CMD_NOTIFY = 7 -CMD_SYNC = 8 -CMD_CALIBRATE = 9 -CMD_GETRANGE = 10 -CMD_DDA = 11 -CMD_FORWARD1 = 12 -CMD_BACKWARD1 = 13 -CMD_SETPOWER = 14 -CMD_GETSENSOR = 15 -CMD_HOMERESET = 16 -CMD_GETMODULETYPE = 255 - -# sync modes # -sync_none = 0 # no sync (default) -sync_seek = 1 # synchronised seeking -sync_inc = 2 # inc motor on each pulse -sync_dec = 3 # dec motor on each pulse - -snap.localAddress = 0 # local address of host PC. This will always be 0. -#global serialPort -#serialPort = False - -def openSerial( port, rate, tout ): - global serialPort - try: - serialPort = serial.Serial( port, rate, timeout = tout ) - return True - except 13: - print "You do not have permissions to use the serial port, try running as root" - -def closeSerial(): - serialPort.close() - -# Convert two 8 bit bytes to one integer -def bytes2int(LSB, MSB): - return int( (0x100 * int(MSB) ) | int(LSB) ) - -# Convert integer to two 8 bit bytes -def int2bytes(val): - MSB = int( ( int(val) & 0xFF00) / 0x100 ) - LSB = int( int(val) & 0xFF ) - return LSB, MSB - -#def loopTest(): -# p = snap.SNAPPacket( serial, snap.localAddress, snap.localAddress, 0, 1, [] ) - -# Scan reprap network for devices (incomplete) - this will be used by autoconfig functions when complete -def scanNetwork(): - devices = [] - for remoteAddress in range(1, 10): # For every address in range. full range will be 255 - print "Trying address " + str(remoteAddress) - p = snap.SNAPPacket( serialPort, remoteAddress, snap.localAddress, 0, 1, [CMD_GETMODULETYPE] ) # Create snap packet requesting module type - #p = snap.SNAPPacket( serialPort, remoteAddress, snap.localAddress, 0, 1, [CMD_VERSION] ) - if p.send(): # Send snap packet, if sent ok then await reply - rep = p.getReply() - if rep: - #devices[ rep.dataBytes[1] ] = remoteAddress - devices.append( { 'address':remoteAddress, 'type':rep.dataBytes[1], 'subType':rep.dataBytes[2] } ) # If device replies then add to device list. - else: - "print na" - else: - print "scan no ack" - time.sleep(0.5) - for d in devices: - #now get versions - print "device", d - -def getNotification(serialPort): - return snap.getPacket(serialPort) - -class extruderClass: - def __init__(self): - self.address = 8 - self.active = False - - def getModuleType(self): #note: do pics not support this yet? I can't see it in code and get no reply from pic - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_GETMODULETYPE] ) # Create SNAP packet requesting module type - if p.send(): - rep = p.getReply() - data = checkReplyPacket( rep, 2, CMD_GETMODULETYPE ) # If packet sent ok and was acknoledged then await reply, otherwise return False - if data: - return data[1] # If valid reply is recieved then return it, otherwise return False - return False - - def getVersion(self): - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_VERSION] ) - if p.send(): - rep = p.getReply() - data = checkReplyPacket( rep, 3, CMD_VERSION ) - if data: - return data[1], data[2] - return False - - def setMotor(self, direction, speed): - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [int(direction), int(speed)] ) ##no command being sent, whats going on? - if p.send(): - return True - return False - - def getTemp(self): - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_GETTEMP] ) - if p.send(): - rep = p.getReply() - data = checkReplyPacket( rep, 2, CMD_GETTEMP ) - if data: - return data[1] - return False - - def setVoltateReference(self, val): - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_SETVREF, int(val)] ) - if p.send(): - return True - return False - - def setHeat(self, lowHeat, highHeat, tempTarget, tempMax): - if self.active: - tempTargetMSB, tempTargetLSB = int2bytes( tempTarget ) - tempMaxMSB ,tempMaxLSB = int2bytes( tempMax ) - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_SETHEAT, int(lowHeat), int(highHeat), tempTargetMSB, tempTargetLSB, tempMaxMSB, tempMaxLSB] ) # assumes MSB first (don't know this!) - if p.send(): - return True - return False - - def setCooler(self, speed): - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_SETCOOLER, int(speed)] ) - if p.send(): - return True - return False - - def freeMotor(self): - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_FREE] ) - if p.send(): - return True - return False - -extruder = extruderClass() - - -def checkReplyPacket (packet, numExpectedBytes, command): - if packet: - if len( packet.dataBytes ) == numExpectedBytes: # check correct number of data bytes have been recieved - if packet.dataBytes[0] == command: # check reply is a reply to sent command - return packet.dataBytes - return False - - -class axisClass: - def __init__(self, address): - self.address = address - self.active = False # when scanning network, set this, then in each func below, check alive before doing anything - self.limit = 100000 # limit effectively disabled unless set - #move axis one step forward - def forward1(self): - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_FORWARD1] ) - if p.send(): - return True - return False - - #move axis one step backward - def backward1(self): - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_BACKWARD1] ) - if p.send(): - return True - return False - - #spin axis forward at given speed - def forward(self, speed): - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_FORWARD, int(speed)] ) - if p.send(): - return True - return False - - #spin axis backward at given speed - def backward(self, speed): - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_REVERSE, int(speed)] ) - if p.send(): - return True - return False - - #debug only - def getSensors(self): - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_GETSENSOR] ) - if p.send(): - rep = p.getReply() - data = checkReplyPacket( rep, 3, CMD_GETSENSOR ) # replace this with a proper object in SNAP module? - if data: - print data[1], data[2] - return False - - #get current axis position - def getPos(self): - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_GETPOS] ) - if p.send(): - rep = p.getReply() - data = checkReplyPacket( rep, 3, CMD_GETPOS ) - if data: - pos = bytes2int( data[1], data[2] ) - return pos # return value - return False - - #set current position (set variable not robot position) - def setPos(self, pos): - if self.active: - posMSB ,posLSB = int2bytes( pos ) - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_SETPOS, posMSB, posLSB] ) - if p.send(): - return True - return False - - #power off coils on stepper - def free(self): - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_FREE] ) - if p.send(): - return True - return False - - #seek to axis location. When waitArrival is True, funtion does not return until seek is compete - def seek(self, pos, speed, waitArrival = True): - if self.active and pos <= self.limit: - posMSB ,posLSB = int2bytes( pos ) - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_SEEK, int(speed), posMSB ,posLSB] ) - if p.send(): - if waitArrival: - if printDebug: print " wait notify" - notif = getNotification( serialPort ) - if notif.dataBytes[0] == CMD_SEEK: - if printDebug: print " valid notification for seek" - else: - return False - if printDebug: print " rec notif" - return True - return False - - #goto 0 position. When waitArrival is True, funtion does not return until reset is compete - def homeReset(self, speed, waitArrival = True): - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_HOMERESET, int(speed)] ) - if p.send(): - if waitArrival: - if printDebug: print "reset wait" - notif = getNotification( serialPort ) - if notif.dataBytes[0] == CMD_HOMERESET: - if printDebug: print " valid notification for reset" - else: - return False - if printDebug: print "reset done" - return True - return False - - def setNotify(self): - #global serialPort - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_NOTIFY, snap.localAddress] ) # set notifications to be sent to host - if p.send(): - return True - return False - - def setSync( self, syncMode ): - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_SYNC, int(syncMode)] ) - if p.send(): - return True - return False - - def DDA( self, speed, seekTo, slaveDelta, waitArrival = True): - if self.active and seekTo <= self.limit: - masterPosMSB, masterPosLSB = int2bytes( seekTo ) - slaveDeltaMSB, slaveDeltaLSB = int2bytes( slaveDelta ) - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_DDA, int(speed), masterPosMSB ,masterPosLSB, slaveDeltaMSB, slaveDeltaLSB] ) #start sync - if p.send(): - if waitArrival: - notif = getNotification( serialPort ) - if notif.dataBytes[0] == CMD_DDA: - if printDebug: print " valid notification for DDA" # todo: add actual enforement on wrong notification - else: - return False - return True - return False - - def setPower( self, power ): - if self.active: - p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_SETPOWER, int( power * 0.63 )] ) # This is a value from 0 to 63 (6 bits) - if p.send(): - return True - return False - -class syncAxis: - def __init__( self, axis, seekTo, delta, direction ): - self.axis = axis - self.seekTo = seekTo - self.delta = delta - self.direction = direction - - if self.direction > 0: - self.syncMode = sync_inc - else: - self.syncMode = sync_dec - - -class cartesianClass: - def __init__(self): - # initiate axies with addresses - self.x = axisClass(2) - self.y = axisClass(3) - self.z = axisClass(4) - - # goto home position (all axies) - def homeReset(self, speed, waitArrival = True): - if self.x.homeReset( speed, waitArrival ): #setting these to true breaks waitArrival convention. need to rework waitArrival and possibly have each axis storing it's arrival flag and pos as variables? - print "X Reset" - if self.y.homeReset( speed, waitArrival ): - print "Y Reset" - if self.z.homeReset( speed, waitArrival ): - print "Z Reset" - # add a way to collect all three notifications (in whatever order) then check they are all there. this will allow symultanious axis movement and use of waitArrival - - # seek to location (all axies). When waitArrival is True, funtion does not return until all seeks are compete - # seek will automatically use syncSeek when it is required. Always use the seek function - def seek(self, pos, speed, waitArrival = True): - curX, curY, curZ = self.x.getPos(), self.y.getPos(), self.z.getPos() - x, y, z = pos - if x <= self.x.limit and y <= self.y.limit and z <= self.z.limit: - if printDebug: print "seek from [", curX, curY, curZ, "] to [", x, y, z, "]" - if x == curX or y == curY: - if printDebug: print " standard seek" - self.x.seek( x, speed, True ) #setting these to true breaks waitArrival convention. need to rework waitArrival and possibly have each axis storing it's arrival flag and pos as variables? - self.y.seek( y, speed, True ) - else: - if printDebug: print " sync seek" - self.syncSeek( pos, speed, waitArrival ) - if z != curZ: - self.z.seek( z, speed, True ) - else: - print "Trying to print outside of limit, aborting seek" - - # perform syncronised x/y movement. This is called by seek when needed. - def syncSeek(self, pos, speed, waitArrival = True): - curX, curY = self.x.getPos(), self.y.getPos() - newX, newY, nullZ = pos - deltaX = abs( curX - newX ) # calc delta movements - deltaY = abs( curY - newY ) - directionX = ( curX - newX ) / -deltaX # gives direction -1 or 1 - directionY = ( curY - newY ) / -deltaY - if printDebug: print " dx", deltaX, "dy", deltaY, "dirX", directionX, "dirY", directionY - if printDebug: print " using x master" - - master = syncAxis( self.x, newX, deltaX, directionX ) # create two swapable data structures, set x as master, y as slave - slave = syncAxis( self.y, newY, deltaY, directionY ) - - if slave.delta > master.delta: # if y has the greater movement then make y master - slave, master = master, slave - if printDebug: print " switching to y master" - if printDebug: print " masterPos", master.seekTo, "slaveDelta", slave.delta - slave.axis.setSync( slave.syncMode ) - master.axis.DDA( speed, master.seekTo, slave.delta, True ) - time.sleep(0.1) - slave.axis.setSync( sync_none ) - if printDebug: print " sync seek complete" - - # get current position of all three axies - def getPos(self): - return self.x.getPos(), self.y.getPos(), self.z.getPos() - - # stop all motors - def stop(self): - self.x.forward( 0 ) - self.y.forward( 0 ) - self.z.forward( 0 ) - - # free all motors (no current on coils) - def free(self): - self.x.free() - self.y.free() - self.z.free() - def setPower(self, power): - self.x.setPower( power ) - self.y.setPower( power ) - self.z.setPower( power ) - #def lockout(): - #keep sending power down commands to all board every second - - -cartesian = cartesianClass() - -#wait on serial only when after somthing? or do pics send messages without pc request? - - - - - - diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/send.html b/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/send.html deleted file mode 100644 index c150344..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/send.html +++ /dev/null @@ -1,78 +0,0 @@ -

-send.py is "glue" for sending a skeinforge-generated gcode file to your arduino-based reprap. -

-

-It is a command-line only utility, starting it from your GUI of choice will not be useful. -

-

- -Syntax is simple: -

-send.py [options] <gcode or file> [<gcode or file>...]
-
-

-

- -To send your extruder.gcode file to your reprap, type: -

-send.py extruder.gcode
-
-

-

-This will print the extruder.gcode shape, and print comments to the console. -Typically, comments are such things as -(>layerStart< 0.402 ) -which can be very useful to track the progress of your build, so these are "on" by default. -

-

-There are a simple options that may be useful for special circumstances. -These are --quiet, --noreset, --port, and --verbose. -These can also be writted -q, -n, -p, and -v for short. -If you are writing a script (for instance, the M100 scripts for use with EMC) then I'd recommend that you use the long options, so future maintainers don't have to look things up. -

-

-Quiet will suppress all but the most basic messages. It won't supress everything, however. Error messages will still be printed. But it will supress almost everything. -Since options are processed in order on the command line, so if you want to supress messages about processing options, you'll have to make Quiet the first option. -

-

-Normally, the arduino is reset by dropping the DTR line for 1 second. -Since the Arduino takes several seconds to reboot, you will want to disable this behavior when including send.py in scripts. -

-

-The verbose option will cause not just comments, but every command sent to and every response recieved from the arduino to be printed out. Useful for debugging, but it prints a great deal of text in ordinary usage. -

-

-The port option uses reasonable defaults for most operating systems - /dev/ttyUSB0 for posix systems, and COM3 for windows systems. -If you have some other port you'll have to set in manually as "send.py -p COM5 extruder.gcode" or -"send.py --port /dev/ttyUSB5 extruder.gcode" or something. -

-

-Future improvements: -

-

-

-I would like to add support for more g-code contructs on the python side of things. -Stuff like variables, subroutines, etc. -Stuff that the g-code firmware is unlikely to ever implement because of size restrictions. -The current version works, and skeinforge doesn't use these features. -It might be nice for a future "print several objects at once, automatically filling the bed area" interface. -And if I get my extruder built, I might even take the time to do that! -

-RepRapArduinoSerialSender.py -

-

- -This, like send.py, was cribbed from Brenden Erwin's code for using EMC. It's been modified somewhat for more general use. -There are only five methods: -

-
-__init__
-reset
-write
-read
-close
-
-

-Of these, you should not directly use read(). It's used internally by write and reset to verify that the operation was completed successfully. -

- diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/send.py b/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/send.py deleted file mode 100644 index c7d7db8..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/send.py +++ /dev/null @@ -1,168 +0,0 @@ -#!/usr/bin/python2.5 -# encoding: utf-8 -""" -Created by Brendan Erwin on 2008-05-21. -Modified by John Gilmore 2008-08-23 -Copyright (c) 2008 Brendan Erwin. All rights reserved. -Copyright (c) 2008 John Gilmore. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -""" - -import os -import sys -import getopt -import RepRapArduinoSerialSender - -help_message = ''' -Usage: send [options] [...] - --verbose : Verbose - print ALL communication, not just comments. - -v : prints responses from the arduino, and every command sent. - - --quiet : Quiet - don't print anything, whereas - -q : normally comments are printed. - - --noreset : skip the reset. - -n : causes the arduino to not be deliberately reset. - - --port : Set the port to write to - -p : default is "/dev/ttyUSB0" for posix, "COM3" for windows. - - --baud : Set the baud rate to use - -b : defaults to 19200 - -You may call this with either a single statement of g-code -to be sent to the arduino, or with the name of a g-code file. ------------------------------------------------------------------- -Copyright (C) 2008 Brendan Erwin -Copyright (C) 2008 John Gilmore - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -''' -#This was originally release by Brendan under GPLv2 or later - - - -class Usage(Exception): - def __init__(self, msg): - self.msg = msg - -def main(argv=None): - - # Set resonable defaults for port, verbosity, and reset. - verbose = 1 - baud = 19200 - reset = True - if os.name == "posix": - port = "/dev/ttyUSB0" - elif os.name == "nt": - port = "COM3" - else: - port = "/dev/ttyUSB0" - - if argv is None: - argv = sys.argv - - try: - try: - opts, argv = getopt.getopt(argv[1:], "vqnhb:p:", ["verbose","quiet","noreset","help","baud=","port="]) - except getopt.error, msg: - raise Usage(msg) - - # option processing - for option, value in opts: - if option in ( "-v" , "--verbose" ): - verbose = 2 - print "You have requested that verbosity be set to True" - print "All communication with the arduino will be printed" - elif option in ( "-q" , "--quiet" ): - verbose = 0 - #don't print "quiet mode on" - elif option in ( "-n" , "--noreset" ): - reset = False - if verbose: - print "Arduino will not be reset before sending gcode" - elif option in ( "-p" , "--port" ): - port = value - elif option in ("-h", "--help" ): - raise Usage(help_message) - elif option in ("-b", "--baud" ): - baud = int(value) - - if verbose: - print "Arduino port set to " + port - - except Usage, err: - #print >> sys.stderr, sys.argv[0].split("/")[-1] + ": " + str(err.msg) - print >> sys.stderr, str(err.msg) - print >> sys.stderr, "For help use --help" - return 2 - - - sender = RepRapArduinoSerialSender.RepRapArduinoSerialSender(port, baud, verbose>1) - if reset: - sender.reset() - - for filename in argv: - processfile(filename,sender,verbose) - -def processfile(filename,sender,verbose): - try: - datafile = open(filename) - except IOError: - #Ignore verbosity settings here, as if it's a typo we'll want to know. - line=filename - if line.lstrip().startswith(("G","X","Y","Z","M")): - if verbose: - print "Unable to open file \"" + line + "\", assuming it's one line of direct G-code..." - sender.write(line) - return 0 - else: - print "Unable to open file \"" + line + "\"" - sys.exit(-1) - - try: - for line in datafile: - line=line.rstrip() - # Ignore lines with comments (not technically correct, should ignore only the comment, - # but all gcode files that I've actually seen so far don't have code on comment lines. - if line.lstrip().startswith( ('(', '"' , '\\') ): - if verbose: - print line - continue - - # This is the place to insert G-Code interpretation. - # Subroutines, Variables, all sorts of fun stuff. - # probably by calling a "gcode interpreter" class intead - # of simply "sender". - - sender.write(line) - finally: - datafile.close() - - return 0 - -if __name__ == "__main__": - sys.exit(main()) diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/snap.py b/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/snap.py deleted file mode 100644 index 308258d..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/fabricate/snap.py +++ /dev/null @@ -1,280 +0,0 @@ -""" - pyRepRap is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - pyRepRap is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with pyRepRap. If not, see . -""" - -try: - import serial # Import the pySerial modules. -except: - print('You do not have pySerial installed, which is needed to control the serial port.') - print('Information on pySerial is at:\nhttp://pyserial.wiki.sourceforge.net/pySerial') - - -offset_payload = 5 -offset_hdb1 = 2 - -#ackTimeout = 0.3 # unused -messageTimeout = 0.3 # used for ack also (possible to split?) -#messageTimeout = 2 # used for ack also (possible to split?) -retries = 3 # number of packet send retries allowed (for whatever failed reason - -printOutgoingPackets = False -printIncomingPackets = False -printFailedPackets = False - -#this is done again in full decode, but needed here so num bytes to expect is known. -def getPacketLen(buffer): - l = breakHDB1( buffer[offset_hdb1] ) - #l = buffer[offset_hdb1] & 0x0f; - #if (l & 8) != 0: - # return 8 << (l & 7) - return l - -#PCaddress = 0 - -#wait for a packet on serial - note : packets addressed to something other than 0 get recieved if you try sending to a non existant pcb (looped round). should we delete or pass on? (they cause errors right now in getpacket) -def getPacket(ser): - buffer = [] - while 1: - byte = ser.read() # read serial byte. - if len(byte) > 0: - buffer.append( ord (byte) ) # add serial byte to buffer. - else: - print "Error: Serial timeout" #clear buffer on timeout? - return False # timeout has occured. - #TODO - add check for sync on first byte - if len(buffer) > 4: # one packet length is recieved (HDB1?). - expectedLength = getPacketLen(buffer) + offset_payload + 1; # read num data bytes. - if len(buffer) >= expectedLength: # check we have enough data, otherwise continue reading from serial. - #print "############PR#############" - p = SNAPPacket( ser, 0, 0, 0, 0, [] ) # create empty packet - for b in buffer: - p.addByte(b) # add byte to packet - p.decode() - if printIncomingPackets: - print "###INCOMING PACKET##" - p.printPacket() - print "###END INCOMING PACKET##" - return p # return recieved packet - #need to check if packet is for pc (0), if not send on. - -#class for checksum calculator -class SNAPChecksum: - def __init__(self): - self.crc = 0 - def addData(self, data): - #byte i = (byte)(data ^ self.crc) - i = data ^ self.crc - self.crc = 0 - if(i & 1) != 0: - self.crc ^= 0x5e - if(i & 2) != 0: - self.crc ^= 0xbc - if(i & 4) != 0: - self.crc ^= 0x61 - if(i & 8) != 0: - self.crc ^= 0xc2 - if(i & 0x10) != 0: - self.crc ^= 0x9d - if(i & 0x20) != 0: - self.crc ^= 0x23 - if(i & 0x40) != 0: - self.crc ^= 0x46 - if(i & 0x80) != 0: - self.crc ^= 0x8c - return data - def getResult(self): - return self.crc - - -#class for snap packet -class SNAPPacket: - def __init__(self, serial, DAB, SAB, ACK, NAK, dataBytes): #specify serial here, not reason not to - self.SYNC = 0x54 - self.DAB = DAB - self.SAB = SAB - self.ACK = ACK - self.NAK = NAK - self.dataBytes = dataBytes - - self.bytes = [] - self.leftoverBytes = [] - self.encoded = False - self.decoded = False - self.valid = False - self.serial = serial - - #manually add a byte to packet (unused) - def addByte(self, byte): - self.bytes.append(byte) - - #convert individual packet properties into table self.bytes (raw data packet) - def encode(self): - self.NDB = len(self.dataBytes) - self.bytes = [] - self.bytes.insert( 0, 0xFF & self.SYNC ) #SYNC - self.bytes.insert( 1, 0xFF & makeHDB2(self.ACK, self.NAK) ) #HDB2 - self.bytes.insert( 2, 0xFF & makeHDB1(self.NDB) ) #HDB1 - self.bytes.insert( 3, 0xFF & self.DAB ) #DAB - self.bytes.insert( 4, 0xFF & self.SAB ) #SAB - - for d in self.dataBytes: - self.bytes.append( 0xFF & d ) #DATA - - checksum = SNAPChecksum() - for d in self.bytes[1:]: - checksum.addData(d) - self.CRC = checksum.getResult() - self.bytes.append( self.CRC ) #CRC - #print self.bytes - self.encoded = True - - #convert table self.bytes (raw data packet) into individual packet properties - def decode(self): - self.SYNC = self.bytes[0] - self.HDB2 = self.bytes[1] - self.HDB1 = self.bytes[2] - self.DAB = self.bytes[3] - self.SAB = self.bytes[4] - self.NDB = breakHDB1(self.HDB1) - - self.dataBytes = [] - for d in self.bytes[5:5 + self.NDB]: - self.dataBytes.append(d) - - #print self.bytes, self.NDB - self.CRC = self.bytes[5 + self.NDB::6 + self.NDB][0] - numLeftoverBytes = len(self.bytes) - 6 - self.NDB - self.leftoverBytes = self.bytes[6 + self.NDB:len(self.bytes)] - if numLeftoverBytes > 0: - print "leftover bytes", numLeftoverBytes, self.leftoverBytes - self.ACK, self.NAK = breakHDB2(self.HDB2) - self.bytes = self.bytes[:6 + self.NDB] - #print "newb", self.bytes - self.decoded = True - - #calculate checksum, compare to value in recieved packet - def check(self): - newChecksum = SNAPChecksum() - for d in self.bytes[1:-1]: - newChecksum.addData(d) - testCRC = newChecksum.getResult() - if testCRC == self.CRC: - self.valid = True - return True - else: - self.valid = False - return False, testCRC, self.CRC - - #actual sending of data packet (self.bytes) - def sendBytes(self): - if self.encoded == True: - for d in self.bytes: - #print "sending", d, chr(d) - self.serial.write(chr(d)) - else: - print "Error: packet not encoded" - - #user send function, sends packet and awaits and checks acknoledgement. - def send(self): - self.encode() - retriesLeft = retries - while retriesLeft > 0: # try sending define number of times only - self.sendBytes() # send data - if printOutgoingPackets: - print "###OUTGOING PACKET##" - self.decode() #remove need for this (tidy up) - self.printPacket() - print "###END OUTGOING PACKET##" - - ack = getPacket(self.serial) # await ack, returns false on timout - if ack: - ack.decode() - if ack.ACK == 1 and ack.SAB == self.DAB: # check that packet is an acknoledgement and that it is from the device we just messaged. - return True - #do some check on ack - TODO - if printFailedPackets: - print "###FAILED OUTGOING PACKET##" - self.decode() #remove need for this (tidy up) - self.printPacket() - print "###END FAILED OUTGOING PACKET##" - else: - print "Error: ACK not recieved" - if printFailedPackets: - print "###FAILED OUTGOING PACKET##" - self.decode() #remove need for this (tidy up) - self.printPacket() - print "###END FAILED OUTGOING PACKET##" - - retriesLeft = retriesLeft - 1 - print "Error: Packet send FAILED (or reply)" - return False - - # get a modules reply packet (not ack) - def getReply(self): - rep = getPacket(self.serial) - return rep - - #print packet info to console - def printPacket(self): - if self.decoded == True: - print self.bytes - print "SNAP Packet:" - if self.SYNC == 0x54: - print "...Sync OK" - else: - print "...Sync Error" - print "...Check: ", self.check() - print "...DATA", self.dataBytes - print "...CRC", self.CRC - print "...SAB", self.SAB - print "...DAB", self.DAB - print "...HDB1", self.HDB1, ":" - print "...........NDB", self.NDB - print "...HDB2", self.HDB2, ":" - print "...........ACK", self.ACK - print "...........NAK", self.NAK - print "END OF PACKET" - else: - print "Error: packet not decoded" - - - -#create HDB2 -def makeHDB2(ACK, NAK): - SAB = 1 # Length of the Source Address Bytes, in Binary. RepRap currently only accepts source addresses of 1 byte length - DAB = 1 # Length of the Destination Address Bytes, in Binary. RepRap currently only accepts destinations of 1 byte length - PFB = 0 # Length of Protocol Flag Bytes. RepRap does not accept any protocol flag bytes, so this must be set to 00 - HDB2val = ((DAB & 0x3) * pow(2,6)) | ((SAB & 0x3) * pow(2,4)) | ((PFB & 0x3) * pow(2,2)) | ((ACK & 0x1) * pow(2,1)) | (NAK & 0x1) - #print "HDB2 = '" + str(HDB2val) + "'" - return HDB2val - -def breakHDB2(HDB2): - ACK = (HDB2 & 0x2) / pow(2,1) - NAK = (HDB2 & 0x1) - return ACK, NAK - -#create HDB1 -def makeHDB1(NDB): - CMD = 0 # Command Mode Bit. Not implemented by RepRap and should be set to 0 - EMD = 0x3 # Currently RepRap only implements 8-bit self.crc. this should be set to 011 - HDB1val = ((CMD & 0x1) * pow(2,7)) | ((EMD & 0x7) * pow(2,4)) | (0xF & NDB) - #print "HDB1 = '" + str(HDB1val) + "'" - return HDB1val - -def breakHDB1(HDB1): - NDB = HDB1 & 0xF - return NDB - - - diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/nophead/enrique.py b/skeinforge/fabmetheus_utilities/miscellaneous/nophead/enrique.py deleted file mode 100644 index 69a7a60..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/nophead/enrique.py +++ /dev/null @@ -1,132 +0,0 @@ -import Image, ImageDraw, ImageChops -from GifImagePlugin import getheader, getdata -from vector3 import Vector3 - -# Get the entire text of a file. -# @param fileName name of the file -# @return entire text of a file. -def getFileText(fileName): - file = open( fileName, 'r') - fileText = file.read() - file.close() - return fileText - -# Get the all the lines of text of a text. -# @param text text -# @return the lines of text of a text -def getTextLines(text): - return text.replace('\r', '\n').split('\n') - -# Get the double value of the word after the first letter. -# @param word string with value starting after the first letter -# @return double value of the word after the first letter -def getDoubleAfterFirstLetter(word): - return float( word[1 :] ) - -# Get the double value of the word after the first occurence of the letter in the split line. -def getDoubleForLetter(letter, splitLine): - return getDoubleAfterFirstLetter( splitLine[ getIndexOfStartingWithSecond(letter, splitLine) ] ) - -# Get index of the first occurence of the given letter in the split line, starting with the second word. Return - 1 if letter is not found -def getIndexOfStartingWithSecond(letter, splitLine): - for wordIndex in xrange( 1, len(splitLine) ): - word = splitLine[ wordIndex ] - firstLetter = word[0] - if firstLetter == letter: - return wordIndex - return - 1 - -# straightforward delta encoding taken from gifmaker.py -def makedelta(fp, sequence): - """Convert list of image frames to a GIF animation file""" - previous = None - for im in sequence: - if not previous: - # global header - for s in getheader(im) + getdata(im): - fp.write(s) - else: - # delta frame - delta = ImageChops.subtract_modulo(im, previous) - bbox = delta.getbbox() - if not bbox: - bbox = (0,0, 1,1) - # compress difference - for s in getdata(im.crop(bbox), offset = bbox[:2]): - fp.write(s) - previous = im.copy() - fp.write(";") - - - -class g2gif: - def __init__(self,fileName, outfile): - self.last_pos = Vector3() - self.last_pos.z = 999 - self.do_move = 1 - fileText = getFileText(fileName) - textLines = getTextLines(fileText) - self.images = [] - self.image = None - for line in textLines: - self.parseLine(line) - self.images.append(self.image) - # write GIF animation - fp = open(outfile, "wb") - makedelta(fp, self.images) - fp.close() - - - def parseLine(self, line): - splitLine = line.split(' ') - if len(splitLine) < 1: - return 0 - firstWord = splitLine[0] - if firstWord == 'G1': - self.linearMove(splitLine) - if firstWord == 'M101': - self.do_move = 1 - - # Set the feedRate to the gcode split line. - def setFeedRate( self, splitLine ): - indexOfF = getIndexOfStartingWithSecond( "F", splitLine ) - if indexOfF > 0: - self.feedRateMinute = getDoubleAfterFirstLetter( splitLine[indexOfF] ) - - # Set a point to the gcode split line. - def setPointComponent( self, point, splitLine ): - point.x = getDoubleForLetter( "X", splitLine ) - point.y = getDoubleForLetter( "Y", splitLine ) - indexOfZ = getIndexOfStartingWithSecond( "Z", splitLine ) - if indexOfZ > 0: - point.z = getDoubleAfterFirstLetter( splitLine[indexOfZ] ) - - def scale( self, x, y ): - return x * 5 + 150, - y * 5 + 100 - - def linearMove( self, splitLine ): - location = Vector3() - self.setFeedRate(splitLine) - self.setPointComponent( location, splitLine ) - if location.z != self.last_pos.z: - if self.image: - for i in xrange(10): - self.images.append(self.image) - self.image = Image.new('P', (300, 200), 255) - palette = [] - for red in xrange(8): - for green in xrange(8): - for blue in xrange(4): - palette.extend((red * 255 / 7, green * 255 / 7, blue * 255 / 3)) - self.image.putpalette(palette) - self.segment = 0 - else: - if self.do_move: - draw = ImageDraw.Draw(self.image) - draw.line( ( self.scale( self.last_pos.x, self.last_pos.y ), self.scale( location.x, location.y ) ), fill = 192 ) - self.segment = self.segment + 1 - else: - draw = ImageDraw.Draw(self.image) - draw.line( ( self.scale( self.last_pos.x, self.last_pos.y ), self.scale(location.x, location.y ) ), fill = self.segment ) - self.last_pos = location - self.do_move = 0 diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/nophead/gRead.py b/skeinforge/fabmetheus_utilities/miscellaneous/nophead/gRead.py deleted file mode 100644 index 13d326a..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/nophead/gRead.py +++ /dev/null @@ -1,103 +0,0 @@ -from vector3 import Vector3 - -# Get the entire text of a file. -# @param fileName name of the file -# @return entire text of a file. -def getFileText(fileName): - file = open( fileName, 'r') - fileText = file.read() - file.close() - return fileText - -# Get the all the lines of text of a text. -# @param text text -# @return the lines of text of a text -def getTextLines(text): - return text.replace('\r', '\n').split('\n') - -# Get the double value of the word after the first letter. -# @param word string with value starting after the first letter -# @return double value of the word after the first letter -def getDoubleAfterFirstLetter(word): - return float( word[1 :] ) - -# Get index of the first occurence of the given letter in the split line, starting with the second word. Return - 1 if letter is not found -def getIndexOfStartingWithSecond(letter, splitLine): - for wordIndex in xrange( 1, len(splitLine) ): - word = splitLine[ wordIndex ] - firstLetter = word[0] - if firstLetter == letter: - return wordIndex - return - 1 - - -class gRead: - def __init__(self,fileName, layers,gcodeText = ''): - if gcodeText == '': - gcodeText = getFileText(fileName) - textLines = getTextLines(gcodeText) - self.last_pos = Vector3() - self.layers = layers - self.layer = None - self.thread = None - self.skeinforge = 0 - self.max_z = -9999999999 - for line in textLines: - self.parseLine(line) - self.newLayer() - - def parseLine(self, line): - if line.startswith( "(" ): - if line.startswith( "(" ): - self.newLayer() - return - splitLine = line.split() - if len(splitLine) < 1: - return 0 - firstWord = splitLine[0] - if firstWord == 'G1': - self.linearMove(splitLine) - if firstWord == 'M110': #filament height only sent by skeinforge at the moment - self.skeinforge = 1 - self.newThread() - if firstWord == 'M103': #extruder off - if self.skeinforge: - self.newThread() #end of thread if skeinforge - if firstWord == 'G92': #offset coordinate system - self.newThread() #for RepRap - - # Set a point to the gcode split line. - def setPointComponent( self, point, splitLine ): - indexOfX = getIndexOfStartingWithSecond( "X", splitLine ) - if indexOfX > 0: - point.x = getDoubleAfterFirstLetter( splitLine[indexOfX] ) - indexOfY = getIndexOfStartingWithSecond( "Y", splitLine ) - if indexOfY > 0: - point.y = getDoubleAfterFirstLetter( splitLine[indexOfY] ) - indexOfZ = getIndexOfStartingWithSecond( "Z", splitLine ) - if indexOfZ > 0: - point.z = getDoubleAfterFirstLetter( splitLine[indexOfZ] ) - - def newLayer(self): - self.newThread() - if self.layer: - self.layers.append(self.layer) - self.layer = [] - - def newThread(self): - if self.thread: - self.layer.append(self.thread) - self.thread = [] - - def linearMove( self, splitLine ): - if self.thread is not None: - pos = self.last_pos.copy() - self.setPointComponent( pos, splitLine ) - if pos.z > self.max_z: -# self.newLayer() - self.max_z = pos.z - if pos.z < self.last_pos.z: - self.newThread() - if self.skeinforge or pos.z < self.max_z: - self.thread.append(pos) - self.last_pos = pos diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/nophead/hexgrid.py b/skeinforge/fabmetheus_utilities/miscellaneous/nophead/hexgrid.py deleted file mode 100644 index e0d4385..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/nophead/hexgrid.py +++ /dev/null @@ -1,28 +0,0 @@ -import math - -# root parameters -drillDiameter = 25.4 / 16.0 # 1/16 of an inch -separationMultiplier = 2.5 -safetyMultiplier = 1.0 -bottomLeft = complex( - 10.0, - 10.0 ) -topRight = complex( 10.0, 10.0 ) - -# derived parameters -separation = drillDiameter * separationMultiplier -horizontalSeparation = separation * math.cos( math.radians( 30.0 ) ) -oddRowOffset = separation * math.sin( math.radians( 30.0 ) ) -safetyMargin = complex( separation, separation ) * safetyMultiplier -safeBottomLeft = bottomLeft + safetyMargin -safeTopRight = topRight - safetyMargin - -# generate drill locations -drillLocation = safeBottomLeft * 1.0 -offset = 0.0 -while drillLocation.imag < safeTopRight.imag: - print('') - while drillLocation.real < safeTopRight.real: - print( drillLocation ) - drillLocation = complex( drillLocation.real + separation, drillLocation.imag ) - offset = oddRowOffset - offset - drillLocation = complex( safeBottomLeft.real + offset, drillLocation.imag + horizontalSeparation ) -print('') diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/nophead/layers.py b/skeinforge/fabmetheus_utilities/miscellaneous/nophead/layers.py deleted file mode 100644 index a335d2b..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/nophead/layers.py +++ /dev/null @@ -1,72 +0,0 @@ -from vector3 import Vector3 -import Image, ImageDraw - -def bounding_cube(layers): - min_x = 999999 - min_y = 999999 - min_z = 999999 - max_x = -999999 - max_y = -999999 - max_z = -999999 - for layer in layers: - for thread in layer: - for point in thread: - if point.x > max_x: - max_x = point.x - if point.y > max_y: - max_y = point.y - if point.z > max_z: - max_z = point.z - if point.x < min_x: - min_x = point.x - if point.y < min_y: - min_y = point.y - if point.z < min_z: - min_z = point.z - return Vector3(min_x, min_y, min_z), Vector3(max_x, max_y, max_z) - -def make_images(layers): - palette = [] - for i in xrange(256): - #resistor colour codes - if i == 1: - palette.extend((134, 100, 57)) # brown - elif i == 2: - palette.extend((255, 0, 0)) # red - elif i == 3: - palette.extend((218, 90, 35)) # orange - elif i == 4: - palette.extend((255, 255, 0)) # yellow - elif i == 5: - palette.extend(( 0, 255, 0)) # green - elif i == 6: - palette.extend(( 0, 0, 255)) # blue - elif i == 7: - palette.extend((255, 0, 255)) # purple - else: - palette.extend((i, i, i)) # shades of grey - cube = bounding_cube(layers) - scale = 10 - x0 = int(cube[0].x) - 1 - y0 = int(cube[0].y) - 1 - width = int(round(cube[1].x - x0) + 1) * scale - height = int(round(cube[1].y - y0) + 1) * scale - last_pos = None - images = [] - for layer in layers: - image = Image.new('P', (width, height), 255) - image.putpalette(palette) - draw = ImageDraw.Draw(image) - segment = 0 - for thread in layer: - if last_pos is not None: - draw.line(((( last_pos.x - x0) * scale, height - ( last_pos.y - y0) * scale), - ((thread[0].x - x0) * scale, height - (thread[0].y - y0) * scale)), fill = 128) - last_pos = thread[0].copy() - for point in thread[1:]: - draw.line((((last_pos.x - x0) * scale, height - (last_pos.y - y0) * scale), - ( (point.x - x0) * scale, height - (point.y - y0) * scale)), fill = segment % 8) - last_pos = point.copy() - segment = segment + 1 - images.append(image) - return images diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/nophead/preview.py b/skeinforge/fabmetheus_utilities/miscellaneous/nophead/preview.py deleted file mode 100644 index e48a6d4..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/nophead/preview.py +++ /dev/null @@ -1,69 +0,0 @@ -import sys -try: - import Tkinter -except: - print('You do not have Tkinter, which is needed for the graphical interface.') - print('Information on how to download Tkinter is at:\nwww.tcl.tk/software/tcltk/') -try: - from layers import * - from gRead import * - import ImageTk -except: - print('You do not have the Python Imaging Library, which is needed by preview and gifview to view the gcode.') - print('The Python Imaging Library can be downloaded from:\nwww.pythonware.com/products/pil/') - -class Preview: - def __init__(self, layers): - self.images = make_images(layers) - self.index = 0 - size = self.images[0].size - self.root = Tkinter.Tk() - self.root.title("Gifscene from HydraRaptor") - frame = Tkinter.Frame(self.root) - frame.pack() - self.canvas = Tkinter.Canvas(frame, width = size[0], height = size[1]) - self.canvas.pack() - self.canvas.config(scrollregion=self.canvas.bbox(Tkinter.ALL)) - self.exit_button = Tkinter.Button(frame, text = "Exit", fg = "red", command = frame.quit) - self.exit_button.pack(side=Tkinter.RIGHT) - self.down_button = Tkinter.Button(frame, text = "Down", command = self.down) - self.down_button.pack(side=Tkinter.LEFT) - self.up_button = Tkinter.Button(frame, text = "Up", command = self.up) - self.up_button.pack(side=Tkinter.LEFT) - self.update() - self.root.mainloop() - - def update(self): - # FIXME: Somehow this fails if this is launched using the Preferences, - # but works from the command-line. - self.image = ImageTk.PhotoImage(self.images[self.index]) - self.canvas.create_image(0,0, anchor= Tkinter.NW, image = self.image) - if self.index < len(self.images) - 1: - self.up_button.config(state = Tkinter.NORMAL) - else: - self.up_button.config(state = Tkinter.DISABLED) - if self.index > 0: - self.down_button.config(state = Tkinter.NORMAL) - else: - self.down_button.config(state = Tkinter.DISABLED) - - def up(self): - self.index += 1 - self.update() - - def down(self): - self.index -= 1 - self.update() - - -def viewGif( fileName, gcodeText = ''): - layers = [] - try: - gRead(fileName, layers, gcodeText) - Preview(layers) - except Exception, why: - print('Preview failed: ' + str( why ) ) - - -if __name__ == "__main__": - viewGif(' '.join(sys.argv[1 :])) diff --git a/skeinforge/fabmetheus_utilities/miscellaneous/nophead/vector3.py b/skeinforge/fabmetheus_utilities/miscellaneous/nophead/vector3.py deleted file mode 100644 index e41d3f9..0000000 --- a/skeinforge/fabmetheus_utilities/miscellaneous/nophead/vector3.py +++ /dev/null @@ -1,489 +0,0 @@ -""" -Vec3 is a three dimensional vector class. - -Below are examples of Vector3 use. - ->>> from vector3 import Vector3 ->>> origin = Vector3() ->>> origin -0.0, 0.0, 0.0 ->>> pythagoras = Vector3( 3, 4, 0 ) ->>> pythagoras -3.0, 4.0, 0.0 ->>> pythagoras.magnitude() -5.0 ->>> pythagoras.magnitudeSquared() -25 ->>> triplePythagoras = pythagoras * 3.0 ->>> triplePythagoras -9.0, 12.0, 0.0 ->>> plane = pythagoras.dropAxis() ->>> plane -(3+4j) -""" - -from __future__ import absolute_import -try: - import psyco - psyco.full() -except: - pass -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -import math -import operator - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -class Vector3: - """A three dimensional vector class.""" - __slots__ = ['x', 'y', 'z'] - - def __init__( self, x = 0.0, y = 0.0, z = 0.0 ): - self.x = x - self.y = y - self.z = z - - def __abs__(self): - """Get the magnitude of the Vector3.""" - return math.sqrt( self.x * self.x + self.y * self.y + self.z * self.z ) - - magnitude = __abs__ - - def __add__(self, other): - """Get the sum of this Vector3 and other one.""" - return Vector3( self.x + other.x, self.y + other.y, self.z + other.z ) - - def __copy__(self): - """Get the copy of this Vector3.""" - return Vector3( self.x, self.y, self.z ) - - __pos__ = __copy__ - - copy = __copy__ - - def __div__(self, other): - """Get a new Vector3 by dividing each component of this one.""" - return Vector3( self.x / other, self.y / other, self.z / other ) - - def __eq__(self, other): - """Determine whether this vector is identical to other one.""" - if other is None: - return False - return self.x == other.x and self.y == other.y and self.z == other.z - - def __floordiv__(self, other): - """Get a new Vector3 by floor dividing each component of this one.""" - return Vector3( self.x // other, self.y // other, self.z // other ) - - def __hash__(self): - """Determine whether this vector is identical to other one.""" - return self.__repr__().__hash__() - - def __iadd__(self, other): - """Add other Vector3 to this one.""" - self.x += other.x - self.y += other.y - self.z += other.z - return self - - def __idiv__(self, other): - """Divide each component of this Vector3.""" - self.x /= other - self.y /= other - self.z /= other - return self - - def __ifloordiv__(self, other): - """Floor divide each component of this Vector3.""" - self.x //= other - self.y //= other - self.z //= other - return self - - def __imul__(self, other): - """Multiply each component of this Vector3.""" - self.x *= other - self.y *= other - self.z *= other - return self - - def __isub__(self, other): - """Subtract other Vector3 from this one.""" - self.x -= other.x - self.y -= other.y - self.z -= other.z - return self - - def __itruediv__(self, other): - """True divide each component of this Vector3.""" - self.x = operator.truediv( self.x, other ) - self.y = operator.truediv( self.y, other ) - self.z = operator.truediv( self.z, other ) - return self - - def __mul__(self, other): - """Get a new Vector3 by multiplying each component of this one.""" - return Vector3( self.x * other, self.y * other, self.z * other ) - - def __ne__(self, other): - """Determine whether this vector is not identical to other one.""" - return not self.__eq__(other) - - def __neg__(self): - return Vector3( - self.x, - self.y, - self.z ) - - def __nonzero__(self): - return self.x != 0 or self.y != 0 or self.z != 0 - - def __repr__(self): - """Get the string representation of this Vector3.""" - return '%s, %s, %s' % ( self.x, self.y, self.z ) - - def __rdiv__(self, other): - """Get a new Vector3 by dividing each component of this one.""" - return Vector3( other / self.x, other / self.y, other / self.z ) - - def __rfloordiv__(self, other): - """Get a new Vector3 by floor dividing each component of this one.""" - return Vector3( other // self.x, other // self.y, other // self.z ) - - def __rmul__(self, other): - """Get a new Vector3 by multiplying each component of this one.""" - return Vector3( self.x * other, self.y * other, self.z * other ) - - def __rtruediv__(self, other): - """Get a new Vector3 by true dividing each component of this one.""" - return Vector3( operator.truediv( other , self.x ), operator.truediv( other, self.y ), operator.truediv( other, self.z ) ) - - def __sub__(self, other): - """Get the difference between the Vector3 and other one.""" - return Vector3( self.x - other.x, self.y - other.y, self.z - other.z ) - - def __truediv__(self, other): - """Get a new Vector3 by true dividing each component of this one.""" - return Vector3( operator.truediv( self.x, other ), operator.truediv( self.y, other ), operator.truediv( self.z, other ) ) - - def cross(self, other): - """Calculate the cross product of this vector with other one.""" - return Vector3( self.y * other.z - self.z * other.y, - self.x * other.z + self.z * other.x, self.x * other.y - self.y * other.x ) - - def distance(self, other): - """Get the Euclidean distance between this vector and other one.""" - return math.sqrt( self.distanceSquared(other) ) - - def distanceSquared(self, other): - """Get the square of the Euclidean distance between this vector and other one.""" - separationX = self.x - other.x - separationY = self.y - other.y - separationZ = self.z - other.z - return separationX * separationX + separationY * separationY + separationZ * separationZ - - def dot(self, other): - """Calculate the dot product of this vector with other one.""" - return self.x * other.x + self.y * other.y + self.z * other.z - - def dropAxis( self, which ): - """Get a complex by removing one axis of this one. - - Keyword arguments: - which -- the axis to drop (0=X, 1=Y, 2=Z)""" - if which == 0: - return complex( self.y, self.z ) - if which == 1: - return complex( self.x, self.z ) - if which == 2: - return complex( self.x, self.y ) - - def getNormalized(self, other): - """Get the normalized Vector3.""" - magnitude = abs(self) - if magnitude == 0.0: - return self.copy() - return self / magnitude - - def magnitudeSquared(self): - """Get the square of the magnitude of the Vector3.""" - return self.x * self.x + self.y * self.y + self.z * self.z - - def normalize(self): - """Scale each component of this Vector3 so that it has a magnitude of 1. If this Vector3 has a magnitude of 0, this method has no effect.""" - magnitude = abs(self) - if magnitude != 0.0: - self /= magnitude - - def reflect( self, normal ): - """Reflect the Vector3 across the normal, which is assumed to be normalized.""" - distance = 2 * ( self.x * normal.x + self.y * normal.y + self.z * normal.z ) - return Vector3( self.x - distance * normal.x, self.y - distance * normal.y, self.z - distance * normal.z ) - - def setToVec3(self, other): - """Set this Vector3 to be identical to other one.""" - self.x = other.x - self.y = other.y - self.z = other.z - - def setToXYZ( self, x, y, z ): - """Set the x, y, and z components of this Vector3.""" - self.x = x - self.y = y - self.z = z - -""" -class Vector3: - __slots__ = ['x', 'y', 'z'] - - def __init__(self, x, y, z): - self.x = x - self.y = y - self.z = z - - def __copy__(self): - return self.__class__(self.x, self.y, self.z) - - copy = __copy__ - - def __repr__(self): - return 'Vector3(%.2f, %.2f, %.2f)' % (self.x, - self.y, - self.z) - - def __eq__(self, other): - if isinstance(other, Vector3): - return self.x == other.x and \ - self.y == other.y and \ - self.z == other.z - else: - assert hasattr(other, '__len__') and len(other) == 3 - return self.x == other[0] and \ - self.y == other[1] and \ - self.z == other[2] - - def __ne__(self, other): - return not self.__eq__(other) - - def __nonzero__(self): - return self.x != 0 or self.y != 0 or self.z != 0 - - def __len__(self): - return 3 - - def __getitem__(self, key): - return (self.x, self.y, self.z)[key] - - def __setitem__(self, key, value): - l = [self.x, self.y, self.z] - l[key] = value - self.x, self.y, self.z = l - - def __iter__(self): - return iter((self.x, self.y, self.z)) - - def __getattr__(self, name): - try: - return tuple([(self.x, self.y, self.z)['xyz'.index(c)] \ - for c in name]) - except ValueError: - raise AttributeError, name - - if _enable_swizzle_set: - # This has detrimental performance on ordinary setattr as well - # if enabled - def __setattr__(self, name, value): - if len(name) == 1: - object.__setattr__(self, name, value) - else: - try: - l = [self.x, self.y, self.z] - for c, v in map(None, name, value): - l['xyz'.index(c)] = v - self.x, self.y, self.z = l - except ValueError: - raise AttributeError, name - - - def __add__(self, other): - if isinstance(other, Vector3): - # Vector + Vector -> Vector - # Vector + Point -> Point - # Point + Point -> Vector - if self.__class__ is other.__class__: - _class = Vector3 - else: - _class = Point3 - return _class(self.x + other.x, - self.y + other.y, - self.z + other.z) - else: - assert hasattr(other, '__len__') and len(other) == 3 - return Vector3(self.x + other[0], - self.y + other[1], - self.z + other[2]) - __radd__ = __add__ - - def __iadd__(self, other): - if isinstance(other, Vector3): - self.x += other.x - self.y += other.y - self.z += other.z - else: - self.x += other[0] - self.y += other[1] - self.z += other[2] - return self - - def __sub__(self, other): - if isinstance(other, Vector3): - # Vector - Vector -> Vector - # Vector - Point -> Point - # Point - Point -> Vector - if self.__class__ is other.__class__: - _class = Vector3 - else: - _class = Point3 - return Vector3(self.x - other.x, - self.y - other.y, - self.z - other.z) - else: - assert hasattr(other, '__len__') and len(other) == 3 - return Vector3(self.x - other[0], - self.y - other[1], - self.z - other[2]) - - - def __rsub__(self, other): - if isinstance(other, Vector3): - return Vector3(other.x - self.x, - other.y - self.y, - other.z - self.z) - else: - assert hasattr(other, '__len__') and len(other) == 3 - return Vector3(other.x - self[0], - other.y - self[1], - other.z - self[2]) - - def __mul__(self, other): - if isinstance(other, Vector3): - # TODO component-wise mul/div in-place and on Vector2; docs. - if self.__class__ is Point3 or other.__class__ is Point3: - _class = Point3 - else: - _class = Vector3 - return _class(self.x * other.x, - self.y * other.y, - self.z * other.z) - else: - assert type(other) in (int, long, float) - return Vector3(self.x * other, - self.y * other, - self.z * other) - - __rmul__ = __mul__ - - def __imul__(self, other): - assert type(other) in (int, long, float) - self.x *= other - self.y *= other - self.z *= other - return self - - def __div__(self, other): - assert type(other) in (int, long, float) - return Vector3(operator.div(self.x, other), - operator.div(self.y, other), - operator.div(self.z, other)) - - - def __rdiv__(self, other): - assert type(other) in (int, long, float) - return Vector3(operator.div(other, self.x), - operator.div(other, self.y), - operator.div(other, self.z)) - - def __floordiv__(self, other): - assert type(other) in (int, long, float) - return Vector3(operator.floordiv(self.x, other), - operator.floordiv(self.y, other), - operator.floordiv(self.z, other)) - - - def __rfloordiv__(self, other): - assert type(other) in (int, long, float) - return Vector3(operator.floordiv(other, self.x), - operator.floordiv(other, self.y), - operator.floordiv(other, self.z)) - - def __truediv__(self, other): - assert type(other) in (int, long, float) - return Vector3(operator.truediv(self.x, other), - operator.truediv(self.y, other), - operator.truediv(self.z, other)) - - - def __rtruediv__(self, other): - assert type(other) in (int, long, float) - return Vector3(operator.truediv(other, self.x), - operator.truediv(other, self.y), - operator.truediv(other, self.z)) - - def __neg__(self): - return Vector3(-self.x, - -self.y, - -self.z) - - __pos__ = __copy__ - - def __abs__(self): - return math.sqrt(self.x ** 2 + \ - self.y ** 2 + \ - self.z ** 2) - - magnitude = __abs__ - - def magnitude_squared(self): - return self.x ** 2 + \ - self.y ** 2 + \ - self.z ** 2 - - def normalize(self): - d = self.magnitude() - if d: - self.x /= d - self.y /= d - self.z /= d - return self - - def normalized(self): - d = self.magnitude() - if d: - return Vector3(self.x / d, - self.y / d, - self.z / d) - return self.copy() - - def dot(self, other): - assert isinstance(other, Vector3) - return self.x * other.x + \ - self.y * other.y + \ - self.z * other.z - - def cross(self, other): - assert isinstance(other, Vector3) - return Vector3(self.y * other.z - self.z * other.y, - -self.x * other.z + self.z * other.x, - self.x * other.y - self.y * other.x) - - def reflect(self, normal): - # assume normal is normalized - assert isinstance(normal, Vector3) - d = 2 * (self.x * normal.x + self.y * normal.y + self.z * normal.z) - return Vector3(self.x - d * normal.x, - self.y - d * normal.y, - self.z - d * normal.z) -""" diff --git a/skeinforge/fabmetheus_utilities/settings.py b/skeinforge/fabmetheus_utilities/settings.py deleted file mode 100644 index 8ba7eca..0000000 --- a/skeinforge/fabmetheus_utilities/settings.py +++ /dev/null @@ -1,1992 +0,0 @@ -""" -Settings is a collection of utilities to display, read & write the settings and position widgets. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -import cStringIO -import math -import os -import shutil -import sys -import traceback -import webbrowser -try: - import Tkinter -except: - print('You do not have Tkinter, which is needed for the graphical interface, you will only be able to use the command line.') - print('Information on how to download Tkinter is at:\nwww.tcl.tk/software/tcltk/') - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = "$Date: 2008/23/04 $" -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalRepositoryDialogListTable = {} -globalProfileSaveListenerListTable = {} -globalCloseListTables = [ globalRepositoryDialogListTable, globalProfileSaveListenerListTable ] -globalSpreadsheetSeparator = '\t' -globalTemporaryOverrides = {} - - -def addAcceleratorCommand( acceleratorBinding, commandFunction, master, menu, text ): - """Add accelerator command.""" - acceleratorText = acceleratorBinding[1 : -1] - lastIndexOfMinus = acceleratorText.rfind('-') - if lastIndexOfMinus > - 1: - acceleratorText = acceleratorText[ : lastIndexOfMinus + 1 ] + acceleratorText[ lastIndexOfMinus + 1 : ].capitalize() - acceleratorText = acceleratorText.replace('KeyPress-', '') - acceleratorText = acceleratorText.replace('-', '+') - acceleratorText = acceleratorText.replace('Control', 'Ctrl') - acceleratorBinding = acceleratorBinding.replace('KeyPress', '') - menu.add_command( accelerator = acceleratorText, label = text, underline = 0, command = commandFunction ) - master.bind( acceleratorBinding, commandFunction ) - -def addEmptyRow( gridPosition ): - """Add an empty row.""" - gridPosition.increment() - Tkinter.Label( gridPosition.master ).grid( row = gridPosition.row, column = gridPosition.column ) - -def addListsToRepository(fileNameHelp, repository): - """Add the value to the lists.""" - addListsToRepositoryByFunction(fileNameHelp, None, repository) - -def addListsToRepositoryByFunction(fileNameHelp, getProfileDirectory, repository): - """Add the value to the lists.""" - repository.displayEntities = [] - repository.executeTitle = None - repository.fileNameHelp = fileNameHelp - repository.fileNameInput = None - repository.lowerName = fileNameHelp.split('.')[-2] - repository.baseName = repository.lowerName + '.csv' - repository.baseNameSynonym = None - repository.capitalizedName = getEachWordCapitalized( repository.lowerName ) - repository.getProfileDirectory = getProfileDirectory - repository.openLocalHelpPage = HelpPage().getOpenFromDocumentationSubName( repository.fileNameHelp ) - repository.openWikiManualHelpPage = None - repository.preferences = [] - repository.repositoryDialog = None - repository.saveListenerTable = {} - repository.title = repository.capitalizedName + ' Settings' - repository.menuEntities = [] - repository.saveCloseTitle = 'Save and Close' - repository.windowPosition = WindowPosition().getFromValue( repository, '0+0') - for setting in repository.preferences: - setting.repository = repository - -def addMenuEntitiesToMenu( menu, menuEntities ): - """Add the menu entities to the menu.""" - for menuEntity in menuEntities: - menuEntity.addToMenu( menu ) - -def addMenuEntitiesToMenuFrameable( menu, menuEntities ): - """Add the menu entities to the menu.""" - for menuEntity in menuEntities: - menuEntity.addToMenuFrameable( menu ) - -def addPluginsParentToMenu( directoryPath, menu, parentPath, pluginFileNames ): - """Add plugins and the parent to the menu.""" - ToolDialog().addPluginToMenu( menu, parentPath[ : parentPath.rfind('.') ] ) - menu.add_separator() - addPluginsToMenu( directoryPath, menu, pluginFileNames ) - -def addPluginsToMenu( directoryPath, menu, pluginFileNames ): - """Add plugins to the menu.""" - for pluginFileName in pluginFileNames: - ToolDialog().addPluginToMenu( menu, os.path.join( directoryPath, pluginFileName ) ) - -def cancelRepository(repository): - """Read the repository then set all the entities to the read repository values.""" - getReadRepository(repository) - for setting in repository.displayEntities: - if setting in repository.preferences: - setting.setStateToValue() - -def deleteDirectory( directory, subfolderName ): - """Delete the directory if it exists.""" - subDirectory = os.path.join( directory, subfolderName ) - if os.path.isdir( subDirectory ): - shutil.rmtree( subDirectory ) - -def deleteMenuItems( menu ): - """Delete the menu items.""" - try: - lastMenuIndex = menu.index( Tkinter.END ) - if lastMenuIndex is not None: - menu.delete( 0, lastMenuIndex ) - except: - print('this should never happen, the lastMenuIndex in deleteMenuItems in settings could not be determined.') - -def getAlongWayHexadecimalColor( beginBrightness, colorWidth, difference, endColorTuple, wayLength ): - """Get a color along the way from begin brightness to the end color.""" - alongWay = 1.0 - if wayLength != 0.0: - alongWay = 0.4 + 0.6 * min( 1.0, abs( float( difference ) / float( wayLength ) ) ) - hexadecimalColor = '#' - oneMinusAlongWay = 1.0 - alongWay - for primaryIndex in xrange(3): - hexadecimalColor += getAlongWayHexadecimalPrimary( beginBrightness, oneMinusAlongWay, colorWidth, endColorTuple[ primaryIndex ], alongWay ) - return hexadecimalColor - -def getAlongWayHexadecimalPrimary( beginBrightness, beginRatio, colorWidth, endBrightness, endRatio ): - """Get a primary color along the way from grey to the end color.""" - brightness = beginRatio * float( beginBrightness ) + endRatio * float( endBrightness ) - return getWidthHex( int( round( brightness ) ), colorWidth ) - -def getDisplayedDialogFromConstructor(repository): - """Display the repository dialog.""" - try: - getReadRepository(repository) - return RepositoryDialog( repository, Tkinter.Tk() ) - except: - print('this should never happen, getDisplayedDialogFromConstructor in settings could not open') - print(repository) - traceback.print_exc(file=sys.stdout) - return None - -def getDisplayedDialogFromPath(path): - """Display the repository dialog.""" - pluginModule = archive.getModuleWithPath(path) - if pluginModule is None: - return None - return getDisplayedDialogFromConstructor( pluginModule.getNewRepository() ) - -def getDisplayToolButtonsRepository( directoryPath, importantFileNames, names, repository ): - """Get the display tool buttons.""" - displayToolButtons = [] - for name in names: - displayToolButton = DisplayToolButton().getFromPath( name in importantFileNames, name, os.path.join( directoryPath, name ), repository ) - displayToolButtons.append( displayToolButton ) - return displayToolButtons - -def getEachWordCapitalized( name ): - """Get the capitalized name.""" - withSpaces = name.lower().replace('_', ' ') - words = withSpaces.split(' ') - capitalizedStrings = [] - for word in words: - capitalizedStrings.append( word.capitalize() ) - return ' '.join( capitalizedStrings ) - -def getFileInAlterationsOrGivenDirectory(fileName): - """Get the file from the fileName or the lowercase fileName in the alterations directories.""" - settingsAlterationsDirectory = archive.getSettingsPath('alterations') - archive.makeDirectory(settingsAlterationsDirectory) - fileInSettingsAlterationsDirectory = getFileInGivenDirectory(settingsAlterationsDirectory, fileName) - if fileInSettingsAlterationsDirectory != '': - return fileInSettingsAlterationsDirectory - alterationsDirectory = archive.getSkeinforgePath('alterations') - return getFileInGivenDirectory(alterationsDirectory, fileName) - -def getFileInGivenDirectory( directory, fileName ): - """Get the file from the fileName or the lowercase fileName in the given directory.""" - directoryListing = os.listdir(directory) - lowerFileName = fileName.lower() - for directoryFile in directoryListing: - if directoryFile.lower() == lowerFileName: - return getFileTextGivenDirectoryFileName( directory, directoryFile ) - return '' - -def getFileTextGivenDirectoryFileName( directory, fileName ): - """Get the entire text of a file with the given file name in the given directory.""" - absoluteFilePath = os.path.join( directory, fileName ) - return archive.getFileText( absoluteFilePath ) - -def getFolders(directory): - """Get the folder list in a directory.""" - archive.makeDirectory(directory) - directoryListing = [] - try: - directoryListing = os.listdir(directory) - except OSError: - print('Skeinforge can not list the directory:') - print(directory) - print('so give it read/write permission for that directory.') - folders = [] - for fileName in directoryListing: - if os.path.isdir( os.path.join( directory, fileName ) ): - folders.append(fileName) - return folders - -def getGlobalRepositoryDialogValues(): - """Get the global repository dialog values.""" - global globalRepositoryDialogListTable - return euclidean.getListTableElements(globalRepositoryDialogListTable) - -def getLinesInAlterationsOrGivenDirectory(fileName): - """Get the text lines from the fileName in the alterations directories, if there is no file look in the given directory.""" - return archive.getTextLines(getFileInAlterationsOrGivenDirectory(fileName)) - -def getPathInFabmetheusFromFileNameHelp( fileNameHelp ): - """Get the directory path from file name help.""" - fabmetheusPath = archive.getFabmetheusPath() - splitFileNameHelps = fileNameHelp.split('.') - splitFileNameDirectoryNames = splitFileNameHelps[ : - 1 ] - for splitFileNameDirectoryName in splitFileNameDirectoryNames: - fabmetheusPath = os.path.join( fabmetheusPath, splitFileNameDirectoryName ) - return fabmetheusPath - -def getProfileBaseName(repository): - """Get the profile base file name.""" - if repository.getProfileDirectory is None: - return repository.baseName - return os.path.join(repository.getProfileDirectory(), repository.baseName) - -def getProfileBaseNameSynonym(repository): - """Get the profile base file name synonym.""" - if repository.getProfileDirectory is None: - return repository.baseNameSynonym - return os.path.join(repository.getProfileDirectory(), repository.baseNameSynonym) - -def getProfilesDirectoryInAboveDirectory(subName=''): - """Get the profiles directory path in the above directory.""" - aboveProfilesDirectory = archive.getSkeinforgePath('profiles') - if subName == '': - return aboveProfilesDirectory - return os.path.join( aboveProfilesDirectory, subName ) - -def getRadioPluginsAddPluginFrame( directoryPath, importantFileNames, names, repository ): - """Get the radio plugins and add the plugin frame.""" - repository.pluginFrame = PluginFrame() - radioPlugins = [] - for name in names: - radioPlugin = RadioPlugin().getFromRadio( name in importantFileNames, repository.pluginFrame.latentStringVar, name, repository, name == importantFileNames[0] ) - radioPlugin.updateFunction = repository.pluginFrame.update - radioPlugins.append( radioPlugin ) - defaultRadioButton = getSelectedRadioPlugin( importantFileNames + [ radioPlugins[0].name ], radioPlugins ) - repository.pluginFrame.getFromPath( defaultRadioButton, directoryPath, repository ) - return radioPlugins - -def getReadRepository(repository): - """Read and return settings from a file.""" - text = archive.getFileText(archive.getProfilesPath(getProfileBaseName(repository)), False) - if text == '': - if repository.baseNameSynonym is not None: - text = archive.getFileText(archive.getProfilesPath(getProfileBaseNameSynonym(repository)), False) - if text == '': - print('The default %s will be written in the .skeinforge folder in the home directory.' % repository.title.lower() ) - text = archive.getFileText(getProfilesDirectoryInAboveDirectory(getProfileBaseName(repository)), False) - if text != '': - readSettingsFromText(repository, text) - writeSettings(repository) - temporaryApplyOverrides(repository) - return repository - readSettingsFromText(repository, text) - temporaryApplyOverrides(repository) - return repository - -def getRepositoryText(repository): - """Get the text representation of the repository.""" - repositoryWriter = cStringIO.StringIO() - repositoryWriter.write('Format is tab separated %s.\n' % repository.title.lower() ) - repositoryWriter.write('_Name %sValue\n' % globalSpreadsheetSeparator ) - for setting in repository.preferences: - setting.writeToRepositoryWriter( repositoryWriter ) - return repositoryWriter.getvalue() - -def getSelectedPluginModuleFromPath( filePath, plugins ): - """Get the selected plugin module.""" - for plugin in plugins: - if plugin.value: - return gcodec.getModuleFromPath( plugin.name, filePath ) - return None - -def getSelectedPluginName( plugins ): - """Get the selected plugin name.""" - for plugin in plugins: - if plugin.value: - return plugin.name - return '' - -def getSelectedRadioPlugin( names, radioPlugins ): - """Get the selected radio button if it exists, None otherwise.""" - for radioPlugin in radioPlugins: - if radioPlugin.value: - return radioPlugin - for name in names: - for radioPlugin in radioPlugins: - if radioPlugin.name == name: - radioPlugin.value = True - return radioPlugin - print('this should never happen, no getSelectedRadioPlugin in settings') - print( names ) - return radioPlugin[0] - -def getShortestUniqueSettingName(settingName, settings): - """Get the shortest unique name in the settings.""" - for length in xrange(3, len(settingName)): - numberOfEquals = 0 - shortName = settingName[: length] - for setting in settings: - if setting.name[: length] == shortName: - numberOfEquals += 1 - if numberOfEquals < 2: - return shortName.lower() - return settingName.lower() - -def getSubfolderWithBasename( basename, directory ): - """Get the subfolder in the directory with the basename.""" - archive.makeDirectory(directory) - directoryListing = os.listdir(directory) - for fileName in directoryListing: - joinedFileName = os.path.join( directory, fileName ) - if os.path.isdir(joinedFileName): - if basename == fileName: - return joinedFileName - return None - -def getTitleFromName( title ): - """Get the title of this setting.""" - if title[-1] == ':': - title = title[ : - 1 ] - spaceBracketIndex = title.find(' (') - if spaceBracketIndex > - 1: - return title[ : spaceBracketIndex ] - return title - -def getUntilFirstBracket(text): - """Get the text until the first bracket, if any.""" - dotIndex = text.find('(') - if dotIndex < 0: - return text - return text[: dotIndex] - -def getWidthHex( number, width ): - """Get the first width hexadecimal digits.""" - return ('0000%s' % hex(number)[ 2 : ] )[ - width : ] - -def liftRepositoryDialogs( repositoryDialogs ): - """Lift the repository dialogs.""" - for repositoryDialog in repositoryDialogs: - repositoryDialog.root.withdraw() # the withdraw & deiconify trick is here because lift does not work properly on my linux computer - repositoryDialog.root.lift() # probably not necessary, here in case the withdraw & deiconify trick does not work on some other computer - repositoryDialog.root.deiconify() - repositoryDialog.root.lift() # probably not necessary, here in case the withdraw & deiconify trick does not work on some other computer - repositoryDialog.root.update_idletasks() - -def openSVGPage( fileName, svgViewer ): - """Open svg page with an svg program.""" - if svgViewer == '': - return - if svgViewer == 'webbrowser': - openWebPage(fileName) - return - filePath = '"' + os.path.normpath(fileName) + '"' # " to send in file name with spaces - shellCommand = svgViewer + ' ' + filePath - commandResult = os.system(shellCommand) - if commandResult != 0: - print('It may be that the system could not find the %s program.' % svgViewer ) - print('If so, try installing the %s program or look for another svg viewer, like Netscape which can be found at:' % svgViewer ) - print('http://www.netscape.org/') - print('') - -def openWebPage( webPagePath ): - """Open a web page in a browser.""" - if webPagePath.find('#') != - 1: # to get around # encode bug - redirectionText = '\n\n\n' - redirectionText += '\n\n' % webPagePath - webPagePath = archive.getDocumentationPath('redirect.html') - archive.writeFileText( webPagePath, redirectionText ) - webPagePath = '"%s"' % webPagePath # " to get around space in url bug - try: - os.startfile( webPagePath )#this is available on some python environments, but not all - return - except: - pass - webbrowserName = webbrowser.get().name - if webbrowserName == '': - print('Skeinforge was not able to open the file in a web browser. To see the documentation, open the following file in a web browser:') - print( webPagePath ) - return - os.system( webbrowserName + ' ' + webPagePath )#used this instead of webbrowser.open() to workaround webbrowser open() bug - -def printProgress(layerIndex, procedureName): - """Print layerIndex followed by a carriage return.""" - printProgressByString('%s layer count %s...' % (procedureName.capitalize(), layerIndex + 1)) - -def printProgressByString(progressString): - """Print progress string.""" - sys.stdout.write(progressString) - sys.stdout.write(chr(27) + '\r') - sys.stdout.flush() - -def printProgressByNumber(layerIndex, numberOfLayers, procedureName): - """Print layerIndex and numberOfLayers followed by a carriage return.""" - printProgressByString('%s layer count %s of %s...' % (procedureName.capitalize(), layerIndex + 1, numberOfLayers)) - -def quitWindow(root): - """Quit a window.""" - try: - root.destroy() - except: - pass - -def quitWindows( event=None ): - """Quit all windows.""" - global globalRepositoryDialogListTable - globalRepositoryDialogValues = euclidean.getListTableElements( globalRepositoryDialogListTable ) - for globalRepositoryDialogValue in globalRepositoryDialogValues: - quitWindow(globalRepositoryDialogValue.root) - -def readSettingsFromText(repository, text): - """Read settings from a text.""" - text = text.replace(('\nName %sValue\n' % globalSpreadsheetSeparator), ('\n_Name %sValue\n' % globalSpreadsheetSeparator)) - lines = archive.getTextLines(text) - shortDictionary = {} - for setting in repository.preferences: - shortDictionary[getShortestUniqueSettingName(setting.name, repository.preferences)] = setting - for lineIndex in xrange(len(lines)): - setRepositoryToLine(lineIndex, lines, shortDictionary) - -def saveAll(): - """Save all the dialogs.""" - for globalRepositoryDialogValue in getGlobalRepositoryDialogValues(): - globalRepositoryDialogValue.save() - -def saveRepository(repository): - """Set the entities to the dialog then write them.""" - for setting in repository.preferences: - setting.setToDisplay() - writeSettingsPrintMessage(repository) - for saveListener in repository.saveListenerTable.values(): - saveListener() - -def setButtonFontWeightString( button, isBold ): - """Set button font weight given isBold.""" - try: - weightString = 'normal' - if isBold: - weightString = 'bold' - splitFont = button['font'].split() - button['font'] = ( splitFont[0], splitFont[1], weightString ) - except: - pass - -def setEntryText( entry, value ): - """Set the entry text.""" - if entry is None: - return - entry.delete( 0, Tkinter.END ) - entry.insert( 0, str(value) ) - -def setIntegerValueToString( integerSetting, valueString ): - """Set the integer to the string.""" - dotIndex = valueString.find('.') - if dotIndex > - 1: - valueString = valueString[: dotIndex] - try: - integerSetting.value = int( valueString ) - return - except: - print('Warning, can not read integer ' + integerSetting.name + ' ' + valueString ) - print('Will try reading as a boolean, which might be a mistake.') - integerSetting.value = 0 - if valueString.lower() == 'true': - integerSetting.value = 1 - -def setRepositoryToLine(lineIndex, lines, shortDictionary): - """Set setting dictionary to a setting line.""" - line = lines[lineIndex] - splitLine = line.split(globalSpreadsheetSeparator) - if len(splitLine) < 2: - return - fileSettingName = splitLine[0] - shortDictionaryKeys = shortDictionary.keys() - shortDictionaryKeys.sort(key=len, reverse=True) # so that a short word like fill is not overidden by a longer word like fillet - for shortDictionaryKey in shortDictionaryKeys: - if fileSettingName[: len(shortDictionaryKey)].lower() == shortDictionaryKey: - shortDictionary[shortDictionaryKey].setValueToSplitLine(lineIndex, lines, splitLine) - return - -def setSpinColor( setting ): - """Set the spin box color to the value, yellow if it is lower than the default and blue if it is higher.""" - if setting.entry is None: - return - if setting.backgroundColor is None: - setting.backgroundColor = setting.entry['background'] - if setting.backgroundColor[0] != '#': - setting.backgroundColor = '#ffffff' - setting.colorWidth = len( setting.backgroundColor ) / 3 - setting.grey = int( setting.backgroundColor[ 1 : 1 + setting.colorWidth ], 16 ) - setting.white = int('f' * setting.colorWidth, 16 ) - if abs( setting.value - setting.defaultValue ) <= 0.75 * setting.increment: - setting.entry['background'] = setting.backgroundColor - return - difference = setting.value - setting.defaultValue - if difference > 0.0: - wayLength = setting.to - setting.defaultValue - setting.entry['background'] = getAlongWayHexadecimalColor( setting.grey, setting.colorWidth, difference, ( 0, setting.white, setting.white ), wayLength ) - return - wayLength = setting.from_ - setting.defaultValue - setting.entry['background'] = getAlongWayHexadecimalColor( setting.grey, setting.colorWidth, difference, ( setting.white, setting.white, 0 ), wayLength ) - -def startMainLoopFromConstructor(repository): - """Display the repository dialog and start the main loop.""" - try: - import Tkinter - except: - return - displayedDialogFromConstructor = getDisplayedDialogFromConstructor(repository) - if displayedDialogFromConstructor is None: - print('Warning, displayedDialogFromConstructor in settings is none, so the window will not be displayed.') - else: - displayedDialogFromConstructor.root.mainloop() - -def startMainLoopFromWindow(window): - """Display the tableau window and start the main loop.""" - if window is None: - return - if window.root is None: - print('Warning, window.root in startMainLoopFromWindow in settings is none, so the window will not be displayed.') - return - window.root.mainloop() - -def temporaryAddPreferenceOverride(module, name, value): - global globalTemporaryOverrides - if not module in globalTemporaryOverrides: - globalTemporaryOverrides[module] = {} - globalTemporaryOverrides[module][name] = value - print('OVERRIDE %s %s %s' % (module,name,value)) - print(globalTemporaryOverrides[module]) - -def temporaryApplyOverrides(repository): - """Apply any overrides that have been set at the command line.""" - # The override dictionary is a mapping of repository names to - # key-value mappings. - global globalTemporaryOverrides - if repository.baseName in globalTemporaryOverrides: - settingTable = {} - for setting in repository.preferences: - settingTable[ setting.name ] = setting - for (name, value) in overrides[repository.baseName].items(): - if name in settingTable: - settingTable[name].setValueToString(value) - else: - print('Override not applied for: %s, %s' % (name,value)) - -def writeValueListToRepositoryWriter( repositoryWriter, setting ): - """Write tab separated name and list to the repository writer.""" - repositoryWriter.write( setting.name ) - for item in setting.value: - if item != '[]': - repositoryWriter.write(globalSpreadsheetSeparator) - repositoryWriter.write( item ) - repositoryWriter.write('\n') - -def writeSettings(repository): - """Write the settings to a file.""" - profilesDirectoryPath = archive.getProfilesPath(getProfileBaseName(repository)) - archive.makeDirectory(os.path.dirname(profilesDirectoryPath)) - archive.writeFileText(profilesDirectoryPath, getRepositoryText(repository)) - for setting in repository.preferences: - setting.updateSaveListeners() - -def writeSettingsPrintMessage(repository): - """Set the settings to the dialog then write them.""" - writeSettings(repository) - print( repository.title.lower().capitalize() + ' have been saved.') - - -class StringSetting: - """A class to display, read & write a string.""" - def __init__(self): - """Set the update function to none.""" - self.entry = None - self.updateFunction = None - - def __repr__(self): - """Get the string representation of this StringSetting.""" - return str(self.__dict__) - - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - gridPosition.increment() - self.label = Tkinter.Label( gridPosition.master, text = self.name ) - self.label.grid( row = gridPosition.row, column = 0, columnspan = 3, sticky = Tkinter.W ) - self.createEntry( gridPosition.master ) - self.setStateToValue() - self.entry.grid( row = gridPosition.row, column = 3, columnspan = 2, sticky = Tkinter.W ) - self.bindEntry() - LabelHelp( self.repository.fileNameHelp, gridPosition.master, self.name, self.label ) - - def addToMenu( self, repositoryMenu ): - """Do nothing because this should only be added to a frameable repository menu.""" - pass - - def addToMenuFrameable( self, repositoryMenu ): - """Add this to the frameable repository menu.""" - titleFromName = getTitleFromName( self.name ) - helpWindowMenu = Tkinter.Menu( repositoryMenu, tearoff = 0 ) - repositoryMenu.add_cascade( label = titleFromName, menu = helpWindowMenu, underline = 0 ) - if self.name in self.repository.frameList.value: - helpWindowMenu.add_command( label = 'Remove from Window', command = self.removeFromWindow ) - else: - helpWindowMenu.add_command( label = 'Add to Window', command = self.addToWindow ) - helpWindowMenu.add_separator() - helpWindowMenu.add_command( label = 'Help', command = HelpPage().getOpenFromDocumentationSubName( self.repository.fileNameHelp + '#' + titleFromName ) ) - - def addToWindow(self): - """Add this to the repository frame list.""" - self.repository.frameList.addToList( self.name ) - - def bindEntry(self): - """Bind the entry to the update function.""" - if self.updateFunction is not None: - self.entry.bind('', self.updateFunction ) - - def createEntry( self, root ): - """Create the entry.""" - self.entry = Tkinter.Entry( root ) - - def getFromValue( self, name, repository, value ): - """Initialize.""" - return self.getFromValueOnlyAddToRepository( name, repository, value ) - - def getFromValueOnly( self, name, repository, value ): - """Initialize.""" - self.defaultValue = value - self.name = name - self.repository = repository - self.value = value - return self - - def getFromValueOnlyAddToRepository( self, name, repository, value ): - """Initialize.""" - repository.displayEntities.append(self) - repository.menuEntities.append(self) - repository.preferences.append(self) - return self.getFromValueOnly( name, repository, value ) - - def removeFromWindow(self): - """Remove this from the repository frame list.""" - self.repository.frameList.removeFromList( self.name ) - - def setStateToValue(self): - """Set the entry to the value.""" - setEntryText( self.entry, self.value ) - - def setToDisplay(self): - """Set the string to the entry field.""" - try: - valueString = self.entry.get() - self.setValueToString( valueString ) - except: - pass - - def setUpdateFunction( self, updateFunction ): - """Set the update function.""" - self.updateFunction = updateFunction - - def setValueToSplitLine( self, lineIndex, lines, splitLine ): - """Set the value to the second word of a split line.""" - self.setValueToString(splitLine[1]) - - def setValueToString( self, valueString ): - """Set the value to the value string.""" - self.value = valueString - - def updateSaveListeners(self): - """Update save listeners if any.""" - pass - - def writeToRepositoryWriter( self, repositoryWriter ): - """Write tab separated name and value to the repository writer.""" - repositoryWriter.write('%s%s%s\n' % ( self.name, globalSpreadsheetSeparator, self.value ) ) - - -class BooleanSetting( StringSetting ): - """A class to display, read & write a boolean.""" - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - gridPosition.increment() - self.checkbutton = Tkinter.Checkbutton( gridPosition.master, command = self.toggleCheckbutton, text = self.name ) -#toggleCheckbutton is being used instead of a Tkinter IntVar because there is a weird bug where it doesn't work properly if this setting is not on the first window. - self.checkbutton.grid( row = gridPosition.row, columnspan = 5, sticky = Tkinter.W ) - self.setStateToValue() - LabelHelp( self.repository.fileNameHelp, gridPosition.master, self.name, self.checkbutton ) - - def addToMenu( self, repositoryMenu ): - """Add this to the repository menu.""" - self.activateToggleMenuCheckbutton = False -#activateToggleMenuCheckbutton is being used instead of setting command after because add_checkbutton does not return a checkbutton. - repositoryMenu.add_checkbutton( label = getTitleFromName( self.name ), command = self.toggleMenuCheckbutton ) - if self.value: - repositoryMenu.invoke( repositoryMenu.index( Tkinter.END ) ) - self.activateToggleMenuCheckbutton = True - - def addToMenuFrameable( self, repositoryMenu ): - """Add this to the frameable repository menu.""" - titleFromName = getTitleFromName( self.name ) - helpWindowMenu = Tkinter.Menu( repositoryMenu, tearoff = 0 ) - repositoryMenu.add_cascade( label = titleFromName, menu = helpWindowMenu, underline = 0 ) - self.addToMenu( helpWindowMenu ) - helpWindowMenu.add_separator() - helpWindowMenu.add_command( label = 'Help', command = HelpPage().getOpenFromDocumentationSubName( self.repository.fileNameHelp + '#' + titleFromName ) ) - - def setStateToValue(self): - """Set the checkbutton to the boolean.""" - try: - if self.value: - self.checkbutton.select() - else: - self.checkbutton.deselect() - except: - pass - - def setToDisplay(self): - """Do nothing because toggleCheckbutton is handling the value.""" - pass - - def setValueToString( self, valueString ): - """Set the boolean to the string.""" - self.value = ( valueString.lower() == 'true') - - def toggleCheckbutton(self): - """Workaround for Tkinter bug, toggle the value.""" - self.value = not self.value - self.setStateToValue() - if self.updateFunction is not None: - self.updateFunction() - - def toggleMenuCheckbutton(self): - """Workaround for Tkinter bug, toggle the value.""" - if self.activateToggleMenuCheckbutton: - self.value = not self.value - if self.updateFunction is not None: - self.updateFunction() - - -class CloseListener: - """A class to listen to link a window to the global repository dialog list table.""" - def __init__( self, window, closeFunction = None ): - """Add the window to the global repository dialog list table.""" - self.closeFunction = closeFunction - self.window = window - self.shouldWasClosedBeBound = True - global globalRepositoryDialogListTable - euclidean.addElementToListDictionaryIfNotThere( window, window, globalRepositoryDialogListTable ) - - def listenToWidget( self, widget ): - """Listen to the destroy message of the widget.""" - if self.shouldWasClosedBeBound: - self.shouldWasClosedBeBound = False - widget.bind('', self.wasClosed ) - - def wasClosed(self, event): - """The dialog was closed.""" - global globalCloseListTables - for globalCloseListTable in globalCloseListTables: - if self.window in globalCloseListTable: - del globalCloseListTable[ self.window ] - if self.closeFunction is not None: - self.closeFunction() - - -class DisplayToolButton: - """A class to display the tool dialog button, in a two column wide table.""" - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - self.displayButton = Tkinter.Button( gridPosition.master, activebackground = 'black', activeforeground = 'white', text = getEachWordCapitalized( self.name ), command = self.displayDialog ) - setButtonFontWeightString( self.displayButton, self.important ) - gridPosition.incrementGivenNumberOfColumns(2) - self.displayButton.grid( row = gridPosition.row, column = gridPosition.column, columnspan = 2 ) - - def displayDialog(self): - """Display function.""" - ToolDialog().getFromPath( self.path ).display() - - def getFromPath( self, important, name, path, repository ): - """Initialize.""" - self.important = important - self.name = name - self.path = path - self.repository = repository - repository.displayEntities.append(self) - return self - - -class FileHelpMenuBar: - def __init__( self, root ): - """Create a menu bar with a file and help menu.""" - self.underlineLetters = [] - self.menuBar = Tkinter.Menu( root ) - self.root = root - root.config( menu = self.menuBar ) - self.fileMenu = Tkinter.Menu( self.menuBar, tearoff = 0 ) - self.menuBar.add_cascade( label = "File", menu = self.fileMenu, underline = 0 ) - self.underlineLetters.append('f') - - def addMenuToMenuBar( self, labelText, menu ): - """Add a menu to the menu bar.""" - lowerLabelText = labelText.lower() - for underlineLetterIndex in xrange( len( lowerLabelText ) ): - underlineLetter = lowerLabelText[ underlineLetterIndex ] - if underlineLetter not in self.underlineLetters: - self.underlineLetters.append( underlineLetter ) - self.menuBar.add_cascade( label = labelText, menu = menu, underline = underlineLetterIndex ) - return - self.menuBar.add_cascade( label = labelText, menu = menu ) - - def addPluginToMenuBar( self, modulePath, repository, window ): - """Add a menu to the menu bar from a tool.""" - pluginModule = archive.getModuleWithPath( modulePath ) - if pluginModule is None: - print('this should never happen, pluginModule in addMenuToMenuBar in settings is None.') - return None - repositoryMenu = Tkinter.Menu( self.menuBar, tearoff = 0 ) - labelText = getEachWordCapitalized( os.path.basename( modulePath ) ) - self.addMenuToMenuBar( labelText, repositoryMenu ) - pluginModule.addToMenu( self.root, repositoryMenu, repository, window ) - - def completeMenu(self, closeFunction, repository, saveFunction, window): - """Complete the menu.""" - self.closeFunction = closeFunction - self.saveFunction = saveFunction - addAcceleratorCommand('', saveFunction, self.root, self.fileMenu, 'Save') - self.fileMenu.add_command(label = "Save and Close", command = self.saveClose) - addAcceleratorCommand('', closeFunction, self.root, self.fileMenu, 'Close') - self.fileMenu.add_separator() - addAcceleratorCommand('', quitWindows, self.root, self.fileMenu, 'Quit') - skeinforgePluginsPath = archive.getSkeinforgePath('skeinforge_plugins') - pluginFileNames = archive.getPluginFileNamesFromDirectoryPath(skeinforgePluginsPath) - for pluginFileName in pluginFileNames: - self.addPluginToMenuBar(os.path.join(skeinforgePluginsPath, pluginFileName), repository, window) - - def saveClose(self): - """Call the save function then the close function.""" - self.saveFunction() - self.closeFunction() - - -class FileNameInput( StringSetting ): - """A class to display, read & write a fileName.""" - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - self.gridPosition = gridPosition - gridPosition.executables.append(self) - - def execute(self): - """Open the file picker.""" - self.wasCancelled = False - parent = self.gridPosition.master - try: - import tkFileDialog - summarized = archive.getSummarizedFileName(self.value) - initialDirectory = os.path.dirname( summarized ) - if len( initialDirectory ) > 0: - initialDirectory += os.sep - else: - initialDirectory = "." - fileName = tkFileDialog.askopenfilename( filetypes = self.getFileNameFirstTypes(), initialdir = initialDirectory, initialfile = os.path.basename( summarized ), parent = parent, title = self.name ) - self.setCancelledValue(fileName) - return - except: - print('Could not get the old directory in settings, so the file picker will be opened in the default directory.') - try: - fileName = tkFileDialog.askopenfilename( filetypes = self.getFileNameFirstTypes(), initialdir = '.', initialfile = '', parent = parent, title = self.name ) - self.setCancelledValue(fileName) - except: - print('Error in execute in FileName in settings, ' + self.name ) - - def getFileNameFirstTypes(self): - """Get the file types with the file type of the fileName moved to the front of the list.""" - allFiles = [ ('All', '*.*') ] - try: - basename = os.path.basename(self.value) - splitFile = basename.split('.') - allReadables = [] - if len( self.fileTypes ) > 1: - for fileType in self.fileTypes: - allReadable = ( ('All Readable', fileType[1] ) ) - allReadables.append( allReadable ) - if len( splitFile ) < 1: - return allReadables + allFiles + self.fileTypes - baseExtension = splitFile[-1] - for fileType in self.fileTypes: - fileExtension = fileType[1].split('.')[-1] - if fileExtension == baseExtension: - fileNameFirstTypes = self.fileTypes[:] - fileNameFirstTypes.remove( fileType ) - return [ fileType ] + allReadables + allFiles + fileNameFirstTypes - return allReadables + allFiles + self.fileTypes - except: - return allFiles - - def getFromFileName( self, fileTypes, name, repository, value ): - """Initialize.""" - self.getFromValueOnly( name, repository, value ) - self.fileTypes = fileTypes - self.wasCancelled = False - repository.displayEntities.append(self) - repository.preferences.append(self) - return self - - def setCancelledValue( self, fileName ): - """Set the value to the file name and wasCancelled true if a file was not picked.""" - if str(fileName) == '()' or str(fileName) == '': - self.wasCancelled = True - else: - self.value = fileName - - def setToDisplay(self): - """Do nothing because the file dialog is handling the value.""" - pass - - -class FloatSetting( StringSetting ): - """A class to display, read & write a float.""" - def setValueToString( self, valueString ): - """Set the float to the string.""" - try: - self.value = float( valueString ) - except: - print('Oops, can not read float' + self.name + ' ' + valueString ) - - -class FloatSpin( FloatSetting ): - """A class to display, read & write an float in a spin box.""" - def addToMenuFrameable( self, repositoryMenu ): - """Add this to the frameable repository menu.""" - titleFromName = getTitleFromName( self.name ) - helpWindowMenu = Tkinter.Menu( repositoryMenu, tearoff = 0 ) - repositoryMenu.add_cascade( label = titleFromName, menu = helpWindowMenu, underline = 0 ) - if self.name in self.repository.frameList.value: - helpWindowMenu.add_command( label = 'Remove from Window', command = self.removeFromWindow ) - else: - helpWindowMenu.add_command( label = 'Add to Window', command = self.addToWindow ) - helpWindowMenu.add_separator() - changeString = ' by %s' % self.increment - helpWindowMenu.add_command( label = 'Increase' + changeString, command = self.increase ) - helpWindowMenu.add_command( label = 'Decrease' + changeString, command = self.decrease ) - helpWindowMenu.add_separator() - helpWindowMenu.add_command( label = 'Help', command = HelpPage().getOpenFromDocumentationSubName( self.repository.fileNameHelp + '#' + titleFromName ) ) - - def bindEntry(self): - """Bind the entry to the update function.""" - self.entry.bind('', self.entryUpdated ) - self.setColor() - - def createEntry( self, root ): - """Create the entry.""" - self.entry = Tkinter.Spinbox( root, command = self.setColorToDisplay, from_ = self.from_, increment = self.increment, to = self.to ) - - def decrease(self): - """Decrease the value then set the state and color to the value.""" - self.value -= self.increment - self.setStateUpdateColor() - - def entryUpdated(self, event=None): - """Create the entry.""" - self.setColorToDisplay() - if self.updateFunction is not None: - self.updateFunction(event) - - def getFromValue(self, from_, name, repository, to, value): - """Initialize.""" - self.backgroundColor = None - self.from_ = from_ - self.minimumWidth = min(value - from_, to - value) - rank = euclidean.getRank(0.05 * (to - from_)) - self.increment = euclidean.getIncrementFromRank(rank) - self.to = to - return self.getFromValueOnlyAddToRepository(name, repository, value) - - def increase(self): - """Increase the value then set the state and color to the value.""" - self.value += self.increment - self.setStateUpdateColor() - - def setColor(self, event=None): - """Set the color to the value, yellow if it is lower than the default and blue if it is higher.""" - setSpinColor(self) - - def setColorToDisplay(self, event=None): - """Set the color to the value, yellow if it is lower than the default and blue if it is higher.""" - self.setToDisplay() - self.setColor() - - def setStateToValue(self): - """Set the entry to the value.""" - setEntryText( self.entry, self.value ) - self.setColor() - - def setStateUpdateColor(self): - """Set the state to the value, call the update function, then set the color.""" - self.setStateToValue() - if self.updateFunction is not None: - self.updateFunction() - - -class FloatSpinNotOnMenu( FloatSpin ): - """A class to display, read & write an float in a spin box, which is not to be added to a menu.""" - def getFromValueOnlyAddToRepository( self, name, repository, value ): - """Initialize.""" - repository.displayEntities.append(self) - repository.preferences.append(self) - return self.getFromValueOnly( name, repository, value ) - - -class FloatSpinUpdate( FloatSpin ): - """A class to display, read, update & write an float in a spin box.""" - def createEntry( self, root ): - """Create the entry.""" - self.entry = Tkinter.Spinbox( root, command = self.entryUpdated, from_ = self.from_, increment = self.increment, to = self.to ) - - -class FrameList: - """A class to list the frames.""" - def addToList(self, word): - """Add the word to the sorted list.""" - self.value.append(word) - self.value.sort() - self.repository.window.redisplayWindowUpdate() - - def getFromValue( self, name, repository, value ): - """Initialize.""" - repository.preferences.append(self) - self.name = name - self.repository = repository - self.value = value - return self - - def removeFromList(self, word): - """Remove the word from the sorted list.""" - self.value.remove(word) - self.value.sort() - self.repository.window.redisplayWindowUpdate() - - def setToDisplay(self): - """Do nothing because frame list does not have a display.""" - pass - - def setValueToSplitLine( self, lineIndex, lines, splitLine ): - """Set the value to the second and later words of a split line.""" - self.value = splitLine[1 :] - - def updateSaveListeners(self): - """Update save listeners if any.""" - pass - - def writeToRepositoryWriter( self, repositoryWriter ): - """Write tab separated name and list to the repository writer.""" - writeValueListToRepositoryWriter( repositoryWriter, self ) - - -class GridHorizontal: - """A class to place elements horizontally on a grid.""" - def __init__( self, column, row ): - """Initialize the column and row.""" - self.column = column - self.columnStart = column - self.row = row - - def getCopy(self): - """Get a copy.""" - copy = GridHorizontal( self.column, self.row ) - copy.columnStart = self.columnStart - return copy - - def increment(self): - """Increment the position horizontally.""" - self.column += 1 - - -class GridVertical: - """A class to place elements vertically on a grid.""" - def __init__( self, column, row ): - """Initialize the column and row.""" - self.column = column - self.columnOffset = column - self.columnStart = column - self.row = row - self.rowStart = row - - def execute(self): - """The execute button was clicked.""" - for executable in self.executables: - executable.execute() - saveAll() - self.repository.execute() - - def getCopy(self): - """Get a copy.""" - copy = GridVertical( self.column, self.row ) - copy.columnOffset = self.columnOffset - copy.columnStart = self.columnStart - copy.rowStart = self.rowStart - return copy - - def increment(self): - """Increment the position vertically.""" - self.column = self.columnStart - self.columnOffset = self.columnStart - self.row += 1 - - def incrementGivenNumberOfColumns( self, numberOfColumns ): - """Increment the position vertically and offset it horizontally by the given number of columns.""" - self.column = self.columnOffset - if self.columnOffset == self.columnStart: - self.columnOffset = self.columnStart + 1 - self.row += 1 - return - if self.columnOffset < self.columnStart + numberOfColumns - 1: - self.columnOffset += 1 - return - self.columnOffset = self.columnStart - - def setExecutablesRepository( self, repository ): - """Set the executables to an empty list and set the repository.""" - self.executables = [] - self.repository = repository - - -class HelpPage: - """A class to open a help page.""" - def __init__(self): - """Initialize column.""" - self.column = 3 - - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - capitalizedName = getEachWordCapitalized( self.name ) - self.displayButton = Tkinter.Button( gridPosition.master, activebackground = 'black', activeforeground = 'white', command = self.openPage, text = capitalizedName ) - if len( capitalizedName ) < 12: - self.displayButton['width'] = 10 - self.displayButton.grid( row = gridPosition.row, column = self.column, columnspan = 2 ) - - def addToMenu( self, repositoryMenu ): - """Add this to the repository menu.""" - repositoryMenu.add_command( label = getTitleFromName( self.name ), command = self.openPage ) - - def addToMenuFrameable( self, repositoryMenu ): - """Add this to the frameable repository menu.""" - self.addToMenu( repositoryMenu ) - - def getFromNameAfterHTTP( self, afterHTTP, name, repository ): - """Initialize.""" - self.setToNameRepository( name, repository ) - self.hypertextAddress = 'http://' + afterHTTP - return self - - def getFromNameAfterWWW( self, afterWWW, name, repository ): - """Initialize.""" - self.setToNameRepository( name, repository ) - self.hypertextAddress = 'http://www.' + afterWWW - return self - - def getFromNameSubName( self, name, repository, subName=''): - """Initialize.""" - self.setToNameRepository( name, repository ) - self.hypertextAddress = archive.getDocumentationPath( subName ) - return self - - def getOpenFromAbsolute( self, hypertextAddress ): - """Get the open help page function from the hypertext address.""" - self.hypertextAddress = hypertextAddress - return self.openPage - - def getOpenFromAfterHTTP( self, afterHTTP ): - """Get the open help page function from the part of the address after the HTTP.""" - self.hypertextAddress = 'http://' + afterHTTP - return self.openPage - - def getOpenFromAfterWWW( self, afterWWW ): - """Get the open help page function from the afterWWW of the address after the www.""" - self.hypertextAddress = 'http://www.' + afterWWW - return self.openPage - - def getOpenFromDocumentationSubName( self, subName=''): - """Get the open help page function from the afterWWW of the address after the www.""" - self.hypertextAddress = archive.getDocumentationPath( subName ) - return self.openPage - - def openPage(self, event=None): - """Open the browser to the hypertext address.""" - openWebPage( self.hypertextAddress ) - - def setToNameRepository( self, name, repository ): - """Set to the name and repository.""" - self.name = name - self.repository = repository - repository.displayEntities.append(self) - repository.menuEntities.append(self) - - -class HelpPageRepository: - """A class to open a repository help page.""" - def __init__( self, repository ): - """Add this to the dialog.""" - self.repository = repository - - def openPage(self, event=None): - """Open the browser to the repository help page.""" - if self.repository.openWikiManualHelpPage is None: - self.repository.openLocalHelpPage() - return - from skeinforge_application.skeinforge_utilities import skeinforge_help - helpRepository = getReadRepository( skeinforge_help.HelpRepository() ) - if helpRepository.wikiManualPrimary.value: - self.repository.openWikiManualHelpPage() - return - self.repository.openLocalHelpPage() - - -class IntSetting( FloatSetting ): - """A class to display, read & write an int.""" - def setValueToString( self, valueString ): - """Set the integer to the string.""" - setIntegerValueToString( self, valueString ) - - -class IntSpin(FloatSpin): - """A class to display, read & write an int in a spin box.""" - def getFromValue(self, from_, name, repository, to, value): - """Initialize.""" - self.backgroundColor = None - self.from_ = from_ - rank = euclidean.getRank(0.05 * (to - from_)) - self.increment = max(1, int(euclidean.getIncrementFromRank(rank))) - self.minimumWidth = min(value - from_, to - value) - self.to = to - return self.getFromValueOnlyAddToRepository(name, repository, value) - - def getSingleIncrementFromValue( self, from_, name, repository, to, value ): - """Initialize.""" - self.backgroundColor = None - self.from_ = from_ - self.increment = 1 - self.minimumWidth = min(value - from_, to - value) - self.to = to - return self.getFromValueOnlyAddToRepository( name, repository, value ) - - def setValueToString( self, valueString ): - """Set the integer to the string.""" - setIntegerValueToString( self, valueString ) - - - -class IntSpinNotOnMenu( IntSpin ): - """A class to display, read & write an integer in a spin box, which is not to be added to a menu.""" - def getFromValueOnlyAddToRepository( self, name, repository, value ): - """Initialize.""" - repository.displayEntities.append(self) - repository.preferences.append(self) - return self.getFromValueOnly( name, repository, value ) - - -class IntSpinUpdate( IntSpin ): - """A class to display, read, update & write an int in a spin box.""" - def createEntry( self, root ): - """Create the entry.""" - self.entry = Tkinter.Spinbox( root, command = self.entryUpdated, from_ = self.from_, increment = self.increment, to = self.to ) - - -class LabelDisplay: - """A class to add a label.""" - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - gridPosition.increment() - self.label = Tkinter.Label( gridPosition.master, text = self.name ) - self.label.grid( row = gridPosition.row, column = 0, columnspan = 3, sticky = Tkinter.W ) - LabelHelp( self.repository.fileNameHelp, gridPosition.master, self.name, self.label ) - - def getFromName( self, name, repository ): - """Initialize.""" - self.name = name - self.repository = repository - repository.displayEntities.append(self) - return self - - -class LabelHelp: - """A class to add help to a widget.""" - def __init__( self, fileNameHelp, master, name, widget ): - """Add menu to the widget.""" - if len( name ) < 1: - return - self.popupMenu = Tkinter.Menu( master, tearoff = 0 ) - titleFromName = getTitleFromName( name.replace('- ', '').replace(' -', '') ) - self.popupMenu.add_command( label = 'Help', command = HelpPage().getOpenFromDocumentationSubName( fileNameHelp + '#' + titleFromName ) ) - widget.bind('', self.unpostPopupMenu ) - widget.bind('', self.unpostPopupMenu ) - widget.bind('', self.displayPopupMenu ) - - def unpostPopupMenu(self, event=None): - """Unpost the popup menu.""" - self.popupMenu.unpost() - - def displayPopupMenu(self, event=None): - """Display the popup menu when the button is right clicked.""" - try: - self.popupMenu.tk_popup( event.x_root + 30, event.y_root, 0 ) - finally: - self.popupMenu.grab_release() - - -class LabelSeparator: - """A class to add a label and menu separator.""" - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - gridPosition.increment() - self.label = Tkinter.Label( gridPosition.master, text='') - self.label.grid( row = gridPosition.row, column = 0, columnspan = 3, sticky = Tkinter.W ) - - def addToMenu( self, repositoryMenu ): - """Add this to the repository menu.""" - repositoryMenu.add_separator() - - def addToMenuFrameable( self, repositoryMenu ): - """Add this to the frameable repository menu.""" - self.addToMenu( repositoryMenu ) - - def getFromRepository( self, repository ): - """Initialize.""" - self.name = '' - self.repository = repository - repository.displayEntities.append(self) - repository.menuEntities.append(self) - return self - - -class LatentStringVar: - """A class to provide a StringVar when needed.""" - def __init__(self): - """Set the string var.""" - self.stringVar = None - - def getVar(self): - """Get the string var.""" - if self.stringVar is None: - self.stringVar = Tkinter.StringVar() - return self.stringVar - - def getString(self): - """Get the string.""" - return self.getVar().get() - - def setString(self, word): - """Set the string.""" - self.getVar().set(word) - - -class LayerCount: - """A class to handle the layerIndex.""" - def __init__(self): - """Initialize.""" - self.layerIndex = 0 - - def __repr__(self): - """Get the string representation of this LayerCount.""" - return str(self.layerIndex) - - def printProgressIncrement(self, procedureName): - """Print progress then increment layerIndex.""" - printProgress(self.layerIndex, procedureName) - self.layerIndex += 1 - - -class MenuButtonDisplay: - """A class to add a menu button.""" - def addRadiosToDialog( self, gridPosition ): - """Add the menu radios to the dialog.""" - for menuRadio in self.menuRadios: - menuRadio.addToDialog( gridPosition ) - - def addToMenu( self, repositoryMenu ): - """Add this to the repository menu.""" - if len( self.menuRadios ) < 1: - print('The MenuButtonDisplay in settings should have menu items.') - print( self.name ) - return - self.menu = Tkinter.Menu( repositoryMenu, tearoff = 0 ) - repositoryMenu.add_cascade( label = getTitleFromName( self.name ), menu = self.menu ) - self.setRadioVarToName( self.menuRadios[0].name ) - - def addToMenuFrameable( self, repositoryMenu ): - """Add this to the frameable repository menu.""" - titleFromName = getTitleFromName( self.name ) - self.addToMenu( repositoryMenu ) - self.menu.add_command( label = 'Help', command = HelpPage().getOpenFromDocumentationSubName( self.repository.fileNameHelp + '#' + titleFromName ) ) - self.menu.add_separator() - - def getFromName( self, name, repository ): - """Initialize.""" - self.menuRadios = [] - self.name = name - self.radioVar = None - self.repository = repository - repository.menuEntities.append(self) - return self - - def removeMenus(self): - """Remove all menus.""" - deleteMenuItems( self.menu ) - self.menuRadios = [] - - def setRadioVarToName(self, name): - """Get the menu button.""" - self.optionList = [name] - self.radioVar = Tkinter.StringVar() - self.radioVar.set( self.optionList[0] ) - - def setToNameAddToDialog( self, name, gridPosition ): - """Get the menu button.""" - if self.radioVar is not None: - return - gridPosition.increment() - self.setRadioVarToName( name ) - self.label = Tkinter.Label( gridPosition.master, text = self.name ) - self.label.grid( row = gridPosition.row, column = 0, columnspan = 3, sticky = Tkinter.W ) - self.menuButton = Tkinter.OptionMenu( gridPosition.master, self.radioVar, self.optionList ) - self.menuButton.grid( row = gridPosition.row, column = 3, columnspan = 2, sticky = Tkinter.W ) - self.menuButton.menu = Tkinter.Menu( self.menuButton, tearoff = 0 ) - self.menu = self.menuButton.menu - self.menuButton['menu'] = self.menu - LabelHelp( self.repository.fileNameHelp, gridPosition.master, self.name, self.label ) - - -class MenuRadio( BooleanSetting ): - """A class to display, read & write a boolean with associated menu radio button.""" - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - self.menuButtonDisplay.setToNameAddToDialog( self.name, gridPosition ) - self.addToSubmenu() - - def addToMenu( self, repositoryMenu ): - """Add this to the submenu set by MenuButtonDisplay, the repository menu is ignored""" - self.addToSubmenu() - - def addToMenuFrameable( self, repositoryMenu ): - """Add this to the frameable repository menu.""" - self.addToMenu( repositoryMenu ) - - def addToSubmenu(self): - """Add this to the submenu.""" - self.activate = False - menu = self.menuButtonDisplay.menu - menu.add_radiobutton( label = self.name, command = self.clickRadio, value = self.name, variable = self.menuButtonDisplay.radioVar ) - self.menuLength = menu.index( Tkinter.END ) - if self.value: - self.menuButtonDisplay.radioVar.set( self.name ) - self.invoke() - self.activate = True - - def clickRadio(self): - """Workaround for Tkinter bug, invoke and set the value when clicked.""" - if not self.activate: - return - self.menuButtonDisplay.radioVar.set( self.name ) - if self.updateFunction is not None: - self.updateFunction() - - def getFromMenuButtonDisplay( self, menuButtonDisplay, name, repository, value ): - """Initialize.""" - self.getFromValueOnlyAddToRepository( name, repository, value ) - self.menuButtonDisplay = menuButtonDisplay - self.menuButtonDisplay.menuRadios.append(self) - return self - - def invoke(self): - """Workaround for Tkinter bug, invoke to set the value when changed.""" - self.menuButtonDisplay.menu.invoke( self.menuLength ) - - def setStateToValue(self): - """Set the checkbutton to the boolean.""" - try: - if self.value: - self.invoke() - except: - pass - - def setToDisplay(self): - """Set the boolean to the checkbutton.""" - if self.menuButtonDisplay.radioVar is not None: - self.value = ( self.menuButtonDisplay.radioVar.get() == self.name ) - - -class PluginFrame: - """A class to display the plugins in a frame.""" - def __init__(self): - """Initialize.""" - self.gridTable = {} - self.latentStringVar = LatentStringVar() - self.oldLatentString = '' - - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - gridPosition.increment() - self.gridPosition = gridPosition.getCopy() - self.gridPosition.master = gridPosition.master - self.createFrame( gridPosition ) - - def createFrame( self, gridPosition ): - """Create the frame.""" - gridVertical = GridVertical( 0, 0 ) - gridVertical.master = Tkinter.LabelFrame( gridPosition.master, borderwidth = 3, relief = 'raised') - gridVertical.master.grid( row = gridPosition.row, column = gridPosition.column, columnspan = 12, sticky = Tkinter.E + Tkinter.W + Tkinter.N + Tkinter.S ) - gridPosition.master.grid_rowconfigure( gridPosition.row, weight = 1 ) - gridPosition.master.grid_columnconfigure( gridPosition.column + 11, weight = 1 ) - if self.latentStringVar.getString() == '': - self.defaultRadioButton.setSelect() - self.gridTable[ self.latentStringVar.getString() ] = gridVertical - path = os.path.join( self.directoryPath, self.latentStringVar.getString() ) - pluginModule = archive.getModuleWithPath(path) - if pluginModule is None: - print('this should never happen, pluginModule in addToDialog in PluginFrame in settings is None') - print(path) - return - gridVertical.repository = getReadRepository( pluginModule.getNewRepository() ) - gridVertical.frameGridVertical = GridVertical( 0, 0 ) - gridVertical.frameGridVertical.setExecutablesRepository( gridVertical.repository ) - executeTitle = gridVertical.repository.executeTitle - if executeTitle is not None: - executeButton = Tkinter.Button( gridVertical.master, activebackground = 'black', activeforeground = 'blue', text = executeTitle, command = gridVertical.frameGridVertical.execute ) - executeButton.grid( row = gridVertical.row, column = gridVertical.column, sticky = Tkinter.W ) - gridVertical.column += 1 - self.helpButton = Tkinter.Button( gridVertical.master, activebackground = 'black', activeforeground = 'white', text = "?", command = HelpPageRepository( gridVertical.repository ).openPage ) - self.helpButton.grid( row = gridVertical.row, column = gridVertical.column, sticky = Tkinter.W ) - addEmptyRow( gridVertical ) - gridVertical.increment() - from fabmetheus_utilities.hidden_scrollbar import HiddenScrollbar - gridVertical.xScrollbar = HiddenScrollbar( gridVertical.master, orient = Tkinter.HORIZONTAL ) - gridVertical.xScrollbar.grid( row = gridVertical.row + 1, column = gridVertical.column, columnspan = 11, sticky = Tkinter.E + Tkinter.W ) - gridVertical.yScrollbar = HiddenScrollbar( gridVertical.master ) - gridVertical.yScrollbar.grid( row = gridVertical.row, column = gridVertical.column + 12, sticky = Tkinter.N + Tkinter.S ) - canvasHeight = min( 900, gridPosition.master.winfo_screenheight() - 540 ) - 6 - int( gridVertical.xScrollbar['width'] ) - canvasWidth = min( 650, gridPosition.master.winfo_screenwidth() - 100 ) - 6 - int( gridVertical.yScrollbar['width'] ) - gridVertical.canvas = Tkinter.Canvas( gridVertical.master, height = canvasHeight, highlightthickness = 0, width = canvasWidth ) - gridVertical.frameGridVertical.master = Tkinter.Frame( gridVertical.canvas ) - for setting in gridVertical.repository.displayEntities: - setting.addToDialog( gridVertical.frameGridVertical ) - addEmptyRow( gridVertical.frameGridVertical ) - gridVertical.frameGridVertical.master.update_idletasks() - gridVertical.xScrollbar.config( command = gridVertical.canvas.xview ) - gridVertical.canvas['xscrollcommand'] = gridVertical.xScrollbar.set - gridVertical.yScrollbar.config( command = gridVertical.canvas.yview ) - gridVertical.canvas['yscrollcommand'] = gridVertical.yScrollbar.set - gridVertical.canvas.create_window( 0, 0, anchor = Tkinter.NW, window = gridVertical.frameGridVertical.master ) - gridVertical.canvas['scrollregion'] = gridVertical.frameGridVertical.master.grid_bbox() - gridVertical.canvas.grid( row = gridVertical.row, column = gridVertical.column, columnspan = 11, sticky = Tkinter.E + Tkinter.W + Tkinter.N + Tkinter.S ) - gridVertical.master.grid_rowconfigure( gridVertical.row, weight = 1 ) - gridVertical.master.grid_columnconfigure( gridVertical.column + 11, weight = 1 ) - gridVertical.frameGridVertical.master.lift() - self.oldLatentString = self.latentStringVar.getString() - - def focusSetMaster( self, gridPosition ): - """Set the focus to the plugin master.""" - gridPosition.frameGridVertical.master.focus_set() - - def getFromPath( self, defaultRadioButton, directoryPath, repository ): - """Initialize.""" - self.defaultRadioButton = defaultRadioButton - self.directoryPath = directoryPath - self.name = 'PluginFrame' - self.repository = repository - repository.displayEntities.append(self) - repository.preferences.append(self) - return self - - def setStateToValue(self): - """Set the state of all the plugins to the value.""" - for gridTableValue in self.gridTable.values(): - cancelRepository( gridTableValue.repository ) - - def setToDisplay(self): - """Set the plugins to the display.""" - pass - - def update(self): - """Update the frame.""" - if len(self.gridTable) < 1: - return - if self.oldLatentString == self.latentStringVar.getString(): - return - self.oldLatentString = self.latentStringVar.getString() - self.repository.preferences.remove(self) - for setting in self.repository.preferences: - setting.setToDisplay() - writeSettingsPrintMessage(self.repository) - self.repository.preferences.append(self) - if self.latentStringVar.getString() in self.gridTable: - gridPosition = self.gridTable[self.latentStringVar.getString()] - gridPosition.master.lift() - self.focusSetMaster(gridPosition) - return - self.createFrame(self.gridPosition) - - def updateSaveListeners(self): - """Update save listeners if any.""" - gridTableKeys = self.gridTable.keys() - gridTableKeys.sort() - for gridTableKey in gridTableKeys: - saveRepository( self.gridTable[ gridTableKey ].repository ) - - def writeToRepositoryWriter( self, repositoryWriter ): - """Write tab separated name and value to the repository writer.""" - pass - - -class PluginGroupFrame( PluginFrame ): - """A class to display the plugin groups in a frame.""" - def createFrame( self, gridPosition ): - """Create the frame.""" - gridVertical = GridVertical( 0, 0 ) - gridVertical.master = Tkinter.LabelFrame( gridPosition.master, borderwidth = 3, relief = 'raised') - gridVertical.master.grid( row = gridPosition.row, column = gridPosition.column, columnspan = 11, sticky = Tkinter.E + Tkinter.W + Tkinter.N + Tkinter.S ) - gridPosition.master.grid_rowconfigure( gridPosition.row, weight = 1 ) - gridPosition.master.grid_columnconfigure( gridPosition.column + 10, weight = 1 ) - if self.latentStringVar.getString() == '': - self.defaultRadioButton.setSelect() - self.gridTable[ self.latentStringVar.getString() ] = gridVertical - path = os.path.join( self.directoryPath, self.latentStringVar.getString() ) - pluginModule = archive.getModuleWithPath(path) - if pluginModule is None: - print('this should never happen, pluginModule in addToDialog in PluginFrame in settings is None') - print(path) - return - gridVertical.repository = getReadRepository( pluginModule.getNewRepository() ) - gridVertical.setExecutablesRepository( gridVertical.repository ) - executeTitle = gridVertical.repository.executeTitle - if executeTitle is not None: - executeButton = Tkinter.Button( gridVertical.master, activebackground = 'black', activeforeground = 'blue', text = executeTitle, command = gridVertical.execute ) - executeButton.grid( row = gridVertical.row, column = gridVertical.column, sticky = Tkinter.W ) - gridVertical.column += 1 - self.helpButton = Tkinter.Button( gridVertical.master, activebackground = 'black', activeforeground = 'white', text = "?", command = HelpPageRepository( gridVertical.repository ).openPage ) - self.helpButton.grid( row = gridVertical.row, column = gridVertical.column, sticky = Tkinter.W ) - addEmptyRow( gridVertical ) - gridVertical.increment() - for setting in gridVertical.repository.displayEntities: - setting.addToDialog( gridVertical ) - gridVertical.master.update_idletasks() - gridVertical.master.lift() - self.oldLatentString = self.latentStringVar.getString() - - def focusSetMaster( self, gridPosition ): - """Set the focus to the plugin master.""" - gridPosition.master.focus_set() - - -class Radio( BooleanSetting ): - """A class to display, read & write a boolean with associated radio button.""" - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - gridPosition.increment() - self.createRadioButton( gridPosition ) - self.radiobutton.grid( row = gridPosition.row, column = 0, columnspan = 3, sticky = Tkinter.W ) - self.setStateToValue() - - def clickRadio(self): - """Workaround for Tkinter bug, set the value.""" - self.latentStringVar.setString( self.radiobutton['value'] ) - if self.updateFunction is not None: - self.updateFunction() - - def createRadioButton( self, gridPosition ): - """Create the radio button.""" - self.radiobutton = Tkinter.Radiobutton( gridPosition.master, command = self.clickRadio, text = self.name, value = self.name, variable = self.latentStringVar.getVar() ) - LabelHelp( self.repository.fileNameHelp, gridPosition.master, self.name, self.radiobutton ) - - def getFromRadio( self, latentStringVar, name, repository, value ): - """Initialize.""" - self.getFromValueOnly( name, repository, value ) - self.latentStringVar = latentStringVar - repository.displayEntities.append(self) - repository.preferences.append(self) -#when addToMenu is added to this entity, the line below should be uncommented -# repository.menuEntities.append(self) - return self - - def setToDisplay(self): - """Set the boolean to the checkbutton.""" - self.value = ( self.latentStringVar.getString() == self.radiobutton['value'] ) - - def setSelect(self): - """Set the int var and select the radio button.""" - oldLatentStringValue = self.latentStringVar.getString() - self.latentStringVar.setString( self.radiobutton['value'] ) - self.radiobutton.select() - if oldLatentStringValue == '': - return False - return oldLatentStringValue != self.latentStringVar.getString() - - def setStateToValue(self): - """Set the checkbutton to the boolean.""" - if self.value: - if self.setSelect(): - if self.updateFunction is not None: - self.updateFunction() - - -class RadioCapitalized( Radio ): - """A class to display, read & write a boolean with associated radio button.""" - def createRadioButton( self, gridPosition ): - """Create the radio button.""" - capitalizedName = getEachWordCapitalized( self.name ) - self.radiobutton = Tkinter.Radiobutton( gridPosition.master, command = self.clickRadio, text = capitalizedName, value = self.name, variable = self.latentStringVar.getVar() ) - - -class RadioCapitalizedButton( Radio ): - """A class to display, read & write a boolean with associated radio button.""" - def createRadioButton( self, gridPosition ): - """Create the radio button.""" - capitalizedName = getEachWordCapitalized( self.name ) - self.radiobutton = Tkinter.Radiobutton( gridPosition.master, command = self.clickRadio, text = capitalizedName, value = self.name, variable = self.latentStringVar.getVar() ) - self.displayButton = Tkinter.Button( gridPosition.master, activebackground = 'black', activeforeground = 'white', text = capitalizedName, command = self.displayDialog ) - self.displayButton.grid( row = gridPosition.row, column = 3, columnspan = 2 ) - - def displayDialog(self): - """Display function.""" - ToolDialog().getFromPath( self.path ).display() - self.setSelect() - - def getFromPath( self, latentStringVar, name, path, repository, value ): - """Initialize.""" - self.getFromRadio( latentStringVar, name, repository, value ) - self.path = path - return self - - -class RadioPlugin( RadioCapitalized ): - """A class to display, read & write a boolean with associated radio button.""" - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - self.createRadioButton( gridPosition ) - self.radiobutton['activebackground'] = 'black' - self.radiobutton['activeforeground'] = 'white' - self.radiobutton['selectcolor'] = 'white' - self.radiobutton['borderwidth'] = 3 - self.radiobutton['indicatoron'] = 0 - setButtonFontWeightString( self.radiobutton, self.important ) - self.incrementGridPosition( gridPosition ) - self.setStateToValue() - - def getFromRadio( self, important, latentStringVar, name, repository, value ): - """Initialize.""" - self.important = important - return RadioCapitalized.getFromRadio( self, latentStringVar, name, repository, value ) - - def incrementGridPosition( self, gridPosition ): - """Increment the grid position.""" - gridPosition.incrementGivenNumberOfColumns( 10 ) - self.radiobutton.grid( row = gridPosition.row, column = gridPosition.column, sticky = Tkinter.W ) - - -class TextSetting( StringSetting ): - """A class to display, read & write a text.""" - def __init__(self): - """Set the update function to none.""" - self.tokenConversions = [ - TokenConversion(), - TokenConversion('carriageReturn', '\r'), - TokenConversion('doubleQuote', '"'), - TokenConversion('newline', '\n'), - TokenConversion('semicolon', ';'), - TokenConversion('singleQuote', "'" ), - TokenConversion('tab', '\t') ] - self.updateFunction = None - - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - gridPosition.increment() - self.label = Tkinter.Label( gridPosition.master, text = self.name ) - self.label.grid( row = gridPosition.row, column = 0, columnspan = 3, sticky = Tkinter.W ) - gridPosition.increment() - self.entry = Tkinter.Text( gridPosition.master ) - self.setStateToValue() - self.entry.grid( row = gridPosition.row, column = 0, columnspan = 5, sticky = Tkinter.W ) - LabelHelp( self.repository.fileNameHelp, gridPosition.master, self.name, self.label ) - - def getFromValue( self, name, repository, value ): - """Initialize.""" - self.getFromValueOnly( name, repository, value ) - repository.displayEntities.append(self) - repository.preferences.append(self) - return self - - def setToDisplay(self): - """Set the string to the entry field.""" - valueString = self.entry.get( 1.0, Tkinter.END ) - self.setValueToString( valueString ) - - def setStateToValue(self): - """Set the entry to the value.""" - try: - self.entry.delete( 1.0, Tkinter.END ) - self.entry.insert( Tkinter.INSERT, self.value ) - except: - pass - - def setValueToSplitLine( self, lineIndex, lines, splitLine ): - """Set the value to the second word of a split line.""" - replacedValue = splitLine[1] - for tokenConversion in reversed( self.tokenConversions ): - replacedValue = tokenConversion.getTokenizedString( replacedValue ) - self.setValueToString( replacedValue ) - - def writeToRepositoryWriter( self, repositoryWriter ): - """Write tab separated name and value to the repository writer.""" - replacedValue = self.value - for tokenConversion in self.tokenConversions: - replacedValue = tokenConversion.getNamedString( replacedValue ) - repositoryWriter.write('%s%s%s\n' % ( self.name, globalSpreadsheetSeparator, replacedValue ) ) - - -class TokenConversion: - """A class to convert tokens in a string.""" - def __init__( self, name = 'replaceToken', token = '___replaced___'): - """Set the name and token.""" - self.replacedName = '___replaced___' + name - self.token = token - - def getNamedString( self, text ): - """Get a string with the tokens changed to names.""" - return text.replace( self.token, self.replacedName ) - - def getTokenizedString( self, text ): - """Get a string with the names changed to tokens.""" - return text.replace( self.replacedName, self.token ) - - -class ToolDialog: - """A class to display the tool repository dialog.""" - def addPluginToMenu( self, menu, path ): - """Add the display command to the menu.""" - name = os.path.basename(path) - self.path = path - menu.add_command( label = getEachWordCapitalized( name ) + '...', command = self.display ) - - def display(self): - """Display the tool repository dialog.""" - global globalRepositoryDialogListTable - for repositoryDialog in globalRepositoryDialogListTable: - if getPathInFabmetheusFromFileNameHelp( repositoryDialog.repository.fileNameHelp ) == self.path: - liftRepositoryDialogs( globalRepositoryDialogListTable[ repositoryDialog ] ) - return - self.repositoryDialog = getDisplayedDialogFromPath( self.path ) - - def getFromPath( self, path ): - """Initialize and return display function.""" - self.path = path - return self - - -class WindowPosition( StringSetting ): - """A class to display, read & write a window position.""" - def addToDialog( self, gridPosition ): - """Set the root to later get the geometry.""" - self.root = gridPosition.master - self.setToDisplay() - - def getFromValue( self, repository, value ): - """Initialize.""" - self.getFromValueOnly('WindowPosition', repository, value ) - repository.displayEntities.append(self) - repository.preferences.append(self) - return self - - def setToDisplay(self): - """Set the string to the window position.""" - try: - geometryString = self.root.geometry() - except: - return - if geometryString == '1x1+0+0': - return - firstPlusIndexPlusOne = geometryString.find('+') + 1 - self.value = geometryString[ firstPlusIndexPlusOne : ] - - def setWindowPosition(self): - """Set the window position.""" - movedGeometryString = '%sx%s+%s' % ( self.root.winfo_reqwidth(), self.root.winfo_reqheight(), self.value ) - self.root.geometry( movedGeometryString ) - - -class RepositoryDialog: - def __init__( self, repository, root ): - """Add entities to the dialog.""" - self.isFirst = ( len( globalRepositoryDialogListTable.keys() ) == 0 ) - self.closeListener = CloseListener(self) - self.repository = repository - self.gridPosition = GridVertical( 0, - 1 ) - self.gridPosition.setExecutablesRepository(repository) - self.gridPosition.master = root - self.root = root - self.openDialogListeners = [] - repository.repositoryDialog = self - root.withdraw() - title = repository.title - if repository.fileNameInput is not None: - title = os.path.basename( repository.fileNameInput.value ) + ' - ' + title - root.title( title ) - fileHelpMenuBar = FileHelpMenuBar( root ) - fileHelpMenuBar.completeMenu( self.close, repository, self.save, self ) - for setting in repository.displayEntities: - setting.addToDialog( self.gridPosition ) - if self.gridPosition.row < 20: - addEmptyRow( self.gridPosition ) - self.addButtons( repository, root ) - root.update_idletasks() - self.setWindowPositionDeiconify() - root.deiconify() - for openDialogListener in self.openDialogListeners: - openDialogListener.openDialog() - - def __repr__(self): - """Get the string representation of this RepositoryDialog.""" - return self.repository.title - - def addButtons( self, repository, root ): - """Add buttons to the dialog.""" - columnIndex = 0 - self.gridPosition.increment() - saveCommand = self.save - saveText = 'Save' - if self.isFirst: - saveCommand = saveAll - saveText = 'Save All' - if repository.executeTitle is not None: - executeButton = Tkinter.Button( root, activebackground = 'black', activeforeground = 'blue', text = repository.executeTitle, command = self.gridPosition.execute ) - executeButton.grid( row = self.gridPosition.row, column = columnIndex, columnspan = 2, sticky = Tkinter.W ) - columnIndex += 2 - self.helpButton = Tkinter.Button( root, activebackground = 'black', activeforeground = 'white', text = "?", command = HelpPageRepository(self.repository).openPage ) - self.helpButton.grid( row = self.gridPosition.row, column = columnIndex, sticky = Tkinter.W ) - self.closeListener.listenToWidget( self.helpButton ) - columnIndex += 6 - cancelButton = Tkinter.Button( root, activebackground = 'black', activeforeground = 'orange', command = self.cancel, fg = 'orange', text = 'Cancel') - cancelButton.grid( row = self.gridPosition.row, column = columnIndex ) - columnIndex += 1 - self.saveButton = Tkinter.Button( root, activebackground = 'black', activeforeground = 'darkgreen', command = saveCommand, fg = 'darkgreen', text = saveText ) - self.saveButton.grid( row = self.gridPosition.row, column = columnIndex ) - - def cancel(self, event=None): - """Set all entities to their saved state.""" - cancelRepository(self.repository) - - def close(self, event=None): - """The dialog was closed.""" - try: - self.root.destroy() - except: - pass - - def save(self, event=None): - """Set the entities to the dialog then write them.""" - saveRepository(self.repository) - - def setWindowPositionDeiconify(self): - """Set the window position if that setting exists.""" - for setting in self.repository.preferences: - if setting.name == 'WindowPosition': - setting.setWindowPosition() - return - - -def addPreferenceOverride(moduleName, prefName, valueName): - return None \ No newline at end of file diff --git a/skeinforge/fabmetheus_utilities/svg_reader.py b/skeinforge/fabmetheus_utilities/svg_reader.py deleted file mode 100644 index 2743348..0000000 --- a/skeinforge/fabmetheus_utilities/svg_reader.py +++ /dev/null @@ -1,959 +0,0 @@ -""" -Svg reader. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.xml_simple_reader import XMLSimpleReader -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -from fabmetheus_utilities import svg_writer -import math -import os -import sys -import traceback - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalNumberOfCornerPoints = 11 -globalNumberOfBezierPoints = globalNumberOfCornerPoints + globalNumberOfCornerPoints -globalNumberOfCirclePoints = 4 * globalNumberOfCornerPoints - - -def addFunctionsToDictionary( dictionary, functions, prefix ): - """Add functions to dictionary.""" - for function in functions: - dictionary[ function.__name__[ len( prefix ) : ] ] = function - -def getArcComplexes(begin, end, largeArcFlag, radius, sweepFlag, xAxisRotation): - """Get the arc complexes, procedure at http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes""" - if begin == end: - print('Warning, begin equals end in getArcComplexes in svgReader') - print(begin) - print(end) - return [] - if radius.imag < 0.0: - print('Warning, radius.imag is less than zero in getArcComplexes in svgReader') - print(radius) - radius = complex(radius.real, abs(radius.imag)) - if radius.real < 0.0: - print('Warning, radius.real is less than zero in getArcComplexes in svgReader') - print(radius) - radius = complex(abs(radius.real), radius.imag) - if radius.imag <= 0.0: - print('Warning, radius.imag is too small for getArcComplexes in svgReader') - print(radius) - return [end] - if radius.real <= 0.0: - print('Warning, radius.real is too small for getArcComplexes in svgReader') - print(radius) - return [end] - xAxisRotationComplex = euclidean.getWiddershinsUnitPolar(xAxisRotation) - reverseXAxisRotationComplex = complex(xAxisRotationComplex.real, -xAxisRotationComplex.imag) - beginRotated = begin * reverseXAxisRotationComplex - endRotated = end * reverseXAxisRotationComplex - beginTransformed = complex(beginRotated.real / radius.real, beginRotated.imag / radius.imag) - endTransformed = complex(endRotated.real / radius.real, endRotated.imag / radius.imag) - midpointTransformed = 0.5 * (beginTransformed + endTransformed) - midMinusBeginTransformed = midpointTransformed - beginTransformed - midMinusBeginTransformedLength = abs(midMinusBeginTransformed) - if midMinusBeginTransformedLength > 1.0: - print('Warning, midMinusBeginTransformedLength is too large for getArcComplexes in svgReader') - print(begin) - print(end) - print(beginTransformed) - print(endTransformed) - print(midpointTransformed) - print(midMinusBeginTransformed) - print('The ellipse will be scaled to fit.') - radius *= midMinusBeginTransformedLength - scale = 1.0 / midMinusBeginTransformedLength - beginTransformed *= scale - endTransformed *= scale - midpointTransformed *= scale - midMinusBeginTransformed *= scale - midMinusBeginTransformedLength = 1.0 - midWiddershinsTransformed = complex(-midMinusBeginTransformed.imag, midMinusBeginTransformed.real) - midWiddershinsLengthSquared = 1.0 - midMinusBeginTransformedLength * midMinusBeginTransformedLength - if midWiddershinsLengthSquared < 0.0: - midWiddershinsLengthSquared = 0.0 - midWiddershinsLength = math.sqrt(midWiddershinsLengthSquared) - midWiddershinsTransformed *= midWiddershinsLength / abs(midWiddershinsTransformed) - centerTransformed = midpointTransformed - if largeArcFlag == sweepFlag: - centerTransformed -= midWiddershinsTransformed - else: - centerTransformed += midWiddershinsTransformed - beginMinusCenterTransformed = beginTransformed - centerTransformed - beginMinusCenterTransformedLength = abs(beginMinusCenterTransformed) - if beginMinusCenterTransformedLength <= 0.0: - return end - beginAngle = math.atan2(beginMinusCenterTransformed.imag, beginMinusCenterTransformed.real) - endMinusCenterTransformed = endTransformed - centerTransformed - angleDifference = euclidean.getAngleDifferenceByComplex(endMinusCenterTransformed, beginMinusCenterTransformed) - if sweepFlag: - if angleDifference < 0.0: - angleDifference += 2.0 * math.pi - else: - if angleDifference > 0.0: - angleDifference -= 2.0 * math.pi - global globalSideAngle - sides = int(math.ceil(abs(angleDifference) / globalSideAngle)) - sideAngle = angleDifference / float(sides) - arcComplexes = [] - center = complex(centerTransformed.real * radius.real, centerTransformed.imag * radius.imag) * xAxisRotationComplex - for side in xrange(1, sides): - unitPolar = euclidean.getWiddershinsUnitPolar(beginAngle + float(side) * sideAngle) - circumferential = complex(unitPolar.real * radius.real, unitPolar.imag * radius.imag) * beginMinusCenterTransformedLength - point = center + circumferential * xAxisRotationComplex - arcComplexes.append(point) - arcComplexes.append(end) - return arcComplexes - -def getChainMatrixSVG(matrixSVG, xmlElement): - """Get chain matrixSVG by svgElement.""" - matrixSVG = matrixSVG.getOtherTimesSelf(getMatrixSVG(xmlElement).tricomplex) - if xmlElement.parent is not None: - matrixSVG = getChainMatrixSVG(matrixSVG, xmlElement.parent) - return matrixSVG - -def getChainMatrixSVGIfNecessary(xmlElement, yAxisPointingUpward): - """Get chain matrixSVG by svgElement and yAxisPointingUpward.""" - matrixSVG = MatrixSVG() - if yAxisPointingUpward: - return matrixSVG - return getChainMatrixSVG(matrixSVG, xmlElement) - -def getCubicPoint( along, begin, controlPoints, end ): - """Get the cubic point.""" - segmentBegin = getQuadraticPoint( along, begin, controlPoints[0], controlPoints[1] ) - segmentEnd = getQuadraticPoint( along, controlPoints[0], controlPoints[1], end ) - return ( 1.0 - along ) * segmentBegin + along * segmentEnd - -def getCubicPoints( begin, controlPoints, end, numberOfBezierPoints=globalNumberOfBezierPoints): - """Get the cubic points.""" - bezierPortion = 1.0 / float(numberOfBezierPoints) - cubicPoints = [] - for bezierIndex in xrange( 1, numberOfBezierPoints + 1 ): - cubicPoints.append(getCubicPoint(bezierPortion * bezierIndex, begin, controlPoints, end)) - return cubicPoints - -def getFontReader(fontFamily): - """Get the font reader for the fontFamily.""" - fontLower = fontFamily.lower().replace(' ', '_') - global globalFontReaderDictionary - if fontLower in globalFontReaderDictionary: - return globalFontReaderDictionary[fontLower] - global globalFontFileNames - if globalFontFileNames is None: - globalFontFileNames = archive.getFileNamesByFilePaths(archive.getFilePathsByDirectory(getFontsDirectoryPath())) - if fontLower not in globalFontFileNames: - print('Warning, the %s font was not found in the fonts folder, so Gentium Basic Regular will be substituted.' % fontFamily) - fontLower = 'gentium_basic_regular' - fontReader = FontReader(fontLower) - globalFontReaderDictionary[fontLower] = fontReader - return fontReader - -def getFontsDirectoryPath(): - """Get the fonts directory path.""" - return archive.getFabmetheusUtilitiesPath('fonts') - -def getLabelString(dictionary): - """Get the label string for the dictionary.""" - for key in dictionary: - labelIndex = key.find('label') - if labelIndex >= 0: - return dictionary[key] - return '' - -def getMatrixSVG(xmlElement): - """Get matrixSVG by svgElement.""" - matrixSVG = MatrixSVG() - if 'transform' not in xmlElement.attributeDictionary: - return matrixSVG - transformWords = [] - for transformWord in xmlElement.attributeDictionary['transform'].replace(')', '(').split('('): - transformWordStrip = transformWord.strip() - if transformWordStrip != '': # workaround for split(character) bug which leaves an extra empty element - transformWords.append(transformWordStrip) - global globalGetTricomplexDictionary - getTricomplexDictionaryKeys = globalGetTricomplexDictionary.keys() - for transformWordIndex, transformWord in enumerate(transformWords): - if transformWord in getTricomplexDictionaryKeys: - transformString = transformWords[transformWordIndex + 1].replace(',', ' ') - matrixSVG = matrixSVG.getSelfTimesOther(globalGetTricomplexDictionary[ transformWord ](transformString.split())) - return matrixSVG - -def getQuadraticPoint( along, begin, controlPoint, end ): - """Get the quadratic point.""" - oneMinusAlong = 1.0 - along - segmentBegin = oneMinusAlong * begin + along * controlPoint - segmentEnd = oneMinusAlong * controlPoint + along * end - return oneMinusAlong * segmentBegin + along * segmentEnd - -def getQuadraticPoints(begin, controlPoint, end, numberOfBezierPoints=globalNumberOfBezierPoints): - """Get the quadratic points.""" - bezierPortion = 1.0 / float(numberOfBezierPoints) - quadraticPoints = [] - for bezierIndex in xrange(1, numberOfBezierPoints + 1): - quadraticPoints.append(getQuadraticPoint(bezierPortion * bezierIndex, begin, controlPoint, end)) - return quadraticPoints - -def getRightStripAlphabetPercent(word): - """Get word with alphabet characters and the percent sign stripped from the right.""" - word = word.strip() - for characterIndex in xrange(len(word) - 1, -1, -1): - character = word[characterIndex] - if not character.isalpha() and not character == '%': - return float(word[: characterIndex + 1]) - return None - -def getRightStripMinusSplit(lineString): - """Get string with spaces after the minus sign stripped.""" - oldLineStringLength = -1 - while oldLineStringLength < len(lineString): - oldLineStringLength = len(lineString) - lineString = lineString.replace('- ', '-') - return lineString.split() - -def getStrokeRadius(xmlElement): - """Get the stroke radius.""" - return 0.5 * getRightStripAlphabetPercent(getStyleValue('1.0', 'stroke-width', xmlElement)) - -def getStyleValue(defaultValue, key, xmlElement): - """Get the stroke value string.""" - if 'style' in xmlElement.attributeDictionary: - line = xmlElement.attributeDictionary['style'] - strokeIndex = line.find(key) - if strokeIndex > -1: - words = line[strokeIndex :].replace(':', ' ').replace(';', ' ').split() - if len(words) > 1: - return words[1] - if key in xmlElement.attributeDictionary: - return xmlElement.attributeDictionary[key] - if xmlElement.parent is None: - return defaultValue - return getStyleValue(defaultValue, key, xmlElement.parent) - -def getTextComplexLoops(fontFamily, fontSize, text, yAxisPointingUpward=True): - """Get text as complex loops.""" - textComplexLoops = [] - fontReader = getFontReader(fontFamily) - horizontalAdvanceX = 0.0 - for character in text: - glyph = fontReader.getGlyph(character, yAxisPointingUpward) - textComplexLoops += glyph.getSizedAdvancedLoops(fontSize, horizontalAdvanceX, yAxisPointingUpward) - horizontalAdvanceX += glyph.horizontalAdvanceX - return textComplexLoops - -def getTransformedFillOutline(loop, xmlElement, yAxisPointingUpward): - """Get the loops if fill is on, otherwise get the outlines.""" - fillOutlineLoops = None - if getStyleValue('none', 'fill', xmlElement).lower() == 'none': - fillOutlineLoops = intercircle.getAroundsFromLoop(loop, getStrokeRadius(xmlElement)) - else: - fillOutlineLoops = [loop] - return getChainMatrixSVGIfNecessary(xmlElement, yAxisPointingUpward).getTransformedPaths(fillOutlineLoops) - -def getTransformedOutlineByPath(path, xmlElement, yAxisPointingUpward): - """Get the outline from the path.""" - aroundsFromPath = intercircle.getAroundsFromPath(path, getStrokeRadius(xmlElement)) - return getChainMatrixSVGIfNecessary(xmlElement, yAxisPointingUpward).getTransformedPaths(aroundsFromPath) - -def getTransformedOutlineByPaths(paths, xmlElement, yAxisPointingUpward): - """Get the outline from the paths.""" - aroundsFromPaths = intercircle.getAroundsFromPaths(paths, getStrokeRadius(xmlElement)) - return getChainMatrixSVGIfNecessary(xmlElement, yAxisPointingUpward).getTransformedPaths(aroundsFromPaths) - -def getTricomplexmatrix(transformWords): - """Get matrixSVG by transformWords.""" - tricomplex = [euclidean.getComplexByWords(transformWords)] - tricomplex.append(euclidean.getComplexByWords(transformWords, 2)) - tricomplex.append(euclidean.getComplexByWords(transformWords, 4)) - return tricomplex - -def getTricomplexrotate(transformWords): - """Get matrixSVG by transformWords.""" - rotate = euclidean.getWiddershinsUnitPolar(math.radians(float(transformWords[0]))) - return [rotate, complex(-rotate.imag,rotate.real), complex()] - -def getTricomplexscale(transformWords): - """Get matrixSVG by transformWords.""" - scale = euclidean.getComplexByWords(transformWords) - return [complex(scale.real,0.0), complex(0.0,scale.imag), complex()] - -def getTricomplexskewX(transformWords): - """Get matrixSVG by transformWords.""" - skewX = math.tan(math.radians(float(transformWords[0]))) - return [complex(1.0, 0.0), complex(skewX, 1.0), complex()] - -def getTricomplexskewY(transformWords): - """Get matrixSVG by transformWords.""" - skewY = math.tan(math.radians(float(transformWords[0]))) - return [complex(1.0, skewY), complex(0.0, 1.0), complex()] - -def getTricomplexTimesColumn(firstTricomplex, otherColumn): - """Get this matrix multiplied by the otherColumn.""" - dotProductX = firstTricomplex[0].real * otherColumn.real + firstTricomplex[1].real * otherColumn.imag - dotProductY = firstTricomplex[0].imag * otherColumn.real + firstTricomplex[1].imag * otherColumn.imag - return complex(dotProductX, dotProductY) - -def getTricomplexTimesOther(firstTricomplex, otherTricomplex): - """Get the first tricomplex multiplied by the other tricomplex.""" - #A down, B right from http://en.wikipedia.org/wiki/Matrix_multiplication - tricomplexTimesOther = [getTricomplexTimesColumn(firstTricomplex, otherTricomplex[0])] - tricomplexTimesOther.append(getTricomplexTimesColumn(firstTricomplex, otherTricomplex[1])) - tricomplexTimesOther.append(getTricomplexTimesColumn(firstTricomplex, otherTricomplex[2]) + firstTricomplex[2]) - return tricomplexTimesOther - -def getTricomplextranslate(transformWords): - """Get matrixSVG by transformWords.""" - translate = euclidean.getComplexByWords(transformWords) - return [complex(1.0, 0.0), complex(0.0, 1.0), translate] - -def processSVGElementcircle( svgReader, xmlElement ): - """Process xmlElement by svgReader.""" - attributeDictionary = xmlElement.attributeDictionary - center = euclidean.getComplexDefaultByDictionaryKeys( complex(), attributeDictionary, 'cx', 'cy') - radius = euclidean.getFloatDefaultByDictionary( 0.0, attributeDictionary, 'r') - if radius == 0.0: - print('Warning, in processSVGElementcircle in svgReader radius is zero in:') - print(attributeDictionary) - return - global globalNumberOfCirclePoints - global globalSideAngle - loop = [] - rotatedLoopLayer = svgReader.getRotatedLoopLayer() - for side in xrange( globalNumberOfCirclePoints ): - unitPolar = euclidean.getWiddershinsUnitPolar( float(side) * globalSideAngle ) - loop.append( center + radius * unitPolar ) - rotatedLoopLayer.loops += getTransformedFillOutline(loop, xmlElement, svgReader.yAxisPointingUpward) - -def processSVGElementellipse( svgReader, xmlElement ): - """Process xmlElement by svgReader.""" - attributeDictionary = xmlElement.attributeDictionary - center = euclidean.getComplexDefaultByDictionaryKeys( complex(), attributeDictionary, 'cx', 'cy') - radius = euclidean.getComplexDefaultByDictionaryKeys( complex(), attributeDictionary, 'rx', 'ry') - if radius.real == 0.0 or radius.imag == 0.0: - print('Warning, in processSVGElementellipse in svgReader radius is zero in:') - print(attributeDictionary) - return - global globalNumberOfCirclePoints - global globalSideAngle - loop = [] - rotatedLoopLayer = svgReader.getRotatedLoopLayer() - for side in xrange( globalNumberOfCirclePoints ): - unitPolar = euclidean.getWiddershinsUnitPolar( float(side) * globalSideAngle ) - loop.append( center + complex( unitPolar.real * radius.real, unitPolar.imag * radius.imag ) ) - rotatedLoopLayer.loops += getTransformedFillOutline(loop, xmlElement, svgReader.yAxisPointingUpward) - -def processSVGElementg(svgReader, xmlElement): - """Process xmlElement by svgReader.""" - if 'id' not in xmlElement.attributeDictionary: - return - idString = xmlElement.attributeDictionary['id'] - if 'beginningOfControlSection' in xmlElement.attributeDictionary: - if xmlElement.attributeDictionary['beginningOfControlSection'].lower()[: 1] == 't': - svgReader.stopProcessing = True - return - idStringLower = idString.lower() - zIndex = idStringLower.find('z:') - if zIndex < 0: - idStringLower = getLabelString(xmlElement.attributeDictionary) - zIndex = idStringLower.find('z:') - if zIndex < 0: - return - floatFromValue = euclidean.getFloatFromValue(idStringLower[zIndex + len('z:') :].strip()) - if floatFromValue is not None: - svgReader.z = floatFromValue - svgReader.bridgeRotation = euclidean.getComplexDefaultByDictionary( None, xmlElement.attributeDictionary, 'bridgeRotation') - -def processSVGElementline(svgReader, xmlElement): - """Process xmlElement by svgReader.""" - begin = euclidean.getComplexDefaultByDictionaryKeys(complex(), xmlElement.attributeDictionary, 'x1', 'y1') - end = euclidean.getComplexDefaultByDictionaryKeys(complex(), xmlElement.attributeDictionary, 'x2', 'y2') - rotatedLoopLayer = svgReader.getRotatedLoopLayer() - rotatedLoopLayer.loops += getTransformedOutlineByPath([begin, end], xmlElement, svgReader.yAxisPointingUpward) - -def processSVGElementpath( svgReader, xmlElement ): - """Process xmlElement by svgReader.""" - if 'd' not in xmlElement.attributeDictionary: - print('Warning, in processSVGElementpath in svgReader can not get a value for d in:') - print(xmlElement.attributeDictionary) - return - rotatedLoopLayer = svgReader.getRotatedLoopLayer() - PathReader(rotatedLoopLayer.loops, xmlElement, svgReader.yAxisPointingUpward) - -def processSVGElementpolygon( svgReader, xmlElement ): - """Process xmlElement by svgReader.""" - if 'points' not in xmlElement.attributeDictionary: - print('Warning, in processSVGElementpolygon in svgReader can not get a value for d in:') - print(xmlElement.attributeDictionary) - return - rotatedLoopLayer = svgReader.getRotatedLoopLayer() - words = getRightStripMinusSplit(xmlElement.attributeDictionary['points'].replace(',', ' ')) - loop = [] - for wordIndex in xrange( 0, len(words), 2 ): - loop.append(euclidean.getComplexByWords(words[wordIndex :])) - rotatedLoopLayer.loops += getTransformedFillOutline(loop, xmlElement, svgReader.yAxisPointingUpward) - -def processSVGElementpolyline(svgReader, xmlElement): - """Process xmlElement by svgReader.""" - if 'points' not in xmlElement.attributeDictionary: - print('Warning, in processSVGElementpolyline in svgReader can not get a value for d in:') - print(xmlElement.attributeDictionary) - return - rotatedLoopLayer = svgReader.getRotatedLoopLayer() - words = getRightStripMinusSplit(xmlElement.attributeDictionary['points'].replace(',', ' ')) - path = [] - for wordIndex in xrange(0, len(words), 2): - path.append(euclidean.getComplexByWords(words[wordIndex :])) - rotatedLoopLayer.loops += getTransformedOutlineByPath(path, xmlElement, svgReader.yAxisPointingUpward) - -def processSVGElementrect( svgReader, xmlElement ): - """Process xmlElement by svgReader.""" - attributeDictionary = xmlElement.attributeDictionary - height = euclidean.getFloatDefaultByDictionary( 0.0, attributeDictionary, 'height') - if height == 0.0: - print('Warning, in processSVGElementrect in svgReader height is zero in:') - print(attributeDictionary) - return - width = euclidean.getFloatDefaultByDictionary( 0.0, attributeDictionary, 'width') - if width == 0.0: - print('Warning, in processSVGElementrect in svgReader width is zero in:') - print(attributeDictionary) - return - center = euclidean.getComplexDefaultByDictionaryKeys(complex(), attributeDictionary, 'x', 'y') - inradius = 0.5 * complex( width, height ) - cornerRadius = euclidean.getComplexDefaultByDictionaryKeys( complex(), attributeDictionary, 'rx', 'ry') - rotatedLoopLayer = svgReader.getRotatedLoopLayer() - if cornerRadius.real == 0.0 and cornerRadius.imag == 0.0: - inradiusMinusX = complex( - inradius.real, inradius.imag ) - loop = [center + inradius, center + inradiusMinusX, center - inradius, center - inradiusMinusX] - rotatedLoopLayer.loops += getTransformedFillOutline(loop, xmlElement, svgReader.yAxisPointingUpward) - return - if cornerRadius.real == 0.0: - cornerRadius = complex( cornerRadius.imag, cornerRadius.imag ) - elif cornerRadius.imag == 0.0: - cornerRadius = complex( cornerRadius.real, cornerRadius.real ) - cornerRadius = complex( min( cornerRadius.real, inradius.real ), min( cornerRadius.imag, inradius.imag ) ) - ellipsePath = [ complex( cornerRadius.real, 0.0 ) ] - inradiusMinusCorner = inradius - cornerRadius - loop = [] - global globalNumberOfCornerPoints - global globalSideAngle - for side in xrange( 1, globalNumberOfCornerPoints ): - unitPolar = euclidean.getWiddershinsUnitPolar( float(side) * globalSideAngle ) - ellipsePath.append( complex( unitPolar.real * cornerRadius.real, unitPolar.imag * cornerRadius.imag ) ) - ellipsePath.append( complex( 0.0, cornerRadius.imag ) ) - cornerPoints = [] - for point in ellipsePath: - cornerPoints.append( point + inradiusMinusCorner ) - cornerPointsReversed = cornerPoints[: : -1] - for cornerPoint in cornerPoints: - loop.append( center + cornerPoint ) - for cornerPoint in cornerPointsReversed: - loop.append( center + complex( - cornerPoint.real, cornerPoint.imag ) ) - for cornerPoint in cornerPoints: - loop.append( center - cornerPoint ) - for cornerPoint in cornerPointsReversed: - loop.append( center + complex( cornerPoint.real, - cornerPoint.imag ) ) - loop = euclidean.getLoopWithoutCloseSequentialPoints( 0.0001 * abs(inradius), loop ) - rotatedLoopLayer.loops += getTransformedFillOutline(loop, xmlElement, svgReader.yAxisPointingUpward) - -def processSVGElementtext(svgReader, xmlElement): - """Process xmlElement by svgReader.""" - if svgReader.yAxisPointingUpward: - return - fontFamily = getStyleValue('Gentium Basic Regular', 'font-family', xmlElement) - fontSize = getRightStripAlphabetPercent(getStyleValue('12.0', 'font-size', xmlElement)) - matrixSVG = getChainMatrixSVGIfNecessary(xmlElement, svgReader.yAxisPointingUpward) - rotatedLoopLayer = svgReader.getRotatedLoopLayer() - translate = euclidean.getComplexDefaultByDictionaryKeys(complex(), xmlElement.attributeDictionary, 'x', 'y') - for textComplexLoop in getTextComplexLoops(fontFamily, fontSize, xmlElement.text, svgReader.yAxisPointingUpward): - translatedLoop = [] - for textComplexPoint in textComplexLoop: - translatedLoop.append(textComplexPoint + translate ) - rotatedLoopLayer.loops.append(matrixSVG.getTransformedPath(translatedLoop)) - - -class FontReader: - """Class to read a font in the fonts folder.""" - def __init__(self, fontFamily): - """Initialize.""" - self.fontFamily = fontFamily - self.glyphDictionary = {} - self.glyphXMLElementDictionary = {} - self.missingGlyph = None - fileName = os.path.join(getFontsDirectoryPath(), fontFamily + '.svg') - self.xmlParser = XMLSimpleReader(fileName, None, archive.getFileText(fileName)) - self.fontXMLElement = self.xmlParser.getRoot().getFirstChildWithClassName('defs').getFirstChildWithClassName('font') - self.fontFaceXMLElement = self.fontXMLElement.getFirstChildWithClassName('font-face') - self.unitsPerEM = float(self.fontFaceXMLElement.attributeDictionary['units-per-em']) - glyphXMLElements = self.fontXMLElement.getChildrenWithClassName('glyph') - for glyphXMLElement in glyphXMLElements: - self.glyphXMLElementDictionary[glyphXMLElement.attributeDictionary['unicode']] = glyphXMLElement - - def getGlyph(self, character, yAxisPointingUpward): - """Get the glyph for the character.""" - if character not in self.glyphXMLElementDictionary: - if self.missingGlyph is None: - missingGlyphXMLElement = self.fontXMLElement.getFirstChildWithClassName('missing-glyph') - self.missingGlyph = Glyph(self.unitsPerEM, missingGlyphXMLElement, yAxisPointingUpward) - return self.missingGlyph - if character not in self.glyphDictionary: - self.glyphDictionary[character] = Glyph(self.unitsPerEM, self.glyphXMLElementDictionary[character], yAxisPointingUpward) - return self.glyphDictionary[character] - - -class Glyph: - """Class to handle a glyph.""" - def __init__(self, unitsPerEM, xmlElement, yAxisPointingUpward): - """Initialize.""" - self.horizontalAdvanceX = float(xmlElement.attributeDictionary['horiz-adv-x']) - self.loops = [] - self.unitsPerEM = unitsPerEM - xmlElement.attributeDictionary['fill'] = '' - if 'd' not in xmlElement.attributeDictionary: - return - PathReader(self.loops, xmlElement, yAxisPointingUpward) - - def getSizedAdvancedLoops(self, fontSize, horizontalAdvanceX, yAxisPointingUpward=True): - """Get loops for font size, advanced horizontally.""" - multiplierX = fontSize / self.unitsPerEM - multiplierY = multiplierX - if not yAxisPointingUpward: - multiplierY = -multiplierY - sizedLoops = [] - for loop in self.loops: - sizedLoop = [] - sizedLoops.append(sizedLoop) - for point in loop: - sizedLoop.append( complex(multiplierX * (point.real + horizontalAdvanceX), multiplierY * point.imag)) - return sizedLoops - - -class MatrixSVG: - """Two by three svg matrix.""" - def __init__(self, tricomplex=None): - """Initialize.""" - self.tricomplex = tricomplex - - def __repr__(self): - """Get the string representation of this two by three svg matrix.""" - return str(self.tricomplex) - - def getOtherTimesSelf(self, otherTricomplex): - """Get the other matrix multiplied by this matrix.""" - if otherTricomplex is None: - return MatrixSVG(self.tricomplex) - if self.tricomplex is None: - return MatrixSVG(otherTricomplex) - return MatrixSVG(getTricomplexTimesOther(otherTricomplex, self.tricomplex)) - - def getSelfTimesOther(self, otherTricomplex): - """Get this matrix multiplied by the other matrix.""" - if otherTricomplex is None: - return MatrixSVG(self.tricomplex) - if self.tricomplex is None: - return MatrixSVG(otherTricomplex) - return MatrixSVG(getTricomplexTimesOther(self.tricomplex, otherTricomplex)) - - def getTransformedPath(self, path): - """Get transformed path.""" - if self.tricomplex is None: - return path - complexX = self.tricomplex[0] - complexY = self.tricomplex[1] - complexTranslation = self.tricomplex[2] - transformedPath = [] - for point in path: - x = complexX.real * point.real + complexY.real * point.imag - y = complexX.imag * point.real + complexY.imag * point.imag - transformedPath.append(complex(x, y) + complexTranslation) - return transformedPath - - def getTransformedPaths(self, paths): - """Get transformed paths.""" - if self.tricomplex is None: - return paths - transformedPaths = [] - for path in paths: - transformedPaths.append(self.getTransformedPath(path)) - return transformedPaths - - -class PathReader: - """Class to read svg path.""" - def __init__(self, loops, xmlElement, yAxisPointingUpward): - """Add to path string to loops.""" - self.controlPoints = None - self.loops = loops - self.oldPoint = None - self.outlinePaths = [] - self.path = [] - self.xmlElement = xmlElement - self.yAxisPointingUpward = yAxisPointingUpward - pathString = xmlElement.attributeDictionary['d'].replace(',', ' ') - global globalProcessPathWordDictionary - processPathWordDictionaryKeys = globalProcessPathWordDictionary.keys() - for processPathWordDictionaryKey in processPathWordDictionaryKeys: - pathString = pathString.replace( processPathWordDictionaryKey, ' %s ' % processPathWordDictionaryKey ) - self.words = getRightStripMinusSplit(pathString) - for self.wordIndex in xrange( len( self.words ) ): - word = self.words[ self.wordIndex ] - if word in processPathWordDictionaryKeys: - globalProcessPathWordDictionary[word](self) - if len(self.path) > 0: - self.outlinePaths.append(self.path) - self.loops += getTransformedOutlineByPaths(self.outlinePaths, xmlElement, yAxisPointingUpward) - - def addPathArc( self, end ): - """Add an arc to the path.""" - begin = self.getOldPoint() - self.controlPoints = None - radius = self.getComplexByExtraIndex(1) - xAxisRotation = math.radians(float(self.words[self.wordIndex + 3])) - largeArcFlag = euclidean.getBooleanFromValue(self.words[ self.wordIndex + 4 ]) - sweepFlag = euclidean.getBooleanFromValue(self.words[ self.wordIndex + 5 ]) - self.path += getArcComplexes(begin, end, largeArcFlag, radius, sweepFlag, xAxisRotation) - self.wordIndex += 8 - - def addPathCubic( self, controlPoints, end ): - """Add a cubic curve to the path.""" - begin = self.getOldPoint() - self.controlPoints = controlPoints - self.path += getCubicPoints( begin, controlPoints, end ) - self.wordIndex += 7 - - def addPathCubicReflected( self, controlPoint, end ): - """Add a cubic curve to the path from a reflected control point.""" - begin = self.getOldPoint() - controlPointBegin = begin - if self.controlPoints is not None: - if len(self.controlPoints) == 2: - controlPointBegin = begin + begin - self.controlPoints[-1] - self.controlPoints = [controlPointBegin, controlPoint] - self.path += getCubicPoints(begin, self.controlPoints, end) - self.wordIndex += 5 - - def addPathLine(self, lineFunction, point): - """Add a line to the path.""" - self.controlPoints = None - self.path.append(point) - self.wordIndex += 3 - self.addPathLineByFunction(lineFunction) - - def addPathLineAxis(self, point): - """Add an axis line to the path.""" - self.controlPoints = None - self.path.append(point) - self.wordIndex += 2 - - def addPathLineByFunction( self, lineFunction ): - """Add a line to the path by line function.""" - while 1: - if self.getFloatByExtraIndex() is None: - return - self.path.append(lineFunction()) - self.wordIndex += 2 - - def addPathMove( self, lineFunction, point ): - """Add an axis line to the path.""" - self.controlPoints = None - if len(self.path) > 0: - self.outlinePaths.append(self.path) - self.oldPoint = self.path[-1] - self.path = [point] - self.wordIndex += 3 - self.addPathLineByFunction(lineFunction) - - def addPathQuadratic( self, controlPoint, end ): - """Add a quadratic curve to the path.""" - begin = self.getOldPoint() - self.controlPoints = [controlPoint] - self.path += getQuadraticPoints(begin, controlPoint, end) - self.wordIndex += 5 - - def addPathQuadraticReflected( self, end ): - """Add a quadratic curve to the path from a reflected control point.""" - begin = self.getOldPoint() - controlPoint = begin - if self.controlPoints is not None: - if len( self.controlPoints ) == 1: - controlPoint = begin + begin - self.controlPoints[-1] - self.controlPoints = [ controlPoint ] - self.path += getQuadraticPoints(begin, controlPoint, end) - self.wordIndex += 3 - - def getComplexByExtraIndex( self, extraIndex=0 ): - """Get complex from the extraIndex.""" - return euclidean.getComplexByWords(self.words, self.wordIndex + extraIndex) - - def getComplexRelative(self): - """Get relative complex.""" - return self.getComplexByExtraIndex() + self.getOldPoint() - - def getFloatByExtraIndex( self, extraIndex=0 ): - """Get float from the extraIndex.""" - totalIndex = self.wordIndex + extraIndex - if totalIndex >= len(self.words): - return None - word = self.words[totalIndex] - if word[: 1].isalpha(): - return None - return euclidean.getFloatFromValue(word) - - def getOldPoint(self): - """Get the old point.""" - if len(self.path) > 0: - return self.path[-1] - return self.oldPoint - - def processPathWordA(self): - """Process path word A.""" - self.addPathArc( self.getComplexByExtraIndex( 6 ) ) - - def processPathWorda(self): - """Process path word a.""" - self.addPathArc(self.getComplexByExtraIndex(6) + self.getOldPoint()) - - def processPathWordC(self): - """Process path word C.""" - end = self.getComplexByExtraIndex( 5 ) - self.addPathCubic( [ self.getComplexByExtraIndex( 1 ), self.getComplexByExtraIndex(3) ], end ) - - def processPathWordc(self): - """Process path word C.""" - begin = self.getOldPoint() - end = self.getComplexByExtraIndex( 5 ) - self.addPathCubic( [ self.getComplexByExtraIndex( 1 ) + begin, self.getComplexByExtraIndex(3) + begin ], end + begin ) - - def processPathWordH(self): - """Process path word H.""" - beginY = self.getOldPoint().imag - self.addPathLineAxis(complex(float(self.words[self.wordIndex + 1]), beginY)) - while 1: - floatByExtraIndex = self.getFloatByExtraIndex() - if floatByExtraIndex is None: - return - self.path.append(complex(floatByExtraIndex, beginY)) - self.wordIndex += 1 - - def processPathWordh(self): - """Process path word h.""" - begin = self.getOldPoint() - self.addPathLineAxis(complex(float(self.words[self.wordIndex + 1]) + begin.real, begin.imag)) - while 1: - floatByExtraIndex = self.getFloatByExtraIndex() - if floatByExtraIndex is None: - return - self.path.append(complex(floatByExtraIndex + self.getOldPoint().real, begin.imag)) - self.wordIndex += 1 - - def processPathWordL(self): - """Process path word L.""" - self.addPathLine(self.getComplexByExtraIndex, self.getComplexByExtraIndex( 1 )) - - def processPathWordl(self): - """Process path word l.""" - self.addPathLine(self.getComplexRelative, self.getComplexByExtraIndex(1) + self.getOldPoint()) - - def processPathWordM(self): - """Process path word M.""" - self.addPathMove(self.getComplexByExtraIndex, self.getComplexByExtraIndex(1)) - - def processPathWordm(self): - """Process path word m.""" - self.addPathMove(self.getComplexRelative, self.getComplexByExtraIndex(1) + self.getOldPoint()) - - def processPathWordQ(self): - """Process path word Q.""" - self.addPathQuadratic( self.getComplexByExtraIndex( 1 ), self.getComplexByExtraIndex(3) ) - - def processPathWordq(self): - """Process path word q.""" - begin = self.getOldPoint() - self.addPathQuadratic(self.getComplexByExtraIndex(1) + begin, self.getComplexByExtraIndex(3) + begin) - - def processPathWordS(self): - """Process path word S.""" - self.addPathCubicReflected( self.getComplexByExtraIndex( 1 ), self.getComplexByExtraIndex(3) ) - - def processPathWords(self): - """Process path word s.""" - begin = self.getOldPoint() - self.addPathCubicReflected(self.getComplexByExtraIndex(1) + begin, self.getComplexByExtraIndex(3) + begin) - - def processPathWordT(self): - """Process path word T.""" - self.addPathQuadraticReflected( self.getComplexByExtraIndex( 1 ) ) - - def processPathWordt(self): - """Process path word t.""" - self.addPathQuadraticReflected(self.getComplexByExtraIndex(1) + self.getOldPoint()) - - def processPathWordV(self): - """Process path word V.""" - beginX = self.getOldPoint().real - self.addPathLineAxis(complex(beginX, float(self.words[self.wordIndex + 1]))) - while 1: - floatByExtraIndex = self.getFloatByExtraIndex() - if floatByExtraIndex is None: - return - self.path.append(complex(beginX, floatByExtraIndex)) - self.wordIndex += 1 - - def processPathWordv(self): - """Process path word v.""" - begin = self.getOldPoint() - self.addPathLineAxis(complex(begin.real, float(self.words[self.wordIndex + 1]) + begin.imag)) - while 1: - floatByExtraIndex = self.getFloatByExtraIndex() - if floatByExtraIndex is None: - return - self.path.append(complex(begin.real, floatByExtraIndex + self.getOldPoint().imag)) - self.wordIndex += 1 - - def processPathWordZ(self): - """Process path word Z.""" - self.controlPoints = None - if len(self.path) < 1: - return - self.loops.append(getChainMatrixSVGIfNecessary(self.xmlElement, self.yAxisPointingUpward).getTransformedPath(self.path)) - self.oldPoint = self.path[0] - self.path = [] - - def processPathWordz(self): - """Process path word z.""" - self.processPathWordZ() - - -class SVGReader: - """An svg carving.""" - def __init__(self): - """Add empty lists.""" - self.bridgeRotation = None - self.rotatedLoopLayers = [] - self.sliceDictionary = None - self.stopProcessing = False - self.z = 0.0 - - def flipDirectLayer(self, rotatedLoopLayer): - """Flip the y coordinate of the layer and direct the loops.""" - for loop in rotatedLoopLayer.loops: - for pointIndex, point in enumerate(loop): - loop[pointIndex] = complex(point.real, -point.imag) - triangle_mesh.sortLoopsInOrderOfArea(True, rotatedLoopLayer.loops) - for loopIndex, loop in enumerate(rotatedLoopLayer.loops): - isInsideLoops = euclidean.getIsInFilledRegion(rotatedLoopLayer.loops[: loopIndex], euclidean.getLeftPoint(loop)) - intercircle.directLoop((not isInsideLoops), loop) - - def getRotatedLoopLayer(self): - """Return the rotated loop layer.""" - if self.z is not None: - rotatedLoopLayer = euclidean.RotatedLoopLayer( self.z ) - self.rotatedLoopLayers.append( rotatedLoopLayer ) - rotatedLoopLayer.rotation = self.bridgeRotation - self.z = None - return self.rotatedLoopLayers[-1] - - def parseSVG(self, fileName, svgText): - """Parse SVG text and store the layers.""" - self.fileName = fileName - xmlParser = XMLSimpleReader(fileName, None, svgText) - self.root = xmlParser.getRoot() - if self.root is None: - print('Warning, root was None in parseSVG in SVGReader, so nothing will be done for:') - print(fileName) - return - self.parseSVGByXMLElement(self.root) - - def parseSVGByXMLElement(self, xmlElement): - """Parse SVG by xmlElement.""" - self.sliceDictionary = svg_writer.getSliceDictionary(xmlElement) - self.yAxisPointingUpward = euclidean.getBooleanFromDictionary(False, self.sliceDictionary, 'yAxisPointingUpward') - self.processXMLElement(xmlElement) - if not self.yAxisPointingUpward: - for rotatedLoopLayer in self.rotatedLoopLayers: - self.flipDirectLayer(rotatedLoopLayer) - - def processXMLElement(self, xmlElement): - """Process the xml element.""" - if self.stopProcessing: - return - lowerClassName = xmlElement.className.lower() - global globalProcessSVGElementDictionary - if lowerClassName in globalProcessSVGElementDictionary: - try: - globalProcessSVGElementDictionary[ lowerClassName ](self, xmlElement) - except: - print('Warning, in processXMLElement in svg_reader, could not process:') - print(xmlElement) - traceback.print_exc(file=sys.stdout) - for child in xmlElement.children: - self.processXMLElement( child ) - - -globalFontFileNames = None -globalFontReaderDictionary = {} -globalGetTricomplexDictionary = {} -globalGetTricomplexFunctions = [ - getTricomplexmatrix, - getTricomplexrotate, - getTricomplexscale, - getTricomplexskewX, - getTricomplexskewY, - getTricomplextranslate ] -globalProcessPathWordFunctions = [ - PathReader.processPathWordA, - PathReader.processPathWorda, - PathReader.processPathWordC, - PathReader.processPathWordc, - PathReader.processPathWordH, - PathReader.processPathWordh, - PathReader.processPathWordL, - PathReader.processPathWordl, - PathReader.processPathWordM, - PathReader.processPathWordm, - PathReader.processPathWordQ, - PathReader.processPathWordq, - PathReader.processPathWordS, - PathReader.processPathWords, - PathReader.processPathWordT, - PathReader.processPathWordt, - PathReader.processPathWordV, - PathReader.processPathWordv, - PathReader.processPathWordZ, - PathReader.processPathWordz ] -globalProcessPathWordDictionary = {} -globalProcessSVGElementDictionary = {} -globalProcessSVGElementFunctions = [ - processSVGElementcircle, - processSVGElementellipse, - processSVGElementg, - processSVGElementline, - processSVGElementpath, - processSVGElementpolygon, - processSVGElementpolyline, - processSVGElementrect, - processSVGElementtext ] -globalSideAngle = 0.5 * math.pi / float( globalNumberOfCornerPoints ) - - -addFunctionsToDictionary( globalGetTricomplexDictionary, globalGetTricomplexFunctions, 'getTricomplex') -addFunctionsToDictionary( globalProcessPathWordDictionary, globalProcessPathWordFunctions, 'processPathWord') -addFunctionsToDictionary( globalProcessSVGElementDictionary, globalProcessSVGElementFunctions, 'processSVGElement') diff --git a/skeinforge/fabmetheus_utilities/svg_writer.py b/skeinforge/fabmetheus_utilities/svg_writer.py deleted file mode 100644 index 767ddcf..0000000 --- a/skeinforge/fabmetheus_utilities/svg_writer.py +++ /dev/null @@ -1,289 +0,0 @@ -""" -Svg_writer is a class and collection of utilities to read from and write to an svg file. - -Svg_writer uses the layer_template.svg file in the templates folder in the same folder as svg_writer, to output an svg file. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities.xml_simple_reader import XMLSimpleReader -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import xml_simple_reader -from fabmetheus_utilities import xml_simple_writer -import cStringIO -import math -import os - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -globalOriginalTextString = '' in lineStripped: - isComment = False - commentElement.text = '%s%s-->\n' % (globalOriginalTextString, commentElementOutput.getvalue()) - commentElement.setParentAddToChildren(self.svgElement) - - def addRotatedLoopLayerToOutput(self, layerIndex, rotatedLoopLayer): - """Add rotated boundary layer to the output.""" - self.addLayerBegin(layerIndex, rotatedLoopLayer) - if rotatedLoopLayer.rotation is not None: - self.graphicsCopy.attributeDictionary['bridgeRotation'] = str(rotatedLoopLayer.rotation) - if self.addLayerTemplateToSVG: - self.pathDictionary['transform'] = self.getTransformString() - else: - del self.pathDictionary['transform'] - self.pathDictionary['d'] = self.getSVGStringForLoops(rotatedLoopLayer.loops) - - def addRotatedLoopLayersToOutput(self, rotatedLoopLayers): - """Add rotated boundary layers to the output.""" - for rotatedLoopLayerIndex, rotatedLoopLayer in enumerate(rotatedLoopLayers): - self.addRotatedLoopLayerToOutput(rotatedLoopLayerIndex, rotatedLoopLayer) - - def getReplacedSVGTemplate(self, fileName, procedureName, rotatedLoopLayers, xmlElement=None): - """Get the lines of text from the layer_template.svg file.""" - self.extent = self.cornerMaximum - self.cornerMinimum - svgTemplateText = archive.getFileText(archive.getTemplatesPath('layer_template.svg')) - self.xmlParser = XMLSimpleReader( fileName, None, svgTemplateText ) - self.svgElement = self.xmlParser.getRoot() - svgElementDictionary = self.svgElement.attributeDictionary - self.sliceDictionary = getSliceDictionary(self.svgElement) - self.controlBoxHeight = float(self.sliceDictionary['controlBoxHeight']) - self.controlBoxWidth = float(self.sliceDictionary['controlBoxWidth']) - self.margin = float(self.sliceDictionary['margin']) - self.marginTop = float(self.sliceDictionary['marginTop']) - self.textHeight = float(self.sliceDictionary['textHeight']) - self.unitScale = float(self.sliceDictionary['unitScale']) - svgMinWidth = float(self.sliceDictionary['svgMinWidth']) - self.controlBoxHeightMargin = self.controlBoxHeight + self.marginTop - if not self.addLayerTemplateToSVG: - self.svgElement.getXMLElementByID('layerTextTemplate').removeFromIDNameParent() - del self.svgElement.getXMLElementByID('sliceElementTemplate').attributeDictionary['transform'] - self.graphicsXMLElement = self.svgElement.getXMLElementByID('sliceElementTemplate') - self.graphicsXMLElement.attributeDictionary['id'] = 'z:' - self.addRotatedLoopLayersToOutput(rotatedLoopLayers) - self.setMetadataNoscriptElement('layerThickness', 'Layer Thickness: ', self.layerThickness) - self.setMetadataNoscriptElement('maxX', 'X: ', self.cornerMaximum.x) - self.setMetadataNoscriptElement('minX', 'X: ', self.cornerMinimum.x) - self.setMetadataNoscriptElement('maxY', 'Y: ', self.cornerMaximum.y) - self.setMetadataNoscriptElement('minY', 'Y: ', self.cornerMinimum.y) - self.setMetadataNoscriptElement('maxZ', 'Z: ', self.cornerMaximum.z) - self.setMetadataNoscriptElement('minZ', 'Z: ', self.cornerMinimum.z) - self.textHeight = float( self.sliceDictionary['textHeight'] ) - controlTop = len(rotatedLoopLayers) * (self.margin + self.extent.y * self.unitScale + self.textHeight) + self.marginTop + self.textHeight - self.svgElement.getFirstChildWithClassName('title').text = os.path.basename(fileName) + ' - Slice Layers' - svgElementDictionary['height'] = '%spx' % self.getRounded(max(controlTop, self.controlBoxHeightMargin)) - width = max(self.extent.x * self.unitScale, svgMinWidth) - svgElementDictionary['width'] = '%spx' % self.getRounded( width ) - self.sliceDictionary['decimalPlacesCarried'] = str( self.decimalPlacesCarried ) - if self.perimeterWidth is not None: - self.sliceDictionary['perimeterWidth'] = self.getRounded( self.perimeterWidth ) - self.sliceDictionary['yAxisPointingUpward'] = 'true' - self.sliceDictionary['procedureName'] = procedureName - self.setDimensionTexts('dimX', 'X: ' + self.getRounded(self.extent.x)) - self.setDimensionTexts('dimY', 'Y: ' + self.getRounded(self.extent.y)) - self.setDimensionTexts('dimZ', 'Z: ' + self.getRounded(self.extent.z)) - self.setTexts('numberOfLayers', 'Number of Layers: %s' % len(rotatedLoopLayers)) - volume = 0.0 - for rotatedLoopLayer in rotatedLoopLayers: - volume += euclidean.getAreaLoops(rotatedLoopLayer.loops) - volume *= 0.001 - self.setTexts('volume', 'Volume: %s cm3' % self.getRounded(volume)) - if not self.addLayerTemplateToSVG: - self.svgElement.getFirstChildWithClassName('script').removeFromIDNameParent() - self.svgElement.getXMLElementByID('isoControlBox').removeFromIDNameParent() - self.svgElement.getXMLElementByID('layerControlBox').removeFromIDNameParent() - self.svgElement.getXMLElementByID('scrollControlBox').removeFromIDNameParent() - self.graphicsXMLElement.removeFromIDNameParent() - self.addOriginalAsComment(xmlElement) - output = cStringIO.StringIO() - output.write(self.xmlParser.beforeRoot) - self.svgElement.addXML(0, output) - return xml_simple_writer.getBeforeRootOutput(self.xmlParser) - - def getRounded(self, number): - """Get number rounded to the number of carried decimal places as a string.""" - return euclidean.getRoundedToPlacesString(self.decimalPlacesCarried, number) - - def getRoundedComplexString(self, point): - """Get the rounded complex string.""" - return self.getRounded( point.real ) + ' ' + self.getRounded( point.imag ) - - def getSVGStringForLoop( self, loop ): - """Get the svg loop string.""" - if len(loop) < 1: - return '' - return self.getSVGStringForPath(loop) + ' z' - - def getSVGStringForLoops( self, loops ): - """Get the svg loops string.""" - loopString = '' - if len(loops) > 0: - loopString += self.getSVGStringForLoop( loops[0] ) - for loop in loops[1 :]: - loopString += ' ' + self.getSVGStringForLoop(loop) - return loopString - - def getSVGStringForPath( self, path ): - """Get the svg path string.""" - svgLoopString = '' - for point in path: - stringBeginning = 'M ' - if len( svgLoopString ) > 0: - stringBeginning = ' L ' - svgLoopString += stringBeginning + self.getRoundedComplexString(point) - return svgLoopString - - def setMetadataNoscriptElement(self, key, prefix, value): - """Set the metadata value and the text.""" - valueString = self.getRounded(value) - self.sliceDictionary[key] = valueString - self.setDimensionTexts(key, prefix + valueString) - - def setDimensionTexts(self, key, valueString): - """Set the texts to the valueString followed by mm.""" - self.setTexts(key, valueString + ' mm') - - def setTexts(self, key, valueString): - """Set the texts to the valueString.""" - self.svgElement.getXMLElementByID(key + 'Iso').text = valueString - self.svgElement.getXMLElementByID(key + 'Layer').text = valueString - self.svgElement.getXMLElementByID(key + 'Scroll').text = valueString - - def getTransformString(self): - """Get the svg transform string.""" - cornerMinimumXString = self.getRounded(-self.cornerMinimum.x) - cornerMinimumYString = self.getRounded(-self.cornerMinimum.y) - return 'scale(%s, %s) translate(%s, %s)' % (self.unitScale, - self.unitScale, cornerMinimumXString, cornerMinimumYString) diff --git a/skeinforge/fabmetheus_utilities/templates/canvas_template.svg b/skeinforge/fabmetheus_utilities/templates/canvas_template.svg deleted file mode 100644 index 7baf264..0000000 --- a/skeinforge/fabmetheus_utilities/templates/canvas_template.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - -replaceLineWithTitle - - - diff --git a/skeinforge/fabmetheus_utilities/templates/layer_template.svg b/skeinforge/fabmetheus_utilities/templates/layer_template.svg deleted file mode 100644 index 48df286..0000000 --- a/skeinforge/fabmetheus_utilities/templates/layer_template.svg +++ /dev/null @@ -1,519 +0,0 @@ - - - - - - - - - replaceWith_Title - - - - - - - Layer 1, z:0.1 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - - - - - - Max - - - - - - Dimension - - - - - - Statistics - - - - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - - - - - - Max - - - - - - Dimension - - - - - - Statistics - - - - - - - - - - Y - X - Scale - : 1 - < - > - - Min - - - - - - Max - - - - - - Dimension - - - - - - Statistics - - - - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - diff --git a/skeinforge/fabmetheus_utilities/vector3.py b/skeinforge/fabmetheus_utilities/vector3.py deleted file mode 100644 index 691794f..0000000 --- a/skeinforge/fabmetheus_utilities/vector3.py +++ /dev/null @@ -1,528 +0,0 @@ -""" -Vector3 is a three dimensional vector class. - -Below are examples of Vector3 use. - ->>> from vector3 import Vector3 ->>> origin = Vector3() ->>> origin -0.0, 0.0, 0.0 ->>> pythagoras = Vector3( 3, 4, 0 ) ->>> pythagoras -3.0, 4.0, 0.0 ->>> pythagoras.magnitude() -5.0 ->>> pythagoras.magnitudeSquared() -25 ->>> triplePythagoras = pythagoras * 3.0 ->>> triplePythagoras -9.0, 12.0, 0.0 ->>> plane = pythagoras.dropAxis() ->>> plane -(3+4j) -""" - -from __future__ import absolute_import -try: - import psyco - psyco.full() -except: - pass -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import xml_simple_writer -import math -import operator - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -class Vector3: - """A three dimensional vector class.""" - __slots__ = ['x', 'y', 'z'] - - def __init__(self, x=0.0, y=0.0, z=0.0): - self.x = x - self.y = y - self.z = z - - def __abs__(self): - """Get the magnitude of the Vector3.""" - return math.sqrt( self.x * self.x + self.y * self.y + self.z * self.z ) - - magnitude = __abs__ - - def __add__(self, other): - """Get the sum of this Vector3 and other one.""" - return Vector3( self.x + other.x, self.y + other.y, self.z + other.z ) - - def __copy__(self): - """Get the copy of this Vector3.""" - return Vector3( self.x, self.y, self.z ) - - __pos__ = __copy__ - - copy = __copy__ - - def __div__(self, other): - """Get a new Vector3 by dividing each component of this one.""" - return Vector3( self.x / other, self.y / other, self.z / other ) - - def __eq__(self, other): - """Determine whether this vector is identical to other one.""" - if other is None: - return False - if other.__class__ != self.__class__: - return False - return self.x == other.x and self.y == other.y and self.z == other.z - - def __floordiv__(self, other): - """Get a new Vector3 by floor dividing each component of this one.""" - return Vector3( self.x // other, self.y // other, self.z // other ) - - def _getAccessibleAttribute(self, attributeName): - """Get the accessible attribute.""" - if attributeName in globalGetAccessibleAttributeSet: - return getattr(self, attributeName, None) - return None - - def __hash__(self): - """Determine whether this vector is identical to other one.""" - return self.__repr__().__hash__() - - def __iadd__(self, other): - """Add other Vector3 to this one.""" - self.x += other.x - self.y += other.y - self.z += other.z - return self - - def __idiv__(self, other): - """Divide each component of this Vector3.""" - self.x /= other - self.y /= other - self.z /= other - return self - - def __ifloordiv__(self, other): - """Floor divide each component of this Vector3.""" - self.x //= other - self.y //= other - self.z //= other - return self - - def __imul__(self, other): - """Multiply each component of this Vector3.""" - self.x *= other - self.y *= other - self.z *= other - return self - - def __isub__(self, other): - """Subtract other Vector3 from this one.""" - self.x -= other.x - self.y -= other.y - self.z -= other.z - return self - - def __itruediv__(self, other): - """True divide each component of this Vector3.""" - self.x = operator.truediv( self.x, other ) - self.y = operator.truediv( self.y, other ) - self.z = operator.truediv( self.z, other ) - return self - - def __mul__(self, other): - """Get a new Vector3 by multiplying each component of this one.""" - return Vector3( self.x * other, self.y * other, self.z * other ) - - def __ne__(self, other): - """Determine whether this vector is not identical to other one.""" - return not self.__eq__(other) - - def __neg__(self): - return Vector3( - self.x, - self.y, - self.z ) - - def __nonzero__(self): - return self.x != 0 or self.y != 0 or self.z != 0 - - def __repr__(self): - """Get the string representation of this Vector3.""" - return '(%s, %s, %s)' % ( self.x, self.y, self.z ) - - def __rdiv__(self, other): - """Get a new Vector3 by dividing each component of this one.""" - return Vector3( other / self.x, other / self.y, other / self.z ) - - def __rfloordiv__(self, other): - """Get a new Vector3 by floor dividing each component of this one.""" - return Vector3( other // self.x, other // self.y, other // self.z ) - - def __rmul__(self, other): - """Get a new Vector3 by multiplying each component of this one.""" - return Vector3( self.x * other, self.y * other, self.z * other ) - - def __rtruediv__(self, other): - """Get a new Vector3 by true dividing each component of this one.""" - return Vector3( operator.truediv( other , self.x ), operator.truediv( other, self.y ), operator.truediv( other, self.z ) ) - - def _setAccessibleAttribute(self, attributeName, value): - """Set the accessible attribute.""" - if attributeName in globalSetAccessibleAttributeSet: - setattr(self, attributeName, value) - - def __sub__(self, other): - """Get the difference between the Vector3 and other one.""" - return Vector3( self.x - other.x, self.y - other.y, self.z - other.z ) - - def __truediv__(self, other): - """Get a new Vector3 by true dividing each component of this one.""" - return Vector3( operator.truediv( self.x, other ), operator.truediv( self.y, other ), operator.truediv( self.z, other ) ) - - def cross(self, other): - """Calculate the cross product of this vector with other one.""" - return Vector3(self.y * other.z - self.z * other.y, -self.x * other.z + self.z * other.x, self.x * other.y - self.y * other.x) - - def distance(self, other): - """Get the Euclidean distance between this vector and other one.""" - return math.sqrt( self.distanceSquared(other) ) - - def distanceSquared(self, other): - """Get the square of the Euclidean distance between this vector and other one.""" - separationX = self.x - other.x - separationY = self.y - other.y - separationZ = self.z - other.z - return separationX * separationX + separationY * separationY + separationZ * separationZ - - def dot(self, other): - """Calculate the dot product of this vector with other one.""" - return self.x * other.x + self.y * other.y + self.z * other.z - - def dropAxis( self, which = 2 ): - """Get a complex by removing one axis of the vector3.""" - if which == 0: - return complex( self.y, self.z ) - if which == 1: - return complex( self.x, self.z ) - if which == 2: - return complex( self.x, self.y ) - - def getFloatList(self): - """Get the vector as a list of floats.""" - return [ float( self.x ), float( self.y ), float( self.z ) ] - - def getIsDefault(self): - """Determine if this is the zero vector.""" - if self.x != 0.0: - return False - if self.y != 0.0: - return False - return self.z == 0.0 - - def getNormalized(self): - """Get the normalized Vector3.""" - magnitude = abs(self) - if magnitude == 0.0: - return self.copy() - return self / magnitude - - def magnitudeSquared(self): - """Get the square of the magnitude of the Vector3.""" - return self.x * self.x + self.y * self.y + self.z * self.z - - def maximize(self, other): - """Maximize the Vector3.""" - self.x =max(other.x, self.x) - self.y =max(other.y, self.y) - self.z =max(other.z, self.z) - - def minimize(self, other): - """Minimize the Vector3.""" - self.x =min(other.x, self.x) - self.y =min(other.y, self.y) - self.z =min(other.z, self.z) - - def normalize(self): - """Scale each component of this Vector3 so that it has a magnitude of 1. If this Vector3 has a magnitude of 0, this method has no effect.""" - magnitude = abs(self) - if magnitude != 0.0: - self /= magnitude - - def reflect( self, normal ): - """Reflect the Vector3 across the normal, which is assumed to be normalized.""" - distance = 2 * ( self.x * normal.x + self.y * normal.y + self.z * normal.z ) - return Vector3( self.x - distance * normal.x, self.y - distance * normal.y, self.z - distance * normal.z ) - - def setToVector3(self, other): - """Set this Vector3 to be identical to other one.""" - self.x = other.x - self.y = other.y - self.z = other.z - - def setToXYZ( self, x, y, z ): - """Set the x, y, and z components of this Vector3.""" - self.x = x - self.y = y - self.z = z - - -globalGetAccessibleAttributeSet = 'x y z'.split() -globalSetAccessibleAttributeSet = globalGetAccessibleAttributeSet - -""" -class Vector3: - __slots__ = ['x', 'y', 'z'] - - def __init__(self, x, y, z): - self.x = x - self.y = y - self.z = z - - def __copy__(self): - return self.__class__(self.x, self.y, self.z) - - copy = __copy__ - - def __repr__(self): - return 'Vector3(%.2f, %.2f, %.2f)' % (self.x, - self.y, - self.z) - - def __eq__(self, other): - if isinstance(other, Vector3): - return self.x == other.x and \ - self.y == other.y and \ - self.z == other.z - else: - assert hasattr(other, '__len__') and len(other) == 3 - return self.x == other[0] and \ - self.y == other[1] and \ - self.z == other[2] - - def __ne__(self, other): - return not self.__eq__(other) - - def __nonzero__(self): - return self.x != 0 or self.y != 0 or self.z != 0 - - def __len__(self): - return 3 - - def __getitem__(self, key): - return (self.x, self.y, self.z)[key] - - def __setitem__(self, key, value): - l = [self.x, self.y, self.z] - l[key] = value - self.x, self.y, self.z = l - - def __iter__(self): - return iter((self.x, self.y, self.z)) - - def __getattr__(self, name): - try: - return tuple([(self.x, self.y, self.z)['xyz'.index(c)] \ - for c in name]) - except ValueError: - raise AttributeError, name - - if _enable_swizzle_set: - # This has detrimental performance on ordinary setattr as well - # if enabled - def __setattr__(self, name, value): - if len(name) == 1: - object.__setattr__(self, name, value) - else: - try: - l = [self.x, self.y, self.z] - for c, v in map(None, name, value): - l['xyz'.index(c)] = v - self.x, self.y, self.z = l - except ValueError: - raise AttributeError, name - - - def __add__(self, other): - if isinstance(other, Vector3): - # Vector + Vector -> Vector - # Vector + Point -> Point - # Point + Point -> Vector - if self.__class__ is other.__class__: - _class = Vector3 - else: - _class = Point3 - return _class(self.x + other.x, - self.y + other.y, - self.z + other.z) - else: - assert hasattr(other, '__len__') and len(other) == 3 - return Vector3(self.x + other[0], - self.y + other[1], - self.z + other[2]) - __radd__ = __add__ - - def __iadd__(self, other): - if isinstance(other, Vector3): - self.x += other.x - self.y += other.y - self.z += other.z - else: - self.x += other[0] - self.y += other[1] - self.z += other[2] - return self - - def __sub__(self, other): - if isinstance(other, Vector3): - # Vector - Vector -> Vector - # Vector - Point -> Point - # Point - Point -> Vector - if self.__class__ is other.__class__: - _class = Vector3 - else: - _class = Point3 - return Vector3(self.x - other.x, - self.y - other.y, - self.z - other.z) - else: - assert hasattr(other, '__len__') and len(other) == 3 - return Vector3(self.x - other[0], - self.y - other[1], - self.z - other[2]) - - - def __rsub__(self, other): - if isinstance(other, Vector3): - return Vector3(other.x - self.x, - other.y - self.y, - other.z - self.z) - else: - assert hasattr(other, '__len__') and len(other) == 3 - return Vector3(other.x - self[0], - other.y - self[1], - other.z - self[2]) - - def __mul__(self, other): - if isinstance(other, Vector3): - # TODO component-wise mul/div in-place and on Vector2; docs. - if self.__class__ is Point3 or other.__class__ is Point3: - _class = Point3 - else: - _class = Vector3 - return _class(self.x * other.x, - self.y * other.y, - self.z * other.z) - else: - assert type(other) in (int, long, float) - return Vector3(self.x * other, - self.y * other, - self.z * other) - - __rmul__ = __mul__ - - def __imul__(self, other): - assert type(other) in (int, long, float) - self.x *= other - self.y *= other - self.z *= other - return self - - def __div__(self, other): - assert type(other) in (int, long, float) - return Vector3(operator.div(self.x, other), - operator.div(self.y, other), - operator.div(self.z, other)) - - - def __rdiv__(self, other): - assert type(other) in (int, long, float) - return Vector3(operator.div(other, self.x), - operator.div(other, self.y), - operator.div(other, self.z)) - - def __floordiv__(self, other): - assert type(other) in (int, long, float) - return Vector3(operator.floordiv(self.x, other), - operator.floordiv(self.y, other), - operator.floordiv(self.z, other)) - - - def __rfloordiv__(self, other): - assert type(other) in (int, long, float) - return Vector3(operator.floordiv(other, self.x), - operator.floordiv(other, self.y), - operator.floordiv(other, self.z)) - - def __truediv__(self, other): - assert type(other) in (int, long, float) - return Vector3(operator.truediv(self.x, other), - operator.truediv(self.y, other), - operator.truediv(self.z, other)) - - - def __rtruediv__(self, other): - assert type(other) in (int, long, float) - return Vector3(operator.truediv(other, self.x), - operator.truediv(other, self.y), - operator.truediv(other, self.z)) - - def __neg__(self): - return Vector3(-self.x, - -self.y, - -self.z) - - __pos__ = __copy__ - - def __abs__(self): - return math.sqrt(self.x ** 2 + \ - self.y ** 2 + \ - self.z ** 2) - - magnitude = __abs__ - - def magnitude_squared(self): - return self.x ** 2 + \ - self.y ** 2 + \ - self.z ** 2 - - def normalize(self): - d = self.magnitude() - if d: - self.x /= d - self.y /= d - self.z /= d - return self - - def normalized(self): - d = self.magnitude() - if d: - return Vector3(self.x / d, - self.y / d, - self.z / d) - return self.copy() - - def dot(self, other): - assert isinstance(other, Vector3) - return self.x * other.x + \ - self.y * other.y + \ - self.z * other.z - - def cross(self, other): - assert isinstance(other, Vector3) - return Vector3(self.y * other.z - self.z * other.y, - -self.x * other.z + self.z * other.x, - self.x * other.y - self.y * other.x) - - def reflect(self, normal): - # assume normal is normalized - assert isinstance(normal, Vector3) - d = 2 * (self.x * normal.x + self.y * normal.y + self.z * normal.z) - return Vector3(self.x - d * normal.x, - self.y - d * normal.y, - self.z - d * normal.z) -""" diff --git a/skeinforge/fabmetheus_utilities/vector3index.py b/skeinforge/fabmetheus_utilities/vector3index.py deleted file mode 100644 index 64fa7e8..0000000 --- a/skeinforge/fabmetheus_utilities/vector3index.py +++ /dev/null @@ -1,277 +0,0 @@ -""" -Vector3 is a three dimensional vector class. - -Below are examples of Vector3 use. - ->>> from vector3 import Vector3 ->>> origin = Vector3() ->>> origin -0.0, 0.0, 0.0 ->>> pythagoras = Vector3( 3, 4, 0 ) ->>> pythagoras -3.0, 4.0, 0.0 ->>> pythagoras.magnitude() -5.0 ->>> pythagoras.magnitudeSquared() -25 ->>> triplePythagoras = pythagoras * 3.0 ->>> triplePythagoras -9.0, 12.0, 0.0 ->>> plane = pythagoras.dropAxis() ->>> plane -(3+4j) -""" - -from __future__ import absolute_import -try: - import psyco - psyco.full() -except: - pass -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import xml_simple_writer -import math -import operator - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -class Vector3Index: - """A three dimensional vector index class.""" - __slots__ = ['index', 'x', 'y', 'z'] - - def __init__( self, index, x = 0.0, y = 0.0, z = 0.0 ): - self.index = index - self.x = x - self.y = y - self.z = z - - def __abs__(self): - """Get the magnitude of the Vector3.""" - return math.sqrt( self.x * self.x + self.y * self.y + self.z * self.z ) - - magnitude = __abs__ - - def __add__(self, other): - """Get the sum of this Vector3 and other one.""" - return Vector3Index( self.index, self.x + other.x, self.y + other.y, self.z + other.z ) - - def __copy__(self): - """Get the copy of this Vector3.""" - return Vector3Index( self.index, self.x, self.y, self.z ) - - __pos__ = __copy__ - - copy = __copy__ - - def __div__(self, other): - """Get a new Vector3 by dividing each component of this one.""" - return Vector3Index( self.index, self.x / other, self.y / other, self.z / other ) - - def __eq__(self, other): - """Determine whether this vector is identical to other one.""" - if other is None: - return False - if other.__class__ != self.__class__: - return False - return self.x == other.x and self.y == other.y and self.z == other.z - - def __floordiv__(self, other): - """Get a new Vector3 by floor dividing each component of this one.""" - return Vector3Index( self.index, self.x // other, self.y // other, self.z // other ) - - def _getAccessibleAttribute(self, attributeName): - """Get the accessible attribute.""" - global globalGetAccessibleAttributeSet - if attributeName in globalGetAccessibleAttributeSet: - return getattr(self, attributeName, None) - return None - - def __hash__(self): - """Determine whether this vector is identical to other one.""" - return self.__repr__().__hash__() - - def __iadd__(self, other): - """Add other Vector3 to this one.""" - self.x += other.x - self.y += other.y - self.z += other.z - return self - - def __idiv__(self, other): - """Divide each component of this Vector3.""" - self.x /= other - self.y /= other - self.z /= other - return self - - def __ifloordiv__(self, other): - """Floor divide each component of this Vector3.""" - self.x //= other - self.y //= other - self.z //= other - return self - - def __imul__(self, other): - """Multiply each component of this Vector3.""" - self.x *= other - self.y *= other - self.z *= other - return self - - def __isub__(self, other): - """Subtract other Vector3 from this one.""" - self.x -= other.x - self.y -= other.y - self.z -= other.z - return self - - def __itruediv__(self, other): - """True divide each component of this Vector3.""" - self.x = operator.truediv( self.x, other ) - self.y = operator.truediv( self.y, other ) - self.z = operator.truediv( self.z, other ) - return self - - def __mul__(self, other): - """Get a new Vector3 by multiplying each component of this one.""" - return Vector3Index( self.index, self.x * other, self.y * other, self.z * other ) - - def __ne__(self, other): - """Determine whether this vector is not identical to other one.""" - return not self.__eq__(other) - - def __neg__(self): - return Vector3Index( self.index, - self.x, - self.y, - self.z ) - - def __nonzero__(self): - return self.x != 0 or self.y != 0 or self.z != 0 - - def __repr__(self): - """Get the string representation of this Vector3 index.""" - return '(%s, %s, %s, %s)' % (self.index, self.x, self.y, self.z) - - def __rdiv__(self, other): - """Get a new Vector3 by dividing each component of this one.""" - return Vector3Index( self.index, other / self.x, other / self.y, other / self.z ) - - def __rfloordiv__(self, other): - """Get a new Vector3 by floor dividing each component of this one.""" - return Vector3Index( self.index, other // self.x, other // self.y, other // self.z ) - - def __rmul__(self, other): - """Get a new Vector3 by multiplying each component of this one.""" - return Vector3Index( self.index, self.x * other, self.y * other, self.z * other ) - - def __rtruediv__(self, other): - """Get a new Vector3 by true dividing each component of this one.""" - return Vector3Index( self.index, operator.truediv( other , self.x ), operator.truediv( other, self.y ), operator.truediv( other, self.z ) ) - - def _setAccessibleAttribute(self, attributeName, value): - """Set the accessible attribute.""" - if attributeName in globalSetAccessibleAttributeSet: - setattr(self, attributeName, value) - - def __sub__(self, other): - """Get the difference between the Vector3 and other one.""" - return Vector3Index( self.index, self.x - other.x, self.y - other.y, self.z - other.z ) - - def __truediv__(self, other): - """Get a new Vector3 by true dividing each component of this one.""" - return Vector3Index( self.index, operator.truediv( self.x, other ), operator.truediv( self.y, other ), operator.truediv( self.z, other ) ) - - def cross(self, other): - """Calculate the cross product of this vector with other one.""" - return Vector3Index( self.index, self.y * other.z - self.z * other.y, - self.x * other.z + self.z * other.x, self.x * other.y - self.y * other.x ) - - def distance(self, other): - """Get the Euclidean distance between this vector and other one.""" - return math.sqrt( self.distanceSquared(other) ) - - def distanceSquared(self, other): - """Get the square of the Euclidean distance between this vector and other one.""" - separationX = self.x - other.x - separationY = self.y - other.y - separationZ = self.z - other.z - return separationX * separationX + separationY * separationY + separationZ * separationZ - - def dot(self, other): - """Calculate the dot product of this vector with other one.""" - return self.x * other.x + self.y * other.y + self.z * other.z - - def dropAxis( self, which = 2 ): - """Get a complex by removing one axis of the vector3.""" - if which == 0: - return complex( self.y, self.z ) - if which == 1: - return complex( self.x, self.z ) - if which == 2: - return complex( self.x, self.y ) - - def getFloatList(self): - """Get the vector as a list of floats.""" - return [ float( self.x ), float( self.y ), float( self.z ) ] - - def getIsDefault(self): - """Determine if this is the zero vector.""" - if self.x != 0.0: - return False - if self.y != 0.0: - return False - return self.z == 0.0 - - def getNormalized(self): - """Get the normalized Vector3.""" - magnitude = abs(self) - if magnitude == 0.0: - return self.copy() - return self / magnitude - - def magnitudeSquared(self): - """Get the square of the magnitude of the Vector3.""" - return self.x * self.x + self.y * self.y + self.z * self.z - - def maximize(self, other): - """Maximize the Vector3.""" - self.x =max(other.x, self.x) - self.y =max(other.y, self.y) - self.z =max(other.z, self.z) - - def minimize(self, other): - """Minimize the Vector3.""" - self.x =min(other.x, self.x) - self.y =min(other.y, self.y) - self.z =min(other.z, self.z) - - def normalize(self): - """Scale each component of this Vector3 so that it has a magnitude of 1. If this Vector3 has a magnitude of 0, this method has no effect.""" - magnitude = abs(self) - if magnitude != 0.0: - self /= magnitude - - def reflect( self, normal ): - """Reflect the Vector3 across the normal, which is assumed to be normalized.""" - distance = 2 * ( self.x * normal.x + self.y * normal.y + self.z * normal.z ) - return Vector3Index( self.index, self.x - distance * normal.x, self.y - distance * normal.y, self.z - distance * normal.z ) - - def setToVector3(self, other): - """Set this Vector3 to be identical to other one.""" - self.x = other.x - self.y = other.y - self.z = other.z - - def setToXYZ( self, x, y, z ): - """Set the x, y, and z components of this Vector3.""" - self.x = x - self.y = y - self.z = z - - -globalGetAccessibleAttributeSet = 'x y z'.split() -globalSetAccessibleAttributeSet = globalGetAccessibleAttributeSet diff --git a/skeinforge/fabmetheus_utilities/version.txt b/skeinforge/fabmetheus_utilities/version.txt deleted file mode 100644 index eb45151..0000000 --- a/skeinforge/fabmetheus_utilities/version.txt +++ /dev/null @@ -1 +0,0 @@ -SFACT_V2.0 11.08.01 help at www.reprapfordummies.net \ No newline at end of file diff --git a/skeinforge/fabmetheus_utilities/xml_simple_reader.py b/skeinforge/fabmetheus_utilities/xml_simple_reader.py deleted file mode 100644 index 0a2f58f..0000000 --- a/skeinforge/fabmetheus_utilities/xml_simple_reader.py +++ /dev/null @@ -1,563 +0,0 @@ -""" -The xml_simple_reader.py script is an xml parser that can parse a line separated xml text. - -This xml parser will read a line seperated xml text and produce a tree of the xml with a root element. Each element can have an attribute table, children, a class name, parent, text and a link to the root element. - -This example gets an xml tree for the xml file boolean.xml. This example is run in a terminal in the folder which contains boolean.xml and xml_simple_reader.py. - - -> python -Python 2.5.1 (r251:54863, Sep 22 2007, 01:43:31) -[GCC 4.2.1 (SUSE Linux)] on linux2 -Type "help", "copyright", "credits" or "license" for more information. ->>> fileName = 'boolean.xml' ->>> file = open(fileName, 'r') ->>> xmlText = file.read() ->>> file.close() ->>> from xml_simple_reader import XMLSimpleReader ->>> xmlParser = XMLSimpleReader(fileName, None, xmlText) ->>> print( xmlParser ) - ?xml, {'version': '1.0'} - ArtOfIllusion, {'xmlns:bf': '//babelfiche/codec', 'version': '2.0', 'fileversion': '3'} - Scene, {'bf:id': 'theScene'} - materials, {'bf:elem-type': 'java.lang.Object', 'bf:list': 'collection', 'bf:id': '1', 'bf:type': 'java.util.Vector'} -.. -many more lines of the xml tree -.. - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.geometry.geometry_utilities import evaluate -from fabmetheus_utilities.geometry.geometry_utilities import matrix -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import xml_simple_writer -import cStringIO - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead \nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addXMLLine(line, xmlLines): - """Get the all the xml lines of a text.""" - strippedLine = line.strip() - if strippedLine[ : len('') - if endIndex != - 1: - endIndex += len('-->') - commentLine = line[: endIndex] - remainderLine = line[endIndex :].strip() - if len(remainderLine) > 0: - xmlLines.append(commentLine) - xmlLines.append(remainderLine) - return - xmlLines.append(line) - -def getXMLLines(text): - """Get the all the xml lines of a text.""" - accumulatedOutput = None - textLines = archive.getTextLines(text) - combinedLines = [] - lastWord = '>' - for textLine in textLines: - strippedLine = textLine.strip() - firstCharacter = None - lastCharacter = None - if len( strippedLine ) > 1: - firstCharacter = strippedLine[0] - lastCharacter = strippedLine[-1] - if firstCharacter == '<' and lastCharacter != '>' and accumulatedOutput is None: - accumulatedOutput = cStringIO.StringIO() - accumulatedOutput.write( textLine ) - if strippedLine[ : len('' - else: - if accumulatedOutput is None: - addXMLLine( textLine, combinedLines ) - else: - accumulatedOutput.write('\n' + textLine ) - if strippedLine[ - len( lastWord ) : ] == lastWord: - addXMLLine( accumulatedOutput.getvalue(), combinedLines ) - accumulatedOutput = None - lastWord = '>' - xmlLines = [] - for combinedLine in combinedLines: - xmlLines += getXMLTagSplitLines(combinedLine) - return xmlLines - -def getXMLTagSplitLines(combinedLine): - """Get the xml lines split at a tag.""" - characterIndex = 0 - lastWord = None - splitIndexes = [] - tagEnd = False - while characterIndex < len(combinedLine): - character = combinedLine[characterIndex] - if character == '"' or character == "'": - lastWord = character - elif combinedLine[characterIndex : characterIndex + len('' - elif combinedLine[characterIndex : characterIndex + len('' - if lastWord is not None: - characterIndex = combinedLine.find(lastWord, characterIndex + 1) - if characterIndex == -1: - return [combinedLine] - character = None - lastWord = None - if character == '>': - tagEnd = True - elif character == '<': - if tagEnd: - if combinedLine[characterIndex : characterIndex + 2] != '') - if cdataEndIndex != - 1: - cdataEndIndex += len(']]>') - self.text = lineStripped[cdataBeginIndex : cdataEndIndex] - lineStripped = lineStripped[: cdataBeginIndex] + lineStripped[cdataEndIndex :] - self.className = lineStripped[1 : lineStripped.replace('/>', ' ').replace('>', ' ').replace('\n', ' ').find(' ')] - lastWord = lineStripped[-2 :] - lineAfterClassName = lineStripped[2 + len(self.className) : -1] - beforeQuote = '' - lastQuoteCharacter = None - withinQuote = '' - for characterIndex in xrange(len(lineAfterClassName)): - character = lineAfterClassName[characterIndex] - if lastQuoteCharacter is None: - if character == '"' or character == "'": - lastQuoteCharacter = character - character = '' - if character == lastQuoteCharacter: - self.addAttribute(beforeQuote, withinQuote) - beforeQuote = '' - lastQuoteCharacter = None - withinQuote = '' - character = '' - if lastQuoteCharacter is None: - beforeQuote += character - else: - withinQuote += character - self.addToIdentifierDictionaryIFIdentifierExists() - if lastWord == '/>': - return parent - tagEnd = '' % self.className - if lineStripped[-len(tagEnd) :] == tagEnd: - untilTagEnd = lineStripped[: -len(tagEnd)] - lastGreaterThanIndex = untilTagEnd.rfind('>') - self.text += untilTagEnd[ lastGreaterThanIndex + 1 : ] - return parent - return self - - def getParser(self): - """Get the parser.""" - return self.getRoot().parser - - def getPaths(self): - """Get all paths.""" - if self.xmlObject is None: - return [] - return self.xmlObject.getPaths() - - def getPreviousVertex(self, defaultVector3=None): - """Get previous vertex if it exists.""" - if self.parent is None: - return defaultVector3 - if self.parent.xmlObject is None: - return defaultVector3 - if len(self.parent.xmlObject.vertexes) < 1: - return defaultVector3 - return self.parent.xmlObject.vertexes[-1] - - def getPreviousXMLElement(self): - """Get previous XMLElement if it exists.""" - if self.parent is None: - return None - previousXMLElementIndex = self.parent.children.index(self) - 1 - if previousXMLElementIndex < 0: - return None - return self.parent.children[previousXMLElementIndex] - - def getRoot(self): - """Get the root element.""" - if self.parent is None: - return self - return self.parent.getRoot() - - def getSubChildWithID( self, idReference ): - """Get the child which has the idReference.""" - for child in self.children: - if 'bf:id' in child.attributeDictionary: - if child.attributeDictionary['bf:id'] == idReference: - return child - subChildWithID = child.getSubChildWithID( idReference ) - if subChildWithID is not None: - return subChildWithID - return None - - def getTagKeys(self): - """Get stripped tag keys.""" - if 'tags' not in self.attributeDictionary: - return [] - tagKeys = [] - tagString = self.attributeDictionary['tags'] - if tagString.startswith('='): - tagString = tagString[1 :] - if tagString.startswith('['): - tagString = tagString[1 :] - if tagString.endswith(']'): - tagString = tagString[: -1] - for tagWord in tagString.split(','): - tagKey = tagWord.strip() - if tagKey != '': - tagKeys.append(tagKey) - return tagKeys - - def getValueByKey( self, key ): - """Get value by the key.""" - if key in evaluate.globalElementValueDictionary: - return evaluate.globalElementValueDictionary[key](self) - if key in self.attributeDictionary: - return evaluate.getEvaluatedLinkValue( self.attributeDictionary[key], self ) - return None - - def getVertexes(self): - """Get the vertexes.""" - if self.xmlObject is None: - return [] - return self.xmlObject.getVertexes() - - def getXMLElementByID(self, idKey): - """Get the xml element by id.""" - idDictionary = self.getRoot().idDictionary - if idKey in idDictionary: - return idDictionary[idKey] - return None - - def getXMLElementByImportID(self, idKey): - """Get the xml element by import file name and id.""" - return self.getXMLElementByID( self.getImportNameWithDot() + idKey ) - - def getXMLElementsByImportName(self, name): - """Get the xml element by import file name and name.""" - return self.getXMLElementsByName( self.getImportNameWithDot() + name ) - - def getXMLElementsByName(self, name): - """Get the xml elements by name.""" - nameDictionary = self.getRoot().nameDictionary - if name in nameDictionary: - return nameDictionary[name] - return None - - def getXMLElementsByTag(self, tag): - """Get the xml elements by tag.""" - tagDictionary = self.getRoot().tagDictionary - if tag in tagDictionary: - return tagDictionary[tag] - return None - - def getXMLProcessor(self): - """Get the xmlProcessor.""" - return self.getRoot().xmlProcessor - - def linkObject(self, xmlObject): - """Link self to xmlObject and add xmlObject to archivableObjects.""" - self.xmlObject = xmlObject - self.xmlObject.xmlElement = self - self.parent.xmlObject.archivableObjects.append(self.xmlObject) - - def printAllVariables(self): - """Print all variables.""" - print('attributeDictionary') - print(self.attributeDictionary) - print('children') - print(self.children) - print('className') - print(self.className) - print('idDictionary') - print(self.idDictionary) - print('importName') - print(self.importName) - print('nameDictionary') - print(self.nameDictionary) - print('parent') - print(self.parent) - print('tagDictionary') - print(self.tagDictionary) - print('text') - print(self.text) - print('xmlObject') - print(self.xmlObject) - print('') - - def printAllVariablesRoot(self): - """Print all variables and the root variables.""" - self.printAllVariables() - root = self.getRoot() - if root is not None and root != self: - print('') - print('Root variables:') - root.printAllVariables() - - def removeChildrenFromIDNameParent(self): - """Remove the children from the id and name dictionaries and the children list.""" - childrenCopy = self.children[:] - for child in childrenCopy: - child.removeFromIDNameParent() - - def removeFromIDNameParent(self): - """Remove this from the id and name dictionaries and the children of the parent.""" - self.removeChildrenFromIDNameParent() - if 'id' in self.attributeDictionary: - idDictionary = self.getRoot().idDictionary - idKey = self.getImportNameWithDot() + self.attributeDictionary['id'] - if idKey in idDictionary: - del idDictionary[idKey] - if 'name' in self.attributeDictionary: - nameDictionary = self.getRoot().nameDictionary - nameKey = self.getImportNameWithDot() + self.attributeDictionary['name'] - euclidean.removeElementFromListTable(self, nameKey, nameDictionary) - for tagKey in self.getTagKeys(): - euclidean.removeElementFromListTable(self, tagKey, self.getRoot().tagDictionary) - if self.parent is not None: - self.parent.children.remove(self) - - def setParentAddToChildren(self, parent): - """Set the parent and add this to its children.""" - self.parent = parent - if self.parent is not None: - self.parent.children.append(self) - - -class XMLSimpleReader: - """A simple xml parser.""" - def __init__(self, fileName, parent, xmlText): - """Add empty lists.""" - self.beforeRoot = '' - self.fileName = fileName - self.isXML = False - self.numberOfWarnings = 0 - self.parent = parent - self.root = None - if parent is not None: - self.root = parent.getRoot() - self.lines = getXMLLines(xmlText) - for self.lineIndex, line in enumerate(self.lines): - self.parseLine(line) - self.xmlText = xmlText - - def __repr__(self): - """Get the string representation of this parser.""" - return str( self.root ) - - def getOriginalRoot(self): - """Get the original reparsed root element.""" - if evaluate.getEvaluatedBoolean(True, 'getOriginalRoot', self.root): - return XMLSimpleReader(self.fileName, self.parent, self.xmlText).root - return None - - def getRoot(self): - """Get the root element.""" - return self.root - - def parseLine(self, line): - """Parse an xml line and add it to the xml tree.""" - lineStripped = line.strip() - if len( lineStripped ) < 1: - return - if lineStripped.startswith('\nArt of Illusion ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addBeginEndInnerXMLTag( attributeDictionary, className, depth, innerText, output, text=''): - """Add the begin and end xml tag and the inner text if any.""" - if len( innerText ) > 0: - addBeginXMLTag( attributeDictionary, className, depth, output, text ) - output.write( innerText ) - addEndXMLTag( className, depth, output ) - else: - addClosedXMLTag( attributeDictionary, className, depth, output, text ) - -def addBeginXMLTag( attributeDictionary, className, depth, output, text=''): - """Add the begin xml tag.""" - depthStart = '\t' * depth - output.write('%s<%s%s>%s\n' % ( depthStart, className, getAttributeDictionaryString(attributeDictionary), text ) ) - -def addClosedXMLTag( attributeDictionary, className, depth, output, text=''): - """Add the closed xml tag.""" - depthStart = '\t' * depth - attributeDictionaryString = getAttributeDictionaryString(attributeDictionary) - if len(text) > 0: - output.write('%s<%s%s >%s\n' % ( depthStart, className, attributeDictionaryString, text, className ) ) - else: - output.write('%s<%s%s />\n' % ( depthStart, className, attributeDictionaryString ) ) - -def addEndXMLTag( className, depth, output ): - """Add the end xml tag.""" - depthStart = '\t' * depth - output.write('%s\n' % ( depthStart, className ) ) - -def addXMLFromLoopComplexZ( attributeDictionary, depth, loop, output, z ): - """Add xml from loop.""" - addBeginXMLTag( attributeDictionary, 'path', depth, output ) - for pointComplexIndex in xrange(len(loop)): - pointComplex = loop[ pointComplexIndex ] - addXMLFromXYZ( depth + 1, pointComplexIndex, output, pointComplex.real, pointComplex.imag, z ) - addEndXMLTag('path', depth, output ) - -def addXMLFromObjects( depth, objects, output ): - """Add xml from objects.""" - for object in objects: - object.addXML(depth, output) - -def addXMLFromVertexes( depth, output, vertexes ): - """Add xml from loop.""" - for vertexIndex in xrange(len(vertexes)): - vertex = vertexes[vertexIndex] - addXMLFromXYZ( depth + 1, vertexIndex, output, vertex.x, vertex.y, vertex.z ) - -def addXMLFromXYZ( depth, index, output, x, y, z ): - """Add xml from x, y & z.""" - attributeDictionary = { 'index' : str( index ) } - if x != 0.0: - attributeDictionary['x'] = str(x) - if y != 0.0: - attributeDictionary['y'] = str(y) - if z != 0.0: - attributeDictionary['z'] = str(z) - addClosedXMLTag( attributeDictionary, 'vertex', depth, output ) - -def compareAttributeKeyAscending(key, otherKey): - """Get comparison in order to sort attribute keys in ascending order, with the id key first and name second.""" - if key == 'id': - return - 1 - if otherKey == 'id': - return 1 - if key == 'name': - return - 1 - if otherKey == 'name': - return 1 - if key < otherKey: - return - 1 - return int(key > otherKey) - -def getAttributeDictionaryString(attributeDictionary): - """Add the closed xml tag.""" - attributeDictionaryString = '' - attributeDictionaryKeys = attributeDictionary.keys() - attributeDictionaryKeys.sort( compareAttributeKeyAscending ) - for attributeDictionaryKey in attributeDictionaryKeys: - valueString = str(attributeDictionary[attributeDictionaryKey]) - if "'" in valueString: - attributeDictionaryString += ' %s="%s"' % (attributeDictionaryKey, valueString) - else: - attributeDictionaryString += " %s='%s'" % (attributeDictionaryKey, valueString) - return attributeDictionaryString - -def getBeforeRootOutput(xmlParser): - """Get the output before the root and the root xml.""" - output = cStringIO.StringIO() - output.write(xmlParser.beforeRoot) - xmlParser.getRoot().addXML(0, output) - return output.getvalue() - -def getBeginGeometryXMLOutput(xmlElement=None): - """Get the beginning of the string representation of this boolean geometry object info.""" - output = getBeginXMLOutput() - attributeDictionary = {} - if xmlElement is not None: - root = xmlElement.getRoot() - attributeDictionary = root.attributeDictionary -# attributeDictionary['version'] = '10.11.30' - addBeginXMLTag( attributeDictionary, 'fabmetheus', 0, output ) - return output - -def getBeginXMLOutput(): - """Get the beginning of the string representation of this object info.""" - output = cStringIO.StringIO() - output.write("\n") - return output - -def getDictionaryWithoutList( dictionary, withoutList ): - """Get the dictionary without the keys in the list.""" - dictionaryWithoutList = {} - for key in dictionary: - if key not in withoutList: - dictionaryWithoutList[key] = dictionary[key] - return dictionaryWithoutList - -def getEndGeometryXMLString(output): - """Get the string representation of this object info.""" - addEndXMLTag('fabmetheus', 0, output ) - return output.getvalue() diff --git a/skeinforge/models/Screw Holder Bottom.stl b/skeinforge/models/Screw Holder Bottom.stl deleted file mode 100644 index f372a18..0000000 --- a/skeinforge/models/Screw Holder Bottom.stl +++ /dev/null @@ -1,2886 +0,0 @@ -solid "Screw_Holder_Bottom"; Produced by Art of Illusion 2.4, Fri Oct 16 16:42:04 PDT 2009 -facet normal 0 -0.831469612304 0.555570233017 - outer loop - vertex 54.002309837942 24.804173569059 0.110046151702 - vertex 48.011309837942 24.804173569059 0.110046151702 - vertex 54.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 24.730643081307 0 - vertex 14.883210818105 25.830303993361 0 - vertex 15.262563132924 25.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 60 23 0 - vertex 54.002309837942 24.730643081307 0 - vertex 60 40 0 - endloop -endfacet -facet normal 0 0.831469612301 0.555570233022 - outer loop - vertex 54.002309837942 15.269356918694 0 - vertex 48.011309837942 15.269356918694 0 - vertex 54.002309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.464705848856 10 0 - vertex 15.830303993361 11.883210818105 0 - vertex 16.5 11.75 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 30 0 - vertex 43.737436867076 27.737436867076 0 - vertex 43.169696006639 28.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 43.169696006639 15.116789181895 0 - vertex 42.5 15.25 0 - vertex 41.422110817733 17 0 - endloop -endfacet -facet normal 0 -0.831469612304 0.555570233017 - outer loop - vertex 48.011309837942 24.730643081307 0 - vertex 54.002309837942 24.730643081307 0 - vertex 48.011309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 30 0 - vertex 43.169696006639 28.116789181895 0 - vertex 42.5 28.25 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 60 40 0 - vertex 52 30 0 - vertex 52 40 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.883210818105 14.169696006639 0 - vertex 14.75 13.5 0 - vertex 12.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.883210818105 27.169696006639 0 - vertex 14.042553191489 30 0 - vertex 15.262563132924 27.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.464705848856 10 0 - vertex 16.5 11.75 0 - vertex 17.169696006639 11.883210818105 0 - endloop -endfacet -facet normal 0 0.831469612301 0.555570233022 - outer loop - vertex 48.011309837942 15.195826430941 0.110046151702 - vertex 54.002309837942 15.195826430941 0.110046151702 - vertex 48.011309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.042553191489 30 0 - vertex 17.169696006639 28.116789181895 0 - vertex 16.5 28.25 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 15.269356918694 0 - vertex 14.75 13.5 0 - vertex 14.883210818105 12.830303993361 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 54.002309837942 17 0 - vertex 60 17 0 - vertex 54.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 10 0 - vertex 42.5 11.75 0 - vertex 43.169696006639 11.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 15.269356918694 0 - vertex 15.262563132924 14.737436867076 0 - vertex 14.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 10 0 - vertex 14.464705848856 10 0 - vertex 42.5 11.75 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.042553191489 30 0 - vertex 15.830303993361 28.116789181895 0 - vertex 15.262563132924 27.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.464705848856 10 0 - vertex 15.262563132924 12.262563132924 0 - vertex 15.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.042553191489 30 0 - vertex 16.5 28.25 0 - vertex 15.830303993361 28.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 54.002309837942 24.730643081307 0 - vertex 60 23 0 - vertex 54.002309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 23 0 - vertex 16.5 24.75 0 - vertex 17.169696006639 24.883210818105 0 - endloop -endfacet -facet normal 0 0.831469612301 0.555570233022 - outer loop - vertex 6.011309837942 15.269356918694 0 - vertex 6.011309837942 15.195826430941 0.110046151702 - vertex 12.002309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.75 26.5 0 - vertex 12.002309837942 24.730643081307 0 - vertex 14.883210818105 27.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 30 0 - vertex 60 40 0 - vertex 54.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.422110817733 17 0 - vertex 48.011309837942 17 0 - vertex 43.169696006639 15.116789181895 0 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 14.75 13.5 0 - vertex 14.883210818105 12.830303993361 0.77775 - vertex 14.883210818105 12.830303993361 0 - endloop -endfacet -facet normal -0 -0 -1 - outer loop - vertex 6.011309837942 17 0 - vertex 6.011309837942 15.269356918694 0 - vertex 0 17 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.422110817733 17 0 - vertex 41.830303993361 15.116789181895 0 - vertex 41.262563132924 14.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.169696006639 11.883210818105 0 - vertex 17.737436867076 12.262563132924 0 - vertex 41.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 6.011309837942 15.269356918694 0 - vertex 0 10 0 - vertex 0 17 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.883210818105 25.830303993361 0 - vertex 12.002309837942 24.730643081307 0 - vertex 14.75 26.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 24.730643081307 0 - vertex 52 30 0 - vertex 54.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 17 0 - vertex 43.737436867076 14.737436867076 0 - vertex 43.169696006639 15.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 42.5 15.25 0 - vertex 41.830303993361 15.116789181895 0 - vertex 41.422110817733 17 0 - endloop -endfacet -facet normal -0 -0 -1 - outer loop - vertex 12.002309837942 15.269356918694 0 - vertex 14.883210818105 12.830303993361 0 - vertex 6.011309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 0 23 0 - vertex 0 30 0 - vertex 6.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0.831469612301 0.555570233022 - outer loop - vertex 12.002309837942 15.269356918694 0 - vertex 6.011309837942 15.269356918694 0 - vertex 12.002309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 54.002309837942 15.269356918694 0 - vertex 60 17 0 - vertex 52 10 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 6.011309837942 23 0 - vertex 0 23 0 - vertex 6.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 14.169696006639 0 - vertex 48.011309837942 15.269356918694 0 - vertex 44.25 13.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.116789181895 27.169696006639 0 - vertex 41.262563132924 25.262563132924 0 - vertex 18.25 26.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.116789181895 25.830303993361 0 - vertex 18.25 26.5 0 - vertex 41.830303993361 24.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.737436867076 14.737436867076 0 - vertex 41.262563132924 14.737436867076 0 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal -0 -0 -1 - outer loop - vertex 41.262563132924 25.262563132924 0 - vertex 41.830303993361 24.883210818105 0 - vertex 18.25 26.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.737436867076 25.262563132924 0 - vertex 18.116789181895 25.830303993361 0 - vertex 41.830303993361 24.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.737436867076 12.262563132924 0 - vertex 18.116789181895 12.830303993361 0 - vertex 40.883210818105 12.830303993361 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.737436867076 12.262563132924 0 - vertex 41.262563132924 12.262563132924 0 - vertex 41.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.262563132924 27.737436867076 0 - vertex 17.169696006639 28.116789181895 0 - vertex 41.830303993361 28.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 42.5 11.75 0 - vertex 14.464705848856 10 0 - vertex 17.169696006639 11.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.25 26.5 0 - vertex 44.116789181895 27.169696006639 0 - vertex 48.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 40.883210818105 12.830303993361 0 - vertex 41.262563132924 12.262563132924 0 - vertex 17.737436867076 12.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.169696006639 24.883210818105 0 - vertex 17.737436867076 25.262563132924 0 - vertex 41.830303993361 24.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 12.830303993361 0 - vertex 44.25 13.5 0 - vertex 48.011309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.116789181895 12.830303993361 0 - vertex 40.75 13.5 0 - vertex 40.883210818105 12.830303993361 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.25 13.5 0 - vertex 18.116789181895 14.169696006639 0 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.262563132924 14.737436867076 0 - vertex 17.737436867076 14.737436867076 0 - vertex 17.169696006639 15.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.116789181895 14.169696006639 0 - vertex 17.737436867076 14.737436867076 0 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 25.830303993361 0 - vertex 44.25 26.5 0 - vertex 48.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 14.883210818105 14.169696006639 0.77775 - vertex 14.75 13.5 0.77775 - vertex 14.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 14.75 13.5 0.77775 - vertex 14.75 13.5 0 - vertex 14.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 41.830303993361 28.116789181895 0 - vertex 42.5 28.25 0.77775 - vertex 41.830303993361 28.116789181895 0.77775 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 15.830303993361 24.883210818105 0.77775 - vertex 15.830303993361 24.883210818105 0 - vertex 15.262563132924 25.262563132924 0 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 16.5 28.25 0 - vertex 17.169696006639 28.116789181895 0.77775 - vertex 16.5 28.25 0.77775 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 43.169696006639 24.883210818105 0 - vertex 42.5 24.75 0.77775 - vertex 43.169696006639 24.883210818105 0.77775 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 16.5 28.25 0.77775 - vertex 15.830303993361 28.116789181895 0.77775 - vertex 16.5 28.25 0 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 15.830303993361 28.116789181895 0.77775 - vertex 15.830303993361 28.116789181895 0 - vertex 16.5 28.25 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 0 23 0 - vertex 6.011309837942 23 0.77775 - vertex 0 23 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 60 0 0.77775 - vertex 52 10 0.77775 - vertex 52 0 0.77775 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 40.883210818105 27.169696006639 0 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 40.75 26.5 0 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 17.169696006639 24.883210818105 0.77775 - vertex 17.169696006639 24.883210818105 0 - vertex 16.5 24.75 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 52 0 0 - vertex 52 0 0.77775 - vertex 52 10 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 34.416922535211 17 0.77775 - vertex 40.883210818105 12.830303993361 0.77775 - vertex 40.75 13.5 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 12.002309837942 24.936988122232 0.77775 - vertex 12.002309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 42.5 24.75 0 - vertex 41.830303993361 24.883210818105 0.77775 - vertex 42.5 24.75 0.77775 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 60 0 0 - vertex 60 0 0.77775 - vertex 52 0 0 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 15.830303993361 28.116789181895 0.77775 - vertex 15.262563132924 27.737436867076 0.77775 - vertex 15.830303993361 28.116789181895 0 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 15.262563132924 27.737436867076 0.77775 - vertex 15.262563132924 27.737436867076 0 - vertex 15.830303993361 28.116789181895 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 6.011309837942 17 0.77775 - vertex 6.011309837942 17 0 - vertex 0 17 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 17 0 - vertex 48.011309837942 17 0.77775 - vertex 48.011309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 0 - outer loop - vertex 18.25 26.5 0 - vertex 18.25 26.5 0.77775 - vertex 18.116789181895 27.169696006639 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.262563132924 14.737436867076 0.77775 - vertex 15.830303993361 15.116789181895 0.77775 - vertex 15.455907969142 17 0.77775 - endloop -endfacet -facet normal 0 0.980785280403 0.195090322015 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 54.002309837942 15.195826430941 0.110046151702 - vertex 48.011309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 0 - outer loop - vertex 44.25 26.5 0 - vertex 44.25 26.5 0.77775 - vertex 44.116789181895 27.169696006639 0.77775 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 52 10 0 - vertex 15.306548743796 10 0.77775 - vertex 14.464705848856 10 0 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 40.75 26.5 0.77775 - vertex 40.883210818105 25.830303993361 0 - vertex 40.75 26.5 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 15.063011877768 0.77775 - vertex 48.011309837942 15.195826430941 0.110046151702 - vertex 48.011309837942 15.269356918694 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 44.116789181895 27.169696006639 0.77775 - vertex 43.737436867076 27.737436867076 0.77775 - vertex 44.116789181895 27.169696006639 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 43.737436867076 27.737436867076 0.77775 - vertex 43.737436867076 27.737436867076 0 - vertex 44.116789181895 27.169696006639 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 52 10 0 - vertex 52 10 0.77775 - vertex 15.306548743796 10 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 23 0.77775 - vertex 6.011309837942 23 0 - vertex 6.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 34.416922535211 17 0.77775 - vertex 40.883210818105 14.169696006639 0.77775 - vertex 41.262563132924 14.737436867076 0.77775 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 14.75 26.5 0 - vertex 14.883210818105 25.830303993361 0.77775 - vertex 14.883210818105 25.830303993361 0 - endloop -endfacet -facet normal 0 -0.980785280403 0.195090322015 - outer loop - vertex 6.011309837942 24.936988122232 0.77775 - vertex 6.011309837942 24.804173569059 0.110046151702 - vertex 12.002309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 18.116789181895 14.169696006639 0.77775 - vertex 17.737436867076 14.737436867076 0.77775 - vertex 18.116789181895 14.169696006639 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 17.737436867076 14.737436867076 0.77775 - vertex 17.737436867076 14.737436867076 0 - vertex 18.116789181895 14.169696006639 0 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 42.5 15.25 0.77775 - vertex 41.830303993361 15.116789181895 0.77775 - vertex 42.5 15.25 0 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 41.830303993361 15.116789181895 0.77775 - vertex 41.830303993361 15.116789181895 0 - vertex 42.5 15.25 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 15.262563132924 14.737436867076 0.77775 - vertex 14.883210818105 14.169696006639 0.77775 - vertex 15.262563132924 14.737436867076 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 14.883210818105 14.169696006639 0.77775 - vertex 14.883210818105 14.169696006639 0 - vertex 15.262563132924 14.737436867076 0 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 0 - outer loop - vertex 43.169696006639 15.116789181895 0 - vertex 43.737436867076 14.737436867076 0.77775 - vertex 43.169696006639 15.116789181895 0.77775 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 14.75 13.5 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - vertex 14.75 13.5 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 41.262563132924 14.737436867076 0.77775 - vertex 40.883210818105 14.169696006639 0.77775 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 42.5 11.75 0.77775 - vertex 43.169696006639 11.883210818105 0.77775 - vertex 43.169696006639 11.883210818105 0 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 -0 - outer loop - vertex 17.169696006639 15.116789181895 0.77775 - vertex 17.169696006639 15.116789181895 0 - vertex 17.737436867076 14.737436867076 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 12.002309837942 24.730643081307 0 - vertex 12.002309837942 23 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 6.011309837942 23 0.77775 - vertex 0 23 0 - vertex 6.011309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 25.830303993361 0 - vertex 48.011309837942 23 0 - vertex 43.737436867076 25.262563132924 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 15.195826430941 0.110046151702 - vertex 12.002309837942 17 0.77775 - vertex 12.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 0 10 0 - vertex 6.011309837942 15.269356918694 0 - vertex 14.883210818105 12.830303993361 0 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 -0 - outer loop - vertex 17.169696006639 28.116789181895 0.77775 - vertex 16.5 28.25 0 - vertex 17.169696006639 28.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 24.730643081307 0 - vertex 44.116789181895 27.169696006639 0 - vertex 43.737436867076 27.737436867076 0 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 44.25 26.5 0.77775 - vertex 44.25 26.5 0 - vertex 44.116789181895 25.830303993361 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 40.75 26.5 0.77775 - vertex 37.474084379442 23 0.77775 - vertex 40.883210818105 25.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 34.416922535211 17 0.77775 - vertex 40.75 13.5 0.77775 - vertex 40.883210818105 14.169696006639 0.77775 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 17.169696006639 11.883210818105 0.77775 - vertex 17.169696006639 11.883210818105 0 - vertex 16.5 11.75 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 43.737436867076 27.737436867076 0.77775 - vertex 52 30 0.77775 - vertex 41.866228156844 30 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 12.002309837942 15.063011877768 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - vertex 14.75 13.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 48.011309837942 15.063011877768 0.77775 - vertex 52 10 0.77775 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 41.830303993361 24.883210818105 0.77775 - vertex 42.5 24.75 0 - vertex 41.830303993361 24.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 6.011309837942 24.730643081307 0 - vertex 14.883210818105 27.169696006639 0 - vertex 12.002309837942 24.730643081307 0 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 -0 - outer loop - vertex 43.737436867076 14.737436867076 0.77775 - vertex 43.169696006639 15.116789181895 0 - vertex 43.737436867076 14.737436867076 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 43.737436867076 27.737436867076 0.77775 - vertex 41.866228156844 30 0.77775 - vertex 43.169696006639 28.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 34.416922535211 17 0.77775 - vertex 41.830303993361 15.116789181895 0.77775 - vertex 42.5 15.25 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 16.5 11.75 0.77775 - vertex 15.830303993361 11.883210818105 0.77775 - vertex 15.306548743796 10 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 0 23 0.77775 - vertex 0 30 0 - vertex 0 23 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 0 30 0 - vertex 0 23 0.77775 - vertex 0 30 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 52 10 0 - vertex 52 0 0.77775 - vertex 52 10 0.77775 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 17.169696006639 11.883210818105 0 - vertex 17.169696006639 11.883210818105 0.77775 - vertex 17.737436867076 12.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 43.169696006639 28.116789181895 0.77775 - vertex 41.866228156844 30 0.77775 - vertex 42.5 28.25 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 14.042553191489 30 0 - vertex 41.866228156844 30 0.77775 - vertex 52 30 0 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 41.830303993361 11.883210818105 0.77775 - vertex 42.5 11.75 0 - vertex 41.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 15.262563132924 12.262563132924 0.77775 - vertex 15.830303993361 11.883210818105 0 - vertex 15.262563132924 12.262563132924 0 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 40.883210818105 25.830303993361 0 - vertex 40.75 26.5 0.77775 - vertex 40.883210818105 25.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.116789181895 27.169696006639 0 - vertex 40.883210818105 25.830303993361 0 - vertex 41.262563132924 25.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 42.5 28.25 0 - vertex 17.169696006639 28.116789181895 0 - vertex 14.042553191489 30 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 15.262563132924 27.737436867076 0.77775 - vertex 15.830303993361 28.116789181895 0.77775 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 14.883210818105 25.830303993361 0.77775 - vertex 15.262563132924 25.262563132924 0.77775 - vertex 14.883210818105 25.830303993361 0 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 15.262563132924 25.262563132924 0.77775 - vertex 15.262563132924 25.262563132924 0 - vertex 14.883210818105 25.830303993361 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 24.804173569059 0.110046151702 - vertex 48.011309837942 23 0.77775 - vertex 48.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 24.730643081307 0 - vertex 43.737436867076 27.737436867076 0 - vertex 52 30 0 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 18.116789181895 25.830303993361 0 - vertex 18.116789181895 25.830303993361 0.77775 - vertex 18.25 26.5 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 15.195826430941 0.110046151702 - vertex 54.002309837942 15.063011877768 0.77775 - vertex 54.002309837942 17 0.77775 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 41.830303993361 15.116789181895 0 - vertex 41.830303993361 15.116789181895 0.77775 - vertex 41.262563132924 14.737436867076 0.77775 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 -0 - outer loop - vertex 43.737436867076 27.737436867076 0.77775 - vertex 43.169696006639 28.116789181895 0.77775 - vertex 43.737436867076 27.737436867076 0 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 -0 - outer loop - vertex 43.169696006639 28.116789181895 0.77775 - vertex 43.169696006639 28.116789181895 0 - vertex 43.737436867076 27.737436867076 0 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 41.830303993361 11.883210818105 0.77775 - vertex 42.5 11.75 0.77775 - vertex 42.5 11.75 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 15.830303993361 24.883210818105 0.77775 - vertex 15.262563132924 25.262563132924 0.77775 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 41.262563132924 14.737436867076 0.77775 - vertex 41.262563132924 14.737436867076 0 - vertex 41.830303993361 15.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 60 17 0 - vertex 60 0 0 - vertex 52 0 0 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 15.262563132924 25.262563132924 0 - vertex 15.262563132924 25.262563132924 0.77775 - vertex 15.830303993361 24.883210818105 0.77775 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 12.002309837942 23 0 - vertex 17.379510917074 23 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 24.936988122232 0.77775 - vertex 6.011309837942 23 0.77775 - vertex 6.011309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.169696006639 11.883210818105 0 - vertex 41.830303993361 11.883210818105 0 - vertex 42.5 11.75 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 42.5 28.25 0 - vertex 14.042553191489 30 0 - vertex 52 30 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 17 0.77775 - vertex 43.169696006639 15.116789181895 0.77775 - vertex 43.737436867076 14.737436867076 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 15.269356918694 0 - vertex 6.011309837942 17 0.77775 - vertex 6.011309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 -0 - outer loop - vertex 18.116789181895 27.169696006639 0.77775 - vertex 18.116789181895 27.169696006639 0 - vertex 18.25 26.5 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 40.75 26.5 0 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 40.75 26.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 0 30 0.77775 - vertex 14.883210818105 27.169696006639 0.77775 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 42.5 11.75 0.77775 - vertex 43.169696006639 11.883210818105 0 - vertex 42.5 11.75 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 15.830303993361 28.116789181895 0.77775 - vertex 16.5 28.25 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 52 30 0.77775 - vertex 52 30 0 - vertex 41.866228156844 30 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 60 17 0 - vertex 52 0 0 - vertex 52 10 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 0 - outer loop - vertex 44.116789181895 14.169696006639 0.77775 - vertex 43.737436867076 14.737436867076 0.77775 - vertex 43.737436867076 14.737436867076 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 41.866228156844 30 0.77775 - vertex 14.042553191489 30 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.169696006639 11.883210818105 0.77775 - vertex 15.306548743796 10 0.77775 - vertex 17.737436867076 12.262563132924 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 15.269356918694 0 - vertex 12.002309837942 17 0.77775 - vertex 12.002309837942 17 0 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 17.169696006639 24.883210818105 0.77775 - vertex 16.5 24.75 0 - vertex 16.5 24.75 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 23 0.77775 - vertex 43.169696006639 24.883210818105 0.77775 - vertex 42.5 24.75 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 6.011309837942 17 0.77775 - vertex 0 17 0 - vertex 0 17 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 16.5 28.25 0.77775 - vertex 17.169696006639 28.116789181895 0.77775 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 18.116789181895 25.830303993361 0.77775 - vertex 17.737436867076 25.262563132924 0 - vertex 17.737436867076 25.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 16.5 24.75 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 17.169696006639 24.883210818105 0.77775 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 -0 - outer loop - vertex 44.116789181895 27.169696006639 0.77775 - vertex 44.116789181895 27.169696006639 0 - vertex 44.25 26.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 40.75 13.5 0 - vertex 18.25 13.5 0 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 25.830303993361 0 - vertex 48.011309837942 24.730643081307 0 - vertex 48.011309837942 23 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 0 10 0.77775 - vertex 0 10 0 - vertex 14.464705848856 10 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.306548743796 10 0.77775 - vertex 15.830303993361 11.883210818105 0.77775 - vertex 15.262563132924 12.262563132924 0.77775 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 43.169696006639 28.116789181895 0 - vertex 43.169696006639 28.116789181895 0.77775 - vertex 42.5 28.25 0.77775 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 17.169696006639 11.883210818105 0.77775 - vertex 16.5 11.75 0 - vertex 16.5 11.75 0.77775 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 0 - outer loop - vertex 18.25 13.5 0.77775 - vertex 18.116789181895 14.169696006639 0.77775 - vertex 18.116789181895 14.169696006639 0 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 17.169696006639 24.883210818105 0.77775 - vertex 17.737436867076 25.262563132924 0 - vertex 17.169696006639 24.883210818105 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 0 10 0.77775 - vertex 14.464705848856 10 0 - vertex 15.306548743796 10 0.77775 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 0 - outer loop - vertex 17.169696006639 15.116789181895 0.77775 - vertex 17.737436867076 14.737436867076 0 - vertex 17.737436867076 14.737436867076 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 23 0.77775 - vertex 48.011309837942 24.804173569059 0.110046151702 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.830303993361 28.116789181895 0.77775 - vertex 41.866228156844 30 0.77775 - vertex 41.262563132924 27.737436867076 0.77775 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 16.5 11.75 0.77775 - vertex 15.830303993361 11.883210818105 0 - vertex 15.830303993361 11.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.75 26.5 0.77775 - vertex 12.002309837942 24.936988122232 0.77775 - vertex 14.883210818105 25.830303993361 0.77775 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 44.116789181895 14.169696006639 0.77775 - vertex 43.737436867076 14.737436867076 0 - vertex 44.116789181895 14.169696006639 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 12.002309837942 24.804173569059 0.110046151702 - vertex 12.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 60 17 0.77775 - vertex 54.002309837942 17 0.77775 - endloop -endfacet -facet normal 0 0.980785280403 0.195090322015 - outer loop - vertex 6.011309837942 15.063011877768 0.77775 - vertex 12.002309837942 15.195826430941 0.110046151702 - vertex 6.011309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 15.830303993361 24.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.830303993361 24.883210818105 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 16.5 24.75 0.77775 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 18.25 26.5 0.77775 - vertex 18.25 26.5 0 - vertex 18.116789181895 25.830303993361 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.262563132924 25.262563132924 0.77775 - vertex 37.474084379442 23 0.77775 - vertex 41.830303993361 24.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 14.883210818105 27.169696006639 0.77775 - vertex 15.262563132924 27.737436867076 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 14.737436867076 0.77775 - vertex 15.455907969142 17 0.77775 - vertex 17.169696006639 15.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 14.737436867076 0.77775 - vertex 34.416922535211 17 0.77775 - vertex 15.455907969142 17 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.306548743796 10 0.77775 - vertex 15.262563132924 12.262563132924 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 17.169696006639 24.883210818105 0.77775 - vertex 17.737436867076 25.262563132924 0.77775 - vertex 17.737436867076 25.262563132924 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 16.5 15.25 0.77775 - vertex 15.455907969142 17 0.77775 - vertex 15.830303993361 15.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.830303993361 28.116789181895 0.77775 - vertex 42.5 28.25 0.77775 - vertex 41.866228156844 30 0.77775 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 18.116789181895 12.830303993361 0.77775 - vertex 18.25 13.5 0.77775 - vertex 18.25 13.5 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 60 17 0.77775 - vertex 60 17 0 - vertex 54.002309837942 17 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 15.455907969142 17 0.77775 - vertex 12.002309837942 17 0 - vertex 12.002309837942 17 0.77775 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 43.169696006639 11.883210818105 0 - vertex 43.737436867076 12.262563132924 0.77775 - vertex 43.737436867076 12.262563132924 0 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 43.169696006639 11.883210818105 0 - vertex 43.169696006639 11.883210818105 0.77775 - vertex 43.737436867076 12.262563132924 0.77775 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 -0 - outer loop - vertex 18.25 13.5 0.77775 - vertex 18.116789181895 14.169696006639 0 - vertex 18.25 13.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 42.5 28.25 0 - vertex 41.830303993361 28.116789181895 0 - vertex 17.169696006639 28.116789181895 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 23 0.77775 - vertex 48.011309837942 23 0 - vertex 48.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.169696006639 15.116789181895 0.77775 - vertex 15.455907969142 17 0.77775 - vertex 16.5 15.25 0.77775 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 17.737436867076 12.262563132924 0.77775 - vertex 17.737436867076 12.262563132924 0 - vertex 17.169696006639 11.883210818105 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 52 40 0.77775 - vertex 60 23 0.77775 - vertex 60 40 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 40.75 13.5 0 - vertex 18.116789181895 12.830303993361 0 - vertex 18.25 13.5 0 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 43.169696006639 28.116789181895 0 - vertex 42.5 28.25 0.77775 - vertex 42.5 28.25 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 23 0 - vertex 12.002309837942 23 0 - vertex 42.5 24.75 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 23 0.77775 - vertex 60 23 0.77775 - vertex 54.002309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 23 0.77775 - vertex 6.011309837942 24.730643081307 0 - vertex 6.011309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 17.169696006639 15.116789181895 0 - vertex 16.5 15.25 0.77775 - vertex 16.5 15.25 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 17 0.77775 - vertex 6.011309837942 15.063011877768 0.77775 - vertex 6.011309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 60 17 0.77775 - vertex 60 0 0 - vertex 60 17 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 60 0 0.77775 - vertex 60 0 0 - vertex 60 17 0.77775 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 15.262563132924 12.262563132924 0.77775 - vertex 15.830303993361 11.883210818105 0.77775 - vertex 15.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 52 10 0.77775 - vertex 44.116789181895 12.830303993361 0.77775 - vertex 43.737436867076 12.262563132924 0.77775 - endloop -endfacet -facet normal 0 0.980785280403 0.195090322015 - outer loop - vertex 6.011309837942 15.063011877768 0.77775 - vertex 12.002309837942 15.063011877768 0.77775 - vertex 12.002309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.169696006639 24.883210818105 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 17.737436867076 25.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 52 10 0.77775 - vertex 43.737436867076 12.262563132924 0.77775 - vertex 43.169696006639 11.883210818105 0.77775 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 42.5 28.25 0.77775 - vertex 41.830303993361 28.116789181895 0 - vertex 42.5 28.25 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 15.269356918694 0 - vertex 6.011309837942 17 0 - vertex 6.011309837942 17 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 40.883210818105 25.830303993361 0.77775 - vertex 37.474084379442 23 0.77775 - vertex 41.262563132924 25.262563132924 0.77775 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 18.116789181895 12.830303993361 0.77775 - vertex 18.25 13.5 0 - vertex 18.116789181895 12.830303993361 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 25.262563132924 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 18.116789181895 25.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 34.416922535211 17 0.77775 - vertex 41.262563132924 14.737436867076 0.77775 - vertex 41.830303993361 15.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 0 30 0.77775 - vertex 6.011309837942 24.936988122232 0.77775 - vertex 12.002309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 25.830303993361 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 37.474084379442 23 0.77775 - endloop -endfacet -facet normal 0 -0.980785280403 0.195090322015 - outer loop - vertex 6.011309837942 24.936988122232 0.77775 - vertex 12.002309837942 24.804173569059 0.110046151702 - vertex 12.002309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 52 10 0.77775 - vertex 43.169696006639 11.883210818105 0.77775 - vertex 42.5 11.75 0.77775 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 41.262563132924 14.737436867076 0.77775 - vertex 40.883210818105 14.169696006639 0 - vertex 41.262563132924 14.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 23 0 - vertex 43.169696006639 24.883210818105 0 - vertex 43.737436867076 25.262563132924 0 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 44.25 26.5 0.77775 - vertex 44.116789181895 25.830303993361 0 - vertex 44.116789181895 25.830303993361 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 60 17 0.77775 - vertex 54.002309837942 17 0 - vertex 54.002309837942 17 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 23 0 - vertex 42.5 24.75 0 - vertex 43.169696006639 24.883210818105 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 43.737436867076 27.737436867076 0.77775 - vertex 44.116789181895 27.169696006639 0.77775 - vertex 52 30 0.77775 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 18.116789181895 25.830303993361 0.77775 - vertex 18.116789181895 25.830303993361 0 - vertex 17.737436867076 25.262563132924 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 15.195826430941 0.110046151702 - vertex 54.002309837942 17 0.77775 - vertex 54.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 14.883210818105 27.169696006639 0.77775 - vertex 14.75 26.5 0 - vertex 14.883210818105 27.169696006639 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 52 0 0.77775 - vertex 52 0 0 - vertex 60 0 0.77775 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 14.883210818105 27.169696006639 0.77775 - vertex 14.75 26.5 0.77775 - vertex 14.75 26.5 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 15.269356918694 0 - vertex 54.002309837942 17 0.77775 - vertex 54.002309837942 17 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 16.5 11.75 0.77775 - vertex 15.306548743796 10 0.77775 - vertex 17.169696006639 11.883210818105 0.77775 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 17.169696006639 15.116789181895 0 - vertex 17.169696006639 15.116789181895 0.77775 - vertex 16.5 15.25 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 15.195826430941 0.110046151702 - vertex 12.002309837942 15.063011877768 0.77775 - vertex 12.002309837942 17 0.77775 - endloop -endfacet -facet normal 0 0.980785280403 0.195090322015 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 48.011309837942 15.195826430941 0.110046151702 - vertex 48.011309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 16.5 11.75 0.77775 - vertex 16.5 11.75 0 - vertex 15.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 15.063011877768 0.77775 - vertex 48.011309837942 15.269356918694 0 - vertex 48.011309837942 17 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 24.936988122232 0.77775 - vertex 52 30 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 42.5 24.75 0.77775 - vertex 43.169696006639 24.883210818105 0 - vertex 42.5 24.75 0 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 14.75 26.5 0 - vertex 14.75 26.5 0.77775 - vertex 14.883210818105 25.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 14.169696006639 0 - vertex 43.737436867076 14.737436867076 0 - vertex 48.011309837942 17 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 14.169696006639 0 - vertex 48.011309837942 17 0 - vertex 48.011309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.169696006639 24.883210818105 0 - vertex 41.830303993361 24.883210818105 0 - vertex 42.5 24.75 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.169696006639 24.883210818105 0 - vertex 42.5 24.75 0 - vertex 12.002309837942 23 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 52 40 0 - vertex 52 40 0.77775 - vertex 60 40 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 52 40 0 - vertex 60 40 0.77775 - vertex 60 40 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 0 - outer loop - vertex 18.116789181895 27.169696006639 0.77775 - vertex 17.737436867076 27.737436867076 0.77775 - vertex 17.737436867076 27.737436867076 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 18.116789181895 27.169696006639 0.77775 - vertex 17.737436867076 27.737436867076 0 - vertex 18.116789181895 27.169696006639 0 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 15.830303993361 24.883210818105 0 - vertex 15.830303993361 24.883210818105 0.77775 - vertex 16.5 24.75 0.77775 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 15.830303993361 24.883210818105 0 - vertex 16.5 24.75 0.77775 - vertex 16.5 24.75 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 12.002309837942 24.936988122232 0.77775 - vertex 12.002309837942 23 0.77775 - vertex 15.262563132924 25.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 12.002309837942 24.936988122232 0.77775 - vertex 15.262563132924 25.262563132924 0.77775 - vertex 14.883210818105 25.830303993361 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 60 40 0.77775 - vertex 60 23 0.77775 - vertex 60 23 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 60 40 0.77775 - vertex 60 23 0 - vertex 60 40 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 15.262563132924 27.737436867076 0 - vertex 15.262563132924 27.737436867076 0.77775 - vertex 14.883210818105 27.169696006639 0.77775 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 15.262563132924 27.737436867076 0 - vertex 14.883210818105 27.169696006639 0.77775 - vertex 14.883210818105 27.169696006639 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 37.474084379442 23 0.77775 - vertex 48.011309837942 23 0.77775 - vertex 42.5 24.75 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 37.474084379442 23 0.77775 - vertex 42.5 24.75 0.77775 - vertex 41.830303993361 24.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.262563132924 14.737436867076 0 - vertex 12.002309837942 17 0 - vertex 41.422110817733 17 0 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 43.169696006639 15.116789181895 0.77775 - vertex 42.5 15.25 0.77775 - vertex 42.5 15.25 0 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 -0 - outer loop - vertex 43.169696006639 15.116789181895 0.77775 - vertex 42.5 15.25 0 - vertex 43.169696006639 15.116789181895 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 52 10 0.77775 - vertex 60 0 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 60 0 0.77775 - vertex 60 17 0.77775 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 40.75 13.5 0.77775 - vertex 40.883210818105 12.830303993361 0.77775 - vertex 40.883210818105 12.830303993361 0 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 40.75 13.5 0.77775 - vertex 40.883210818105 12.830303993361 0 - vertex 40.75 13.5 0 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 0 - outer loop - vertex 17.737436867076 27.737436867076 0 - vertex 17.737436867076 27.737436867076 0.77775 - vertex 17.169696006639 28.116789181895 0.77775 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 0 - outer loop - vertex 17.737436867076 27.737436867076 0 - vertex 17.169696006639 28.116789181895 0.77775 - vertex 17.169696006639 28.116789181895 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.883210818105 27.169696006639 0.77775 - vertex 0 30 0.77775 - vertex 12.002309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.883210818105 27.169696006639 0.77775 - vertex 12.002309837942 24.936988122232 0.77775 - vertex 14.75 26.5 0.77775 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 43.737436867076 12.262563132924 0.77775 - vertex 44.116789181895 12.830303993361 0.77775 - vertex 44.116789181895 12.830303993361 0 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 43.737436867076 12.262563132924 0.77775 - vertex 44.116789181895 12.830303993361 0 - vertex 43.737436867076 12.262563132924 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 48.011309837942 23 0 - vertex 48.011309837942 23 0.77775 - vertex 37.474084379442 23 0.77775 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 16.5 15.25 0.77775 - vertex 15.830303993361 15.116789181895 0.77775 - vertex 15.830303993361 15.116789181895 0 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 16.5 15.25 0.77775 - vertex 15.830303993361 15.116789181895 0 - vertex 16.5 15.25 0 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 40.883210818105 12.830303993361 0.77775 - vertex 41.262563132924 12.262563132924 0.77775 - vertex 41.262563132924 12.262563132924 0 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 40.883210818105 12.830303993361 0.77775 - vertex 41.262563132924 12.262563132924 0 - vertex 40.883210818105 12.830303993361 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 17 0 - vertex 16.5 15.25 0 - vertex 15.830303993361 15.116789181895 0 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 43.737436867076 25.262563132924 0 - vertex 43.737436867076 25.262563132924 0.77775 - vertex 44.116789181895 25.830303993361 0.77775 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 43.737436867076 25.262563132924 0 - vertex 44.116789181895 25.830303993361 0.77775 - vertex 44.116789181895 25.830303993361 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 40.883210818105 14.169696006639 0.77775 - vertex 40.75 13.5 0.77775 - vertex 40.75 13.5 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 40.883210818105 14.169696006639 0.77775 - vertex 40.75 13.5 0 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 60 23 0 - vertex 60 23 0.77775 - vertex 54.002309837942 23 0.77775 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 60 23 0 - vertex 54.002309837942 23 0.77775 - vertex 54.002309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 0 30 0 - vertex 14.042553191489 30 0 - vertex 14.883210818105 27.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 0 30 0 - vertex 14.883210818105 27.169696006639 0 - vertex 6.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 41.262563132924 25.262563132924 0 - vertex 41.262563132924 25.262563132924 0.77775 - vertex 41.830303993361 24.883210818105 0.77775 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 41.262563132924 25.262563132924 0 - vertex 41.830303993361 24.883210818105 0.77775 - vertex 41.830303993361 24.883210818105 0 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 41.830303993361 28.116789181895 0.77775 - vertex 41.262563132924 27.737436867076 0.77775 - vertex 41.262563132924 27.737436867076 0 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 41.830303993361 28.116789181895 0.77775 - vertex 41.262563132924 27.737436867076 0 - vertex 41.830303993361 28.116789181895 0 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 43.169696006639 24.883210818105 0.77775 - vertex 43.737436867076 25.262563132924 0.77775 - vertex 43.737436867076 25.262563132924 0 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 43.169696006639 24.883210818105 0.77775 - vertex 43.737436867076 25.262563132924 0 - vertex 43.169696006639 24.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 10 0 - vertex 43.169696006639 11.883210818105 0 - vertex 43.737436867076 12.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 10 0 - vertex 43.737436867076 12.262563132924 0 - vertex 54.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 24.936988122232 0.77775 - vertex 60 23 0.77775 - vertex 52 40 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 24.936988122232 0.77775 - vertex 52 40 0.77775 - vertex 52 30 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 15.455907969142 17 0.77775 - vertex 34.416922535211 17 0.77775 - vertex 41.422110817733 17 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 15.455907969142 17 0.77775 - vertex 41.422110817733 17 0 - vertex 12.002309837942 17 0 - endloop -endfacet -facet normal 0 -0.831469612304 0.555570233017 - outer loop - vertex 12.002309837942 24.804173569059 0.110046151702 - vertex 6.011309837942 24.804173569059 0.110046151702 - vertex 6.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 -0.831469612304 0.555570233017 - outer loop - vertex 12.002309837942 24.804173569059 0.110046151702 - vertex 6.011309837942 24.730643081307 0 - vertex 12.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.262563132924 14.737436867076 0.77775 - vertex 15.455907969142 17 0.77775 - vertex 12.002309837942 17 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.262563132924 14.737436867076 0.77775 - vertex 12.002309837942 17 0.77775 - vertex 14.883210818105 14.169696006639 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 44.116789181895 25.830303993361 0.77775 - vertex 43.737436867076 25.262563132924 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 0 17 0.77775 - vertex 0 10 0.77775 - vertex 6.011309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 0 17 0.77775 - vertex 6.011309837942 15.063011877768 0.77775 - vertex 6.011309837942 17 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 17 0.77775 - vertex 34.416922535211 17 0.77775 - vertex 42.5 15.25 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 17 0.77775 - vertex 42.5 15.25 0.77775 - vertex 43.169696006639 15.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.883210818105 14.169696006639 0.77775 - vertex 12.002309837942 17 0.77775 - vertex 12.002309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.883210818105 14.169696006639 0.77775 - vertex 12.002309837942 15.063011877768 0.77775 - vertex 14.75 13.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 6.011309837942 24.936988122232 0.77775 - vertex 0 30 0.77775 - vertex 0 23 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 6.011309837942 24.936988122232 0.77775 - vertex 0 23 0.77775 - vertex 6.011309837942 23 0.77775 - endloop -endfacet -facet normal -0 -0 -1 - outer loop - vertex 40.75 26.5 0 - vertex 40.883210818105 25.830303993361 0 - vertex 18.116789181895 27.169696006639 0 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 0 - outer loop - vertex 44.25 13.5 0.77775 - vertex 44.116789181895 14.169696006639 0.77775 - vertex 44.116789181895 14.169696006639 0 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 -0 - outer loop - vertex 44.25 13.5 0.77775 - vertex 44.116789181895 14.169696006639 0 - vertex 44.25 13.5 0 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 17.737436867076 12.262563132924 0 - vertex 17.737436867076 12.262563132924 0.77775 - vertex 18.116789181895 12.830303993361 0.77775 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 17.737436867076 12.262563132924 0 - vertex 18.116789181895 12.830303993361 0.77775 - vertex 18.116789181895 12.830303993361 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 0 10 0.77775 - vertex 15.306548743796 10 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - endloop -endfacet -facet normal 0 -0.980785280403 0.195090322015 - outer loop - vertex 54.002309837942 24.804173569059 0.110046151702 - vertex 54.002309837942 24.936988122232 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 -0.980785280403 0.195090322015 - outer loop - vertex 54.002309837942 24.804173569059 0.110046151702 - vertex 48.011309837942 24.936988122232 0.77775 - vertex 48.011309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 14.883210818105 12.830303993361 0 - vertex 14.883210818105 12.830303993361 0.77775 - vertex 15.262563132924 12.262563132924 0.77775 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 14.883210818105 12.830303993361 0 - vertex 15.262563132924 12.262563132924 0.77775 - vertex 15.262563132924 12.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 54.002309837942 15.269356918694 0 - vertex 43.737436867076 12.262563132924 0 - vertex 44.116789181895 12.830303993361 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 54.002309837942 15.269356918694 0 - vertex 44.116789181895 12.830303993361 0 - vertex 48.011309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 0 30 0 - vertex 0 30 0.77775 - vertex 14.607403236621 30 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 0 30 0 - vertex 14.607403236621 30 0.77775 - vertex 14.042553191489 30 0 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 41.262563132924 12.262563132924 0 - vertex 41.262563132924 12.262563132924 0.77775 - vertex 41.830303993361 11.883210818105 0.77775 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 41.262563132924 12.262563132924 0 - vertex 41.830303993361 11.883210818105 0.77775 - vertex 41.830303993361 11.883210818105 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 0 10 0 - vertex 0 10 0.77775 - vertex 0 17 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 0 10 0 - vertex 0 17 0.77775 - vertex 0 17 0 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 44.116789181895 12.830303993361 0.77775 - vertex 44.25 13.5 0.77775 - vertex 44.25 13.5 0 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 44.116789181895 12.830303993361 0.77775 - vertex 44.25 13.5 0 - vertex 44.116789181895 12.830303993361 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 41.422110817733 17 0 - vertex 34.416922535211 17 0.77775 - vertex 48.011309837942 17 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 41.422110817733 17 0 - vertex 48.011309837942 17 0.77775 - vertex 48.011309837942 17 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 52 30 0.77775 - vertex 52 40 0.77775 - vertex 52 40 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 52 30 0.77775 - vertex 52 40 0 - vertex 52 30 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 15.830303993361 24.883210818105 0 - vertex 16.5 24.75 0 - vertex 12.002309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.262563132924 27.737436867076 0 - vertex 40.883210818105 27.169696006639 0 - vertex 17.737436867076 27.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.262563132924 27.737436867076 0 - vertex 17.737436867076 27.737436867076 0 - vertex 17.169696006639 28.116789181895 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 6.011309837942 15.063011877768 0.77775 - vertex 0 10 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 6.011309837942 15.063011877768 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - vertex 12.002309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 17 0.77775 - vertex 43.737436867076 14.737436867076 0.77775 - vertex 44.116789181895 14.169696006639 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 17 0.77775 - vertex 44.116789181895 14.169696006639 0.77775 - vertex 48.011309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 15.262563132924 25.262563132924 0 - vertex 15.830303993361 24.883210818105 0 - vertex 12.002309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 15.262563132924 25.262563132924 0 - vertex 12.002309837942 23 0 - vertex 12.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 44.25 26.5 0.77775 - vertex 44.116789181895 25.830303993361 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 40.883210818105 27.169696006639 0 - vertex 40.75 26.5 0 - vertex 18.116789181895 27.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 40.883210818105 27.169696006639 0 - vertex 18.116789181895 27.169696006639 0 - vertex 17.737436867076 27.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 17 0 - vertex 41.262563132924 14.737436867076 0 - vertex 17.169696006639 15.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 17 0 - vertex 17.169696006639 15.116789181895 0 - vertex 16.5 15.25 0 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 15.830303993361 15.116789181895 0 - vertex 15.830303993361 15.116789181895 0.77775 - vertex 15.262563132924 14.737436867076 0.77775 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 15.830303993361 15.116789181895 0 - vertex 15.262563132924 14.737436867076 0.77775 - vertex 15.262563132924 14.737436867076 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 41.262563132924 27.737436867076 0.77775 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 40.883210818105 27.169696006639 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 41.262563132924 27.737436867076 0.77775 - vertex 40.883210818105 27.169696006639 0 - vertex 41.262563132924 27.737436867076 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 48.011309837942 23 0 - vertex 37.474084379442 23 0.77775 - vertex 17.379510917074 23 0.77775 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 48.011309837942 23 0 - vertex 17.379510917074 23 0.77775 - vertex 12.002309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 17 0 - vertex 15.830303993361 15.116789181895 0 - vertex 15.262563132924 14.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 17 0 - vertex 15.262563132924 14.737436867076 0 - vertex 12.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 40.883210818105 25.830303993361 0 - vertex 40.883210818105 25.830303993361 0.77775 - vertex 41.262563132924 25.262563132924 0.77775 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 40.883210818105 25.830303993361 0 - vertex 41.262563132924 25.262563132924 0.77775 - vertex 41.262563132924 25.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.883210818105 12.830303993361 0 - vertex 15.262563132924 12.262563132924 0 - vertex 14.464705848856 10 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.883210818105 12.830303993361 0 - vertex 14.464705848856 10 0 - vertex 0 10 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 27.737436867076 0.77775 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 41.262563132924 27.737436867076 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.262563132924 27.737436867076 0.77775 - vertex 17.169696006639 28.116789181895 0.77775 - vertex 17.737436867076 27.737436867076 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 23 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - vertex 43.737436867076 25.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 23 0.77775 - vertex 43.737436867076 25.262563132924 0.77775 - vertex 43.169696006639 24.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 15.063011877768 0.77775 - vertex 44.116789181895 14.169696006639 0.77775 - vertex 44.25 13.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 44.116789181895 27.169696006639 0.77775 - vertex 44.25 26.5 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 44.116789181895 27.169696006639 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - vertex 52 30 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 27.169696006639 0.77775 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 17.737436867076 27.737436867076 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 23 0.77775 - vertex 54.002309837942 24.936988122232 0.77775 - vertex 54.002309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.262563132924 27.737436867076 0.77775 - vertex 41.866228156844 30 0.77775 - vertex 14.607403236621 30 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.262563132924 27.737436867076 0.77775 - vertex 14.607403236621 30 0.77775 - vertex 17.169696006639 28.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 15.063011877768 0.77775 - vertex 44.25 13.5 0.77775 - vertex 44.116789181895 12.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 15.063011877768 0.77775 - vertex 44.116789181895 12.830303993361 0.77775 - vertex 52 10 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 14.169696006639 0.77775 - vertex 18.25 13.5 0.77775 - vertex 41.262563132924 12.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.25 26.5 0.77775 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 18.116789181895 27.169696006639 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 24.730643081307 0 - vertex 54.002309837942 23 0 - vertex 54.002309837942 23 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 24.730643081307 0 - vertex 54.002309837942 23 0.77775 - vertex 54.002309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.830303993361 11.883210818105 0.77775 - vertex 41.262563132924 12.262563132924 0.77775 - vertex 18.25 13.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.830303993361 11.883210818105 0.77775 - vertex 18.25 13.5 0.77775 - vertex 18.116789181895 12.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 12.830303993361 0.77775 - vertex 17.737436867076 12.262563132924 0.77775 - vertex 42.5 11.75 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 12.830303993361 0.77775 - vertex 42.5 11.75 0.77775 - vertex 41.830303993361 11.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 12.262563132924 0.77775 - vertex 15.306548743796 10 0.77775 - vertex 52 10 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 12.262563132924 0.77775 - vertex 52 10 0.77775 - vertex 42.5 11.75 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 40.883210818105 12.830303993361 0.77775 - vertex 18.116789181895 14.169696006639 0.77775 - vertex 41.262563132924 12.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.25 26.5 0.77775 - vertex 40.75 26.5 0.77775 - vertex 40.883210818105 27.169696006639 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 25.830303993361 0.77775 - vertex 37.474084379442 23 0.77775 - vertex 40.75 26.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 25.830303993361 0.77775 - vertex 40.75 26.5 0.77775 - vertex 18.25 26.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 40.883210818105 12.830303993361 0.77775 - vertex 34.416922535211 17 0.77775 - vertex 17.737436867076 14.737436867076 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 40.883210818105 12.830303993361 0.77775 - vertex 17.737436867076 14.737436867076 0.77775 - vertex 18.116789181895 14.169696006639 0.77775 - endloop -endfacet -endsolid diff --git a/skeinforge/models/Screw Holder.gts b/skeinforge/models/Screw Holder.gts deleted file mode 100644 index 6399a12..0000000 --- a/skeinforge/models/Screw Holder.gts +++ /dev/null @@ -1,4493 +0,0 @@ -737 2253 1502 Number of Vertices,Number of Edges,Number of Faces --6.859863212247494 0.22628773741583247 9.642249999999999 Vertex Coordinates XYZ --6.649863212247495 0.946287737415833 9.642249999999999 --6.319863212247495 1.396287737415833 9.642249999999999 --5.809863212247494 1.726287737415833 9.642249999999999 --5.2998632122474945 1.8462877374158326 9.642249999999999 --4.519863212247495 1.8462877374158326 9.642249999999999 --4.009863212247495 1.636287737415833 9.642249999999999 --3.6798632122474944 1.2762877374158328 9.642249999999999 --3.4698632122474935 0.7962877374158329 9.642249999999999 --3.3498632122474934 0.016287737415832892 9.642249999999999 --3.3498632122474934 -0.37371226258416745 9.642249999999999 --5.689863212247494 -0.4037122625841675 9.642249999999999 --5.509863212247495 -0.9437122625841673 9.642249999999999 --5.179863212247494 -1.2437122625841672 9.642249999999999 --4.699863212247494 -1.3937122625841676 9.642249999999999 --3.949863212247494 -1.3637122625841673 9.642249999999999 --3.319863212247494 -1.1837122625841672 9.642249999999999 --3.3498632122474934 -1.9637122625841674 9.642249999999999 --4.279863212247495 -2.143712262584168 9.642249999999999 --5.209863212247494 -2.143712262584168 9.642249999999999 --5.929863212247494 -1.9037122625841678 9.642249999999999 --6.409863212247495 -1.4837122625841674 9.642249999999999 --6.679863212247494 -1.0337122625841673 9.642249999999999 --6.829863212247495 -0.4337122625841675 9.642249999999999 --5.4473632122474935 0.8687877374158329 9.642249999999999 --4.457363212247493 0.8387877374158327 9.642249999999999 --4.367363212247493 0.26878773741583245 9.642249999999999 --5.627363212247492 0.3887877374158325 9.642249999999999 --4.667363212247494 1.1087877374158324 9.642249999999999 --5.627363212247492 0.2987877374158325 9.642249999999999 --5.177363212247494 1.1087877374158324 9.642249999999999 --4.009863212247495 1.636287737415833 11.322250000000002 --4.519863212247496 1.8462877374158326 11.322250000000002 --3.6798632122474944 1.276287737415834 11.32225 --3.3498632122474934 -0.37371226258416734 11.32225 --3.3498632122474934 0.016287737415832892 11.32225 --5.689863212247495 -0.4037122625841676 11.32225 --3.9498632122474935 -1.3637122625841673 11.32225 --3.319863212247494 -1.1837122625841672 11.32225 --3.3498632122474943 -1.9637122625841679 11.32225 --6.859863212247496 0.2262877374158324 11.322249999999999 --6.829863212247496 -0.4337122625841676 11.32225 --6.319863212247493 1.396287737415832 11.322249999999999 --5.809863212247494 1.726287737415833 11.32225 --6.649863212247495 0.9462877374158329 11.32225 --5.209863212247495 -2.143712262584168 11.32225 --5.929863212247496 -1.9037122625841687 11.32225 --5.179863212247494 -1.2437122625841672 11.32225 --4.699863212247494 -1.3937122625841676 11.32225 --4.279863212247495 -2.1437122625841676 11.32225 --6.4098632122474966 -1.483712262584167 11.32225 --6.679863212247495 -1.0337122625841677 11.32225 --5.299863212247494 1.846287737415833 11.32225 --3.4698632122474944 0.796287737415833 11.32225 --5.509863212247496 -0.9437122625841675 11.32225 --4.667363212247494 1.1087877374158326 11.32225 --5.177363212247494 1.1087877374158317 11.32225 --4.457363212247494 0.8387877374158329 11.32225 --5.627363212247493 0.38878773741583256 11.32225 --4.367363212247493 0.2687877374158326 11.32225 --5.627363212247492 0.2987877374158324 11.32225 --5.4473632122474935 0.8687877374158326 11.32225 -11.759863212247497 1.8856484886916096 9.64225 -12.899863212247496 1.8556484886916098 9.64225 -12.929863212247495 1.22564848869161 9.64225 -13.439863212247495 1.6756484886916105 9.64225 -13.889863212247496 1.8556484886916098 9.64225 -14.519863212247497 1.8556484886916098 9.64225 -14.999863212247497 1.5856484886916102 9.64225 -15.359863212247497 1.0756484886916096 9.64225 -15.539863212247496 0.3556484886916095 9.64225 -15.539863212247496 -0.60435151130839 9.64225 -15.329863212247497 -1.23435151130839 9.64225 -14.999863212247497 -1.6843515113083907 9.64225 -14.609863212247497 -1.9543515113083907 9.64225 -14.039863212247496 -2.1343515113083904 9.64225 -12.899863212247496 -2.194351511308391 9.64225 -12.869863212247497 -3.5143515113083907 9.64225 -11.759863212247497 -3.484351511308391 9.64225 -12.899863212247496 -1.3843515113083904 9.64225 -13.079863212247497 -1.4443515113083905 9.64225 -14.279863212247497 -0.9043515113083903 9.64225 -12.899863212247496 0.4456484886916098 9.64225 -13.379863212247496 0.8956484886916104 9.64225 -13.769863212247497 1.0156484886916095 9.64225 -14.369863212247497 -0.21435151130839014 9.64225 -14.279863212247497 0.5056484886916098 9.64225 -14.009863212247497 -1.2943515113083905 9.64225 -14.099863212247497 0.8656484886916099 9.64225 -13.649863212247496 -1.4443515113083905 9.64225 -11.759863212247497 1.8856484886916096 11.32225 -12.899863212247498 1.8556484886916098 11.32225 -12.929863212247488 1.2256484886916095 11.32225 -13.439863212247495 1.6756484886916105 11.32225 -13.889863212247494 1.8556484886916107 11.32225 -14.519863212247497 1.8556484886916098 11.32225 -14.999863212247497 1.5856484886916107 11.32225 -15.359863212247493 1.0756484886916098 11.32225 -15.5398632122475 0.35564848869160914 11.32225 -15.539863212247498 -0.6043515113083899 11.32225 -15.329863212247494 -1.234351511308391 11.32225 -14.999863212247503 -1.684351511308392 11.32225 -14.609863212247497 -1.9543515113083898 11.32225 -14.039863212247498 -2.1343515113083895 11.32225 -12.899863212247496 -2.194351511308391 11.32225 -12.869863212247498 -3.514351511308391 11.32225 -11.759863212247494 -3.4843515113083914 11.32225 -14.279863212247493 -0.9043515113083888 11.322250000000002 -14.009863212247494 -1.2943515113083883 11.322250000000002 -13.379863212247498 0.8956484886916118 11.32225 -13.769863212247497 1.0156484886916093 11.322249999999997 -12.899863212247496 0.4456484886916098 11.32225 -12.899863212247496 -1.38435151130839 11.32225 -14.36986321224749 -0.2143515113083907 11.32225 -14.279863212247497 0.5056484886916095 11.32225 -14.099863212247497 0.8656484886916107 11.32225 -13.649863212247496 -1.4443515113083905 11.32225 -13.0798632122475 -1.4443515113083896 11.32225 -2.270136787752506 3.2862877374158317 9.64225 -5.210136787752507 3.256287737415831 9.64225 -5.7801367877525065 3.0462877374158315 9.64225 -6.110136787752507 2.716287737415832 9.64225 -6.260136787752507 2.356287737415831 9.64225 -6.320136787752506 1.6662877374158316 9.64225 -6.140136787752507 1.0962877374158313 9.64225 -5.600136787752507 0.5562877374158314 9.64225 -5.270136787752507 0.3462877374158312 9.64225 -7.040136787752506 -2.1737122625841687 9.64225 -5.720136787752507 -2.143712262584169 9.64225 -4.220136787752507 0.04628773741583159 9.64225 -3.380136787752506 0.01628773741583156 9.64225 -3.350136787752507 -2.1737122625841687 9.64225 -2.270136787752506 -2.143712262584169 9.64225 -3.3801367877525057 2.5062877374158314 9.64225 -3.3801367877525057 0.8562877374158319 9.64225 -5.120136787752506 1.9962877374158312 9.64225 -4.520136787752507 0.9162877374158317 9.64225 -5.120136787752506 1.4562877374158316 9.64225 -3.920136787752506 0.8262877374158316 9.64225 -4.580136787752507 2.476287737415832 9.64225 -4.940136787752506 2.296287737415832 9.64225 -4.880136787752506 1.0962877374158313 9.64225 -2.2701367877525054 3.286287737415832 11.32225 -5.210136787752507 3.256287737415833 11.322250000000004 -5.780136787752506 3.046287737415832 11.32225 -6.1101367877525075 2.7162877374158323 11.32225 -6.260136787752506 2.356287737415831 11.32225 -6.320136787752505 1.6662877374158316 11.32225 -6.140136787752509 1.0962877374158313 11.32225 -5.600136787752508 0.5562877374158319 11.32225 -5.270136787752508 0.3462877374158302 11.32225 -7.040136787752505 -2.1737122625841687 11.32225 -5.7201367877525096 -2.143712262584169 11.32225 -4.220136787752508 0.046287737415831476 11.32225 -3.3801367877525066 0.01628773741583056 11.32225 -3.3501367877525063 -2.1737122625841683 11.32225 -2.2701367877525063 -2.143712262584169 11.322250000000002 -3.9201367877525066 0.8262877374158334 11.32225 -4.520136787752508 0.9162877374158318 11.32225 -4.880136787752507 1.096287737415831 11.32225 -5.120136787752507 1.9962877374158317 11.32225 -4.940136787752505 2.296287737415833 11.32225 -5.120136787752507 1.4562877374158316 11.32225 -3.380136787752506 0.8562877374158319 11.32225 -4.580136787752508 2.476287737415833 11.32225 -3.3801367877525057 2.506287737415832 11.32225 --2.4198632122474937 1.876287737415832 9.64225 --1.279863212247494 1.8462877374158322 9.64225 --1.2498632122474946 1.2162877374158323 9.64225 --0.7398632122474949 1.666287737415833 9.64225 --0.2898632122474938 1.8462877374158322 9.64225 -0.3401367877525061 1.8462877374158322 9.64225 -0.8201367877525065 1.5762877374158326 9.64225 -1.1801367877525069 1.066287737415832 9.64225 -1.3601367877525057 0.34628773741583185 9.64225 -1.3601367877525057 -0.6137122625841677 9.64225 -1.1501367877525075 -1.2437122625841677 9.64225 -0.8201367877525065 -1.6937122625841683 9.64225 -0.43013678775250686 -1.9637122625841683 9.64225 --0.13986321224749437 -2.143712262584168 9.64225 --1.279863212247494 -2.2037122625841685 9.64225 --1.3098632122474934 -3.5237122625841684 9.64225 --2.4198632122474937 -3.4937122625841686 9.64225 --1.0998632122474925 -1.453712262584168 9.64225 -0.10013678775250578 -0.9137122625841679 9.64225 --1.279863212247494 0.43628773741583216 9.64225 --0.7998632122474936 0.8862877374158328 9.64225 --0.40986321224749395 1.0062877374158319 9.64225 --1.279863212247494 -1.393712262584168 9.64225 -0.19013678775250686 -0.22371226258416776 9.64225 -0.10013678775250612 0.4962877374158322 9.64225 --0.16986321224749384 -1.3037122625841682 9.64225 --0.07986321224749288 0.8562877374158323 9.64225 --0.5298632122474941 -1.453712262584168 9.64225 --2.4198632122474937 1.876287737415832 11.32225 --1.2798632122474942 1.8462877374158313 11.32225 --1.2498632122474944 1.2162877374158318 11.32225 --0.7398632122474951 1.6662877374158342 11.322249999999999 --0.28986321224749373 1.8462877374158322 11.32225 -0.340136787752506 1.8462877374158322 11.32225 -0.8201367877525063 1.5762877374158322 11.32225 -1.180136787752507 1.0662877374158315 11.32225 -1.3601367877525052 0.34628773741583185 11.32225 -1.3601367877525052 -0.6137122625841679 11.32225 -1.1501367877525073 -1.2437122625841677 11.32225 -0.8201367877525064 -1.6937122625841687 11.322250000000002 -0.43013678775250686 -1.9637122625841683 11.32225 --0.13986321224749487 -2.143712262584167 11.32225 --1.2798632122474942 -2.203712262584169 11.32225 --1.3098632122474934 -3.5237122625841684 11.32225 --2.4198632122474937 -3.493712262584169 11.32225 -0.10013678775250634 -0.9137122625841673 11.32225 --0.16986321224749368 -1.3037122625841677 11.32225 --0.40986321224749384 1.0062877374158323 11.32225 --1.2798632122474942 0.43628773741583216 11.32225 --1.2798632122474942 -1.393712262584168 11.32225 -0.19013678775250709 -0.22371226258416776 11.32225 -0.10013678775250609 0.4962877374158318 11.32225 --0.07986321224749288 0.8562877374158324 11.32225 --0.5298632122474942 -1.453712262584168 11.32225 --1.0998632122474927 -1.453712262584168 11.32225 --0.7998632122474936 0.8862877374158331 11.32225 --11.929863212247497 3.2862877374158317 9.64225 --8.989863212247496 3.256287737415831 9.64225 --8.419863212247495 3.0462877374158315 9.64225 --8.089863212247495 2.716287737415832 9.64225 --7.939863212247495 2.356287737415831 9.64225 --7.879863212247496 1.6662877374158316 9.64225 --8.059863212247494 1.0962877374158313 9.64225 --8.599863212247495 0.5562877374158314 9.64225 --8.929863212247495 0.3462877374158312 9.64225 --7.159863212247496 -2.1737122625841687 9.64225 --8.479863212247496 -2.143712262584169 9.64225 --9.979863212247496 0.04628773741583159 9.64225 --10.819863212247496 0.01628773741583156 9.64225 --10.849863212247495 -2.1737122625841687 9.64225 --11.929863212247497 -2.143712262584169 9.64225 --10.819863212247496 2.5062877374158314 9.64225 --10.819863212247496 0.8562877374158319 9.64225 --9.079863212247496 1.9962877374158312 9.64225 --9.679863212247495 0.9162877374158317 9.64225 --9.079863212247496 1.4562877374158316 9.64225 --10.279863212247495 0.8262877374158316 9.64225 --9.619863212247495 2.476287737415832 9.64225 --9.259863212247495 2.296287737415832 9.64225 --9.319863212247496 1.0962877374158313 9.64225 --11.9298632122475 3.2862877374158317 11.32225 --8.989863212247498 3.2562877374158314 11.32225 --8.419863212247495 3.046287737415831 11.32225 --8.089863212247495 2.7162877374158314 11.32225 --7.939863212247496 2.3562877374158306 11.322250000000002 --7.879863212247495 1.666287737415833 11.32225 --8.059863212247494 1.096287737415831 11.32225 --8.599863212247495 0.5562877374158306 11.32225 --8.929863212247497 0.3462877374158324 11.32225 --7.159863212247495 -2.1737122625841683 11.32225 --8.479863212247496 -2.143712262584169 11.32225 --9.979863212247498 0.04628773741582992 11.32225 --10.819863212247498 0.016287737415831227 11.32225 --10.849863212247497 -2.1737122625841687 11.32225 --11.929863212247499 -2.1437122625841694 11.32225 --9.679863212247495 0.9162877374158314 11.32225 --9.319863212247498 1.096287737415831 11.322250000000002 --9.079863212247496 1.4562877374158316 11.32225 --9.079863212247496 1.996287737415832 11.322250000000002 --9.259863212247495 2.2962877374158324 11.32225 --10.819863212247496 0.8562877374158329 11.322250000000002 --9.619863212247497 2.476287737415832 11.32225 --10.279863212247498 0.8262877374158322 11.32225 --10.819863212247494 2.5062877374158314 11.32225 -30.0 15.073000000000004 7.822250000000002 -30.0 15.206210818105248 8.491946006638905 -30.0 15.585563132923546 9.059686867076463 -30.0 16.153303993361096 9.43903918189475 -30.0 16.823 9.572249999999997 -30.0 17.49269600663891 9.43903918189475 -30.0 18.06043686707646 9.059686867076458 -30.0 18.439789181894753 8.49194600663891 -30.0 18.573000000000004 7.822250000000006 -30.0 18.439789181894753 7.152553993361098 -22.000000000000007 18.43978918189476 7.152553993361091 -30.0 18.06043686707646 6.5848131329235455 -30.0 17.492696006638916 6.205460818105249 -30.0 16.823 6.072249999999999 -30.0 16.153303993361092 6.205460818105249 -30.0 15.585563132923546 6.584813132923542 -30.0 15.206210818105244 7.152553993361091 -22.000000000000007 15.073000000000006 7.822250000000001 -22.000000000000007 15.206210818105252 8.491946006638905 -22.000000000000007 15.585563132923546 9.05968686707646 -22.000000000000007 16.823000000000008 9.572249999999997 -22.000000000000007 16.153303993361096 9.439039181894755 -22.000000000000014 17.492696006638912 9.439039181894753 -22.000000000000007 18.060436867076454 9.059686867076454 -22.000000000000007 18.439789181894753 8.491946006638907 -22.0 18.57300000000001 7.822250000000001 -22.000000000000007 18.060436867076465 6.584813132923542 -22.000000000000007 17.492696006638912 6.20546081810525 -22.000000000000007 16.823 6.0722499999999995 -22.000000000000007 16.1533039933611 6.205460818105244 -22.000000000000007 15.585563132923546 6.584813132923544 -22.000000000000007 15.206210818105255 7.152553993361091 -22.000000000000007 15.073000000000002 -0.17774999999999785 -22.000000000000007 15.585563132923546 1.0596868670764614 -22.000000000000007 15.206210818105255 0.49194600663890586 -22.000000000000007 16.153303993361096 1.439039181894751 -22.000000000000007 16.823000000000004 1.5722499999999995 -22.000000000000007 17.492696006638912 1.4390391818947483 -22.000000000000007 18.06043686707646 1.059686867076457 -22.000000000000014 18.573000000000004 -0.1777500000000014 -22.000000000000007 18.43978918189476 0.49194600663890853 -22.000000000000007 18.060436867076458 -1.4151868670764545 -22.000000000000007 18.43978918189476 -0.8474460066389078 -22.000000000000007 17.492696006638912 -1.7945391818947485 -22.000000000000007 16.153303993361092 -1.7945391818947503 -22.000000000000007 16.823000000000004 -1.9277499999999996 -22.000000000000007 15.585563132923546 -1.4151868670764598 -22.000000000000007 15.206210818105253 -0.8474460066389087 -30.0 15.072999999999999 -0.17774999999999785 -30.0 15.206210818105257 0.49194600663890586 -30.0 15.58556313292355 1.0596868670764596 -30.0 16.153303993361096 1.4390391818947554 -30.0 16.823000000000004 1.5722499999999995 -30.0 18.060436867076465 1.0596868670764579 -30.0 17.492696006638912 1.4390391818947492 -30.0 18.439789181894753 0.49194600663890586 -30.0 18.573 -0.1777500000000014 -30.0 18.43978918189476 -0.8474460066389105 -30.0 17.492696006638912 -1.7945391818947511 -30.0 18.06043686707646 -1.4151868670764562 -30.0 16.823000000000004 -1.9277499999999996 -30.0 16.153303993361096 -1.7945391818947494 -30.0 15.585563132923548 -1.4151868670764598 -30.0 15.20621081810525 -0.8474460066389096 -29.999999999999993 -17.927 -0.1777500000000014 -22.000000000000007 -17.793789181894752 0.491946006638905 -30.0 -17.414436867076454 1.0596868670764552 -30.0 -16.846696006638904 1.4390391818947492 -30.0 -16.176999999999996 1.5722499999999995 -30.0 -15.507303993361093 1.4390391818947545 -30.0 -14.939563132923539 1.059686867076457 -29.999999999999993 -14.560210818105249 0.4919460066389041 -29.999999999999993 -14.427 -0.17774999999999963 -30.0 -14.560210818105247 -0.8474460066389069 -30.0 -14.93956313292354 -1.4151868670764562 -30.0 -15.507303993361088 -1.794539181894752 -30.0 -16.177 -1.9277500000000023 -30.0 -16.846696006638904 -1.7945391818947556 -30.0 -17.414436867076454 -1.4151868670764527 -29.999999999999993 -17.793789181894756 -0.8474460066389087 -30.0 -17.793789181894756 0.4919460066389023 -22.000000000000007 -17.927000000000003 -0.17774999999999785 -22.000000000000007 -17.414436867076454 1.059686867076456 -22.000000000000007 -16.846696006638904 1.4390391818947519 -22.000000000000007 -16.176999999999996 1.5722499999999995 -22.000000000000007 -15.507303993361091 1.4390391818947519 -22.000000000000007 -14.939563132923539 1.0596868670764579 -22.000000000000007 -14.560210818105244 0.49194600663890764 -22.000000000000007 -14.427000000000001 -0.1777500000000023 -22.000000000000007 -14.560210818105245 -0.8474460066389105 -22.000000000000007 -14.939563132923539 -1.4151868670764625 -22.000000000000007 -15.507303993361091 -1.7945391818947538 -22.000000000000007 -16.177 -1.9277500000000014 -22.000000000000007 -16.846696006638904 -1.79453918189476 -22.000000000000007 -17.414436867076454 -1.415186867076459 -22.000000000000007 -17.79378918189475 -0.8474460066389069 -22.0 -17.92699999999999 7.822249999999998 -22.0 -17.793789181894745 8.491946006638901 -22.0 -17.414436867076454 9.059686867076454 -22.000000000000007 -16.8466960066389 9.43903918189475 -22.000000000000007 -16.177 9.572249999999999 -22.000000000000007 -15.507303993361091 9.439039181894753 -22.000000000000007 -14.939563132923539 9.059686867076458 -22.000000000000007 -14.560210818105242 8.491946006638909 -22.0 -14.426999999999989 7.822249999999997 -22.0 -14.560210818105247 7.152553993361094 -22.000000000000007 -14.939563132923539 6.584813132923543 -22.000000000000007 -15.50730399336109 6.205460818105245 -22.000000000000007 -16.177 6.072249999999999 -22.000000000000007 -16.846696006638904 6.205460818105244 -22.000000000000007 -17.414436867076454 6.584813132923531 -22.0 -17.793789181894745 7.15255399336109 -30.0 -17.92699999999999 7.822249999999999 -29.999999999999993 -17.79378918189475 8.491946006638901 -30.0 -16.8466960066389 9.439039181894747 -29.999999999999993 -17.41443686707645 9.059686867076447 -30.0 -16.177000000000003 9.572249999999999 -30.0 -15.507303993361093 9.439039181894755 -30.0 -14.939563132923542 9.05968686707646 -29.999999999999993 -14.560210818105244 8.49194600663891 -30.0 -14.426999999999994 7.822249999999999 -30.0 -14.560210818105247 7.15255399336109 -30.0 -15.507303993361091 6.205460818105246 -30.0 -14.939563132923539 6.58481313292354 -30.0 -16.846696006638908 6.20546081810525 -30.0 -16.177000000000003 6.072249999999999 -30.0 -17.414436867076454 6.5848131329235375 -29.999999999999993 -17.793789181894738 7.152553993361091 -22.000000000000007 20.323 11.32225 --15.957446808510642 10.323 -3.6777500000000014 -22.000000000000007 10.323 -3.677749999999998 -22.000000000000007 20.323 -3.6777499999999996 --30.0 10.323 11.32225 -22.000000000000007 10.323 11.32225 -18.512888012183033 10.323 -3.6777500000000014 -3.649215653894089 10.323 11.32225 --30.0 10.323 -3.6777500000000014 -22.000000000000007 -19.677 -3.677750000000003 --15.535294151144047 -9.677 -3.677749999999998 --15.551298997002412 -9.677 11.32225 --30.0 -9.677 11.32225 -22.000000000000007 -9.677 -3.677749999999998 -22.000000000000007 -9.677 11.32225 -14.771385376467595 -9.677000000000001 11.322249999999997 --30.0 -9.677 -3.6777500000000014 -22.000000000000007 -19.677 11.32225 -14.25 -6.1770000000000005 11.32225 -14.116789181894752 -6.846696006638907 11.32225 -13.737436867076458 -7.414436867076454 11.32225 -13.169696006638908 -7.793789181894753 11.32225 -12.5 -7.927000000000002 11.32225 -11.830303993361095 -7.793789181894753 -3.677749999999998 -10.883210818105248 -6.846696006638907 11.32225 -10.750000000000002 -6.177000000000002 11.32225 -10.883210818105248 -5.507303993361092 11.32225 -11.262563132923546 -4.939563132923541 11.32225 -11.830303993361092 -4.56021081810525 11.32225 -12.5 -4.4270000000000005 11.32225 -13.169696006638912 -4.560210818105252 11.32225 -13.737436867076458 -4.939563132923545 11.32225 -14.116789181894745 -5.507303993361094 11.32225 -11.262563132923546 -7.414436867076459 -3.677749999999998 -14.116789181894752 -6.846696006638906 -3.677749999999998 -14.250000000000004 -6.177000000000001 -3.677749999999998 -13.737436867076454 -7.414436867076457 -3.677749999999998 -12.5 -7.9270000000000005 -3.677749999999998 -13.169696006638908 -7.793789181894753 -3.677749999999998 -11.262563132923546 -7.4144368670764615 11.322250000000004 -11.830303993361099 -7.793789181894749 11.322249999999997 -10.883210818105246 -6.846696006638908 -3.6777500000000014 -10.749999999999998 -6.177000000000003 -3.6777500000000014 -10.883210818105246 -5.50730399336109 -3.677749999999998 -11.262563132923546 -4.939563132923544 -3.677749999999998 -11.830303993361092 -4.560210818105249 -3.677749999999998 -12.5 -4.427 -3.6777500000000014 -13.169696006638912 -4.560210818105251 -3.6777500000000014 -13.737436867076458 -4.939563132923547 -3.6777500000000014 -14.116789181894745 -5.507303993361091 -3.677749999999998 -14.25 6.823000000000001 11.32225 -14.116789181894752 6.153303993361095 11.32225 -13.737436867076458 5.585563132923542 11.32225 -13.169696006638908 5.206210818105249 11.32225 -12.5 5.0729999999999995 11.32225 -11.830303993361092 5.206210818105249 11.32225 -11.262563132923542 5.58556313292354 11.32225 -10.88321081810525 6.153303993361093 11.32225 -10.75 6.823000000000001 11.32225 -10.88321081810525 7.4926960066389094 11.32225 -11.262563132923542 8.060436867076458 11.32225 -11.830303993361092 8.439789181894751 11.32225 -12.500000000000004 8.572999999999997 11.32225 -13.169696006638908 8.43978918189475 11.32225 -13.737436867076454 8.060436867076458 11.32225 -14.116789181894745 7.492696006638908 11.32225 -14.116789181894756 6.153303993361094 -3.677749999999998 -14.250000000000004 6.822999999999999 -3.677749999999998 -13.169696006638908 5.206210818105248 -3.677749999999998 -13.737436867076454 5.585563132923541 -3.6777500000000014 -11.830303993361092 5.206210818105244 -3.677749999999998 -12.500000000000007 5.073 -3.677749999999998 -11.262563132923539 5.585563132923539 -3.6777500000000014 -10.883210818105248 6.153303993361094 -3.677749999999998 -10.75 6.823000000000002 -3.677749999999998 -10.88321081810525 7.49269600663891 -3.677749999999998 -11.262563132923542 8.060436867076458 -3.677749999999998 -11.830303993361092 8.439789181894751 -3.677749999999998 -13.169696006638908 8.439789181894747 -3.677749999999998 -12.500000000000007 8.572999999999999 -3.677749999999998 -13.73743686707645 8.060436867076456 -3.677749999999998 -14.116789181894752 7.492696006638909 -3.677749999999998 --11.75 6.8229999999999995 11.32225 --11.883210818105248 6.153303993361091 11.32225 --12.262563132923546 5.585563132923542 11.32225 --12.830303993361092 5.206210818105249 11.32225 --13.5 5.0729999999999995 11.32225 --14.169696006638908 5.206210818105247 11.32225 --14.737436867076461 5.585563132923542 11.32225 --15.116789181894752 6.153303993361095 11.32225 --15.25 6.8229999999999995 11.32225 --15.116789181894749 7.492696006638904 11.32225 --14.737436867076454 8.060436867076458 11.32225 --14.169696006638908 8.439789181894753 11.32225 --13.500000000000007 8.573 11.32225 --12.830303993361099 8.439789181894755 11.32225 --12.262563132923542 8.060436867076463 11.32225 --11.883210818105244 7.492696006638908 11.32225 --11.749999999999996 6.823 -3.6777500000000014 --11.883210818105255 6.153303993361096 -3.677749999999998 --12.830303993361095 5.2062108181052515 -3.677750000000005 --12.262563132923542 5.5855631329235464 -3.677749999999998 --13.5 5.073 -3.6777500000000014 --14.169696006638908 5.20621081810525 -3.677749999999998 --15.116789181894756 6.153303993361094 -3.6777500000000014 --14.737436867076461 5.5855631329235464 -3.6777500000000014 --15.25 6.823000000000004 -3.6777500000000014 --15.116789181894749 7.492696006638907 -3.677749999999998 --14.169696006638908 8.439789181894753 -3.6777500000000014 --14.737436867076454 8.06043686707646 -3.677749999999998 --13.500000000000007 8.573 -3.6777500000000014 --12.830303993361099 8.439789181894756 -3.677749999999998 --12.262563132923546 8.060436867076461 -3.677749999999998 --11.883210818105248 7.492696006638909 -3.6777500000000014 --11.75 -6.177000000000002 11.32225 --11.883210818105248 -6.846696006638909 11.32225 --12.262563132923546 -7.4144368670764615 11.32225 --12.830303993361095 -7.793789181894753 11.32225 --13.5 -7.927000000000004 11.32225 --14.169696006638912 -7.793789181894753 11.32225 --14.737436867076458 -7.414436867076458 11.32225 --15.116789181894752 -6.846696006638909 11.32225 --15.25 -6.177000000000002 11.32225 --15.116789181894752 -5.507303993361099 11.32225 --14.737436867076461 -4.9395631329235465 11.32225 --14.169696006638908 -4.56021081810525 11.32225 --13.5 -4.4270000000000005 11.32225 --12.830303993361095 -4.56021081810525 11.32225 --12.262563132923539 -4.939563132923539 11.32225 --11.88321081810524 -5.507303993361094 11.32225 --11.883210818105248 -6.846696006638911 -3.677749999999998 --11.750000000000004 -6.177 -3.6777500000000014 --12.262563132923546 -7.414436867076457 -3.677749999999998 --12.830303993361095 -7.7937891818947564 -3.677749999999998 --14.169696006638908 -7.793789181894753 -3.6777500000000014 --13.5 -7.927000000000008 -3.677749999999998 --14.737436867076454 -7.414436867076457 -3.677749999999998 --15.116789181894752 -6.846696006638908 -3.677749999999998 --15.250000000000004 -6.177 -3.6777500000000014 --15.116789181894749 -5.507303993361097 -3.6777500000000014 --14.737436867076461 -4.939563132923546 -3.677749999999998 --14.169696006638908 -4.560210818105251 -3.677749999999998 --13.5 -4.427 -3.6777500000000014 --12.830303993361095 -4.560210818105254 -3.6777500000000014 --12.262563132923546 -4.93956313292354 -3.677749999999998 --11.88321081810524 -5.507303993361091 -3.677749999999998 --17.997690162057708 -2.677 2.3222500000000004 --17.997690162057708 3.323 2.3222500000000004 -30.0 3.323 2.3222500000000004 -30.0 3.323 -3.6777500000000014 --23.988690162057708 3.323 2.3222500000000004 --23.988690162057708 -2.677 2.3222500000000004 -30.0 -2.677 -3.6777500000000014 -18.011309837942285 -2.677 2.3222500000000004 -30.0 -2.677 2.3222500000000004 -18.011309837942285 3.323 -3.677749999999998 --30.0 3.323 -3.6777500000000014 --17.997690162057708 3.323 -3.6777500000000014 --23.988690162057708 3.323 -3.677749999999998 -11.422110817733461 -2.677 -3.677749999999998 --17.997690162057708 -2.677 -3.6777500000000014 --30.0 -2.677 2.3222500000000004 --23.988690162057708 -2.677 -3.677749999999998 --30.0 3.323 2.3222500000000004 -24.002309837942285 -2.677 2.3222500000000004 -18.011309837942285 3.323 2.3222500000000004 -24.002309837942285 3.323 -3.6777500000000014 --30.0 -2.677 -3.6777500000000014 -24.002309837942285 -2.677 -3.6777500000000014 -24.002309837942285 3.323 2.3222500000000004 -18.011309837942285 -2.677 -3.677749999999998 --17.997690162057708 -4.876999999999995 -1.5777500000000053 --17.997690162057708 -4.481173569058687 0.41220384829846246 --17.997690162057708 -3.3539552621700417 2.099205262170041 --17.997690162057708 -1.6669538482984616 3.226423569058687 --17.997690162057708 0.3230000000000051 3.6222499999999958 --17.997690162057708 2.312953848298472 3.226423569058687 --17.997690162057708 3.9999552621700523 2.099205262170044 --17.997690162057708 5.127173569058697 0.41220384829846424 --17.997690162057708 5.523000000000007 -1.5777500000000053 --17.997690162057708 5.127173569058698 -3.5677038482984695 --17.997690162057708 -4.481173569058685 -3.5677038482984766 --23.988690162057708 -4.876999999999992 -1.5777500000000053 --23.988690162057708 -4.481173569058684 0.41220384829846246 --23.988690162057708 -3.35395526217004 2.099205262170041 --23.988690162057708 -1.6669538482984607 3.226423569058687 --23.988690162057708 0.323000000000006 3.6222499999999958 --23.988690162057708 2.312953848298473 3.226423569058687 --23.988690162057708 3.999955262170054 2.099205262170044 --23.988690162057708 5.127173569058697 0.41220384829846246 --23.988690162057708 5.523000000000007 -1.5777500000000053 --23.988690162057708 5.1271735690587 -3.567703848298473 --23.988690162057708 -4.481173569058683 -3.5677038482984766 --17.997690162057708 5.053643081306509 -3.6777500000000014 --17.997690162057708 -4.4076430813064995 -3.6777500000000014 --23.988690162057708 5.0536430813065145 -3.677749999999998 --23.988690162057708 -4.4076430813064995 -3.677749999999998 -30.0 20.323 -3.6777499999999996 -30.0 20.323 11.32225 -30.0 -19.677 -3.677750000000003 -30.0 -19.677 11.32225 -24.002309837942285 5.053643081306509 -3.6777500000000014 -18.011309837942285 5.053643081306513 -3.677749999999998 -24.002309837942285 -4.4076430813064995 -3.6777500000000014 -18.011309837942285 -4.407643081306494 -3.677749999999998 -24.002309837942285 -4.876999999999995 -1.5777500000000053 -24.002309837942285 -4.481173569058687 0.41220384829846246 -24.002309837942285 -3.3539552621700417 2.099205262170041 -24.002309837942285 -1.6669538482984616 3.226423569058687 -24.002309837942285 0.3230000000000051 3.6222499999999958 -24.002309837942285 2.312953848298472 3.226423569058687 -24.002309837942285 3.9999552621700523 2.099205262170044 -24.002309837942285 5.127173569058697 0.41220384829846424 -24.002309837942285 5.523000000000007 -1.5777500000000053 -24.002309837942285 5.127173569058698 -3.5677038482984695 -24.002309837942285 -4.481173569058685 -3.5677038482984766 -18.011309837942285 -4.876999999999992 -1.5777500000000053 -18.011309837942285 -4.481173569058684 0.41220384829846246 -18.011309837942285 -3.35395526217004 2.099205262170041 -18.011309837942285 -1.6669538482984607 3.226423569058687 -18.011309837942285 0.323000000000006 3.6222499999999958 -18.011309837942285 2.312953848298473 3.226423569058687 -18.011309837942285 3.999955262170054 2.099205262170044 -18.011309837942285 5.127173569058697 0.41220384829846246 -18.011309837942285 5.523000000000007 -1.5777500000000053 -18.011309837942285 5.1271735690587 -3.567703848298473 -18.011309837942285 -4.481173569058683 -3.5677038482984766 --12.919863212247494 1.006287737415828 11.322250000000007 --13.189863212247493 1.4862877374158323 11.32225 --15.109863212247499 3.4362877374158303 11.32225 --16.999863212247483 1.5762877374158215 11.32225 --17.53986321224749 0.19628773741582983 11.322249999999999 --12.739863212247494 -0.3737122625841701 11.322250000000006 --12.739863212247498 0.34628773741582886 11.322250000000004 --12.979863212247494 -1.0937122625841718 11.322250000000004 --13.999863212247496 -2.08371226258417 11.32225 --14.689863212247495 -2.3237122625841695 11.32225 --13.459863212247495 -1.7237122625841699 11.32225 --16.939863212247495 -1.57371226258417 11.32225 --17.35986321224749 0.9762877374158305 11.32225 --16.3398632122475 -2.05371226258417 11.322250000000002 --15.649863212247492 -2.3237122625841677 11.32225 --17.329863212247496 -0.9137122625841699 11.32224999999999 --17.509863212247502 -0.25371226258417345 11.322249999999986 --17.539863212247496 0.1962877374158304 9.64225 --17.359863212247497 0.9762877374158304 9.64225 --16.999863212247497 1.5762877374158304 9.64225 --15.109863212247495 3.43628773741583 9.64225 --13.189863212247493 1.48628773741583 9.64225 --12.919863212247494 1.0062877374158297 9.64225 --12.739863212247494 0.34628773741582985 9.64225 --12.739863212247494 -0.3737122625841701 9.64225 --12.979863212247494 -1.09371226258417 9.64225 --13.459863212247495 -1.7237122625841703 9.64225 --13.999863212247494 -2.08371226258417 9.64225 --14.689863212247495 -2.32371226258417 9.64225 --15.649863212247494 -2.32371226258417 9.64225 --16.339863212247494 -2.05371226258417 9.64225 --16.939863212247495 -1.57371226258417 9.64225 --17.329863212247496 -0.9137122625841699 9.64225 --17.509863212247495 -0.25371226258417 9.64225 -7.756738351254477 -1.9418924731182776 11.32225 -7.60673835125448 -0.38189247311828 11.32225 -7.996738351254475 -0.05189247311827905 11.322249999999997 -8.14673835125448 -2.18189247311828 11.32225 -10.906738351254479 -1.4618924731182803 11.32225 -8.746738351254475 -2.2418924731182805 11.32225 -9.226738351254475 -2.0918924731182775 11.322249999999997 -7.786738351254477 0.7881075268817213 11.32225 -7.426738351254476 -0.891892473118279 11.32225 -7.426738351254478 -1.1618924731182783 11.322249999999993 -11.146738351254479 -1.4918924731182788 11.32225 -11.146738351254477 -2.1518924731182794 11.32225 -8.56673835125448 1.7481075268817183 11.322249999999999 -7.816738351254481 1.5381075268817215 11.32225 -8.05673835125448 0.9081075268817214 11.322249999999999 -8.776738351254474 -1.4318924731182783 11.32225 -8.536738351254476 0.12810752688172422 11.322249999999997 -9.61673835125448 -1.7018924731182792 11.322250000000002 -8.83673835125448 1.1181075268817215 11.322249999999997 -7.546738351254474 -1.6418924731182787 11.322249999999997 -8.536738351254476 -1.1618924731182818 11.32225 -9.316738351254479 1.0581075268817208 11.32225 -9.256738351254473 -1.4318924731182792 11.322250000000002 -10.36673835125448 -2.2418924731182828 11.322249999999997 -10.096738351254476 1.6581075268817225 11.322249999999997 -8.686738351254476 -0.5618924731182797 11.322249999999997 -8.506738351254475 -0.8618924731182792 11.32225 -9.946738351254476 -2.091892473118282 11.322249999999997 -9.496738351254475 1.8081075268817197 11.32225 -9.616738351254476 0.24810752688172077 11.322250000000004 -9.586738351254477 -1.1918924731182794 11.322249999999993 -10.726738351254475 -1.3118924731182808 11.322249999999993 -10.666738351254477 0.8781075268817216 11.32225 -9.586738351254478 0.7881075268817216 11.32225 -9.706738351254476 -1.7918924731182786 11.32225 -9.166738351254473 -0.41189247311827915 11.322249999999997 -10.486738351254473 1.3281075268817206 11.32225 -9.496738351254475 0.21810752688172008 11.322250000000002 -9.61673835125448 -0.44189247311827906 11.322249999999997 -7.4267383512544765 -0.891892473118279 9.67725 -7.606738351254478 -0.3818924731182791 9.67725 -7.996738351254475 -0.05189247311827877 9.67725 -8.536738351254474 0.12810752688172145 9.67725 -9.496738351254475 0.21810752688172086 9.67725 -9.616738351254478 0.24810752688172089 9.67725 -9.586738351254478 0.7881075268817215 9.67725 -9.316738351254479 1.058107526881721 9.67725 -8.836738351254478 1.118107526881721 9.67725 -8.056738351254479 0.9081075268817216 9.67725 -7.786738351254474 0.7881075268817215 9.67725 -7.816738351254479 1.5381075268817215 9.67725 -8.566738351254479 1.748107526881721 9.67725 -9.496738351254475 1.8081075268817215 9.67725 -10.096738351254478 1.6581075268817216 9.67725 -10.486738351254475 1.3281075268817215 9.67725 -10.666738351254477 0.8781075268817216 9.67725 -10.726738351254475 -1.311892473118279 9.67725 -10.906738351254477 -1.461892473118279 9.67725 -11.146738351254477 -1.4918924731182792 9.67725 -11.146738351254477 -2.15189247311828 9.67725 -10.366738351254478 -2.241892473118279 9.67725 -9.946738351254476 -2.0918924731182797 9.67725 -9.706738351254476 -1.7918924731182795 9.67725 -9.616738351254478 -1.7018924731182796 9.67725 -9.226738351254475 -2.0918924731182797 9.67725 -8.746738351254475 -2.241892473118279 9.67725 -8.146738351254477 -2.1818924731182796 9.67725 -7.756738351254475 -1.9418924731182798 9.67725 -7.546738351254474 -1.6418924731182791 9.67725 -7.4267383512544765 -1.1618924731182791 9.67725 -8.536738351254474 -1.1618924731182791 9.67725 -8.686738351254476 -0.5618924731182792 9.67725 -8.506738351254475 -0.861892473118279 9.67725 -9.586738351254478 -1.1918924731182794 9.67725 -9.256738351254475 -1.4318924731182792 9.67725 -9.616738351254478 -0.44189247311827906 9.67725 -9.166738351254477 -0.41189247311827915 9.67725 -8.776738351254474 -1.4318924731182792 9.67725 -671 426 Edge Vertex Indices Starting from 1 -426 107 -647 646 -646 645 -633 261 -672 455 -431 417 -417 101 -193 174 -174 172 -80 63 -627 247 -190 176 -176 175 -191 190 -190 175 -188 172 -172 171 -481 143 -83 63 -18 17 -17 16 -142 137 -137 127 -85 67 -67 66 -85 68 -68 67 -736 731 -731 685 -671 107 -667 148 -661 148 -193 191 -191 174 -20 19 -19 14 -190 177 -177 176 -19 15 -15 14 -448 434 -434 431 -481 249 -249 33 -19 18 -18 16 -19 16 -16 15 -484 247 -665 425 -708 674 -24 23 -23 12 -188 171 -171 170 -694 677 -677 666 -191 175 -175 174 -193 172 -153 128 -142 127 -127 126 -627 626 -626 247 -20 14 -14 13 -30 12 -710 673 -673 667 -366 352 -352 335 -32 6 -597 276 -34 7 -470 453 -34 32 -32 7 -33 32 -195 33 -280 279 -296 280 -300 285 -187 170 -170 169 -295 278 -314 312 -402 314 -639 637 -637 522 -474 458 -389 373 -358 342 -40 17 -646 627 -194 181 -181 180 -328 310 -44 43 -43 3 -44 3 -92 63 -111 84 -401 317 -317 315 -404 289 -289 288 -43 2 -624 600 -45 2 -562 549 -46 20 -510 494 -731 702 -702 701 -38 35 -49 38 -643 630 -348 347 -363 348 -679 152 -44 4 -222 219 -219 214 -402 313 -313 310 -38 15 -683 665 -665 426 -49 15 -363 362 -408 363 -42 23 -323 322 -322 306 -481 195 -195 143 -52 23 -569 558 -558 552 -55 12 -724 665 -55 37 -37 12 -614 604 -604 567 -153 152 -152 128 -434 417 -735 733 -733 716 -673 146 -53 5 -620 564 -621 620 -366 365 -408 366 -494 493 -509 494 -596 328 -251 43 -57 56 -56 29 -57 29 -293 291 -399 293 -287 286 -301 287 -56 26 -30 27 -60 30 -339 338 -354 339 -61 59 -59 28 -61 28 -467 453 -453 452 -509 493 -210 209 -209 182 -615 605 -605 604 -391 271 -357 341 -597 274 -413 404 -404 99 -417 100 -562 555 -555 549 -512 497 -497 496 -569 552 -616 569 -253 229 -254 253 -505 489 -402 312 -658 641 -326 309 -596 327 -292 291 -291 274 -328 312 -330 328 -598 349 -365 349 -610 568 -253 41 -325 323 -323 307 -640 639 -639 522 -324 308 -625 615 -615 604 -412 361 -361 360 -501 485 -659 643 -643 642 -592 503 -399 296 -296 295 -325 307 -408 362 -412 408 -401 318 -318 317 -399 281 -291 275 -275 274 -459 458 -475 459 -295 294 -399 295 -195 34 -325 308 -53 6 -621 611 -611 610 -256 51 -470 454 -454 453 -350 349 -365 350 -323 306 -596 329 -362 346 -607 563 -281 280 -296 281 -326 324 -324 309 -597 275 -332 315 -333 332 -506 490 -278 277 -294 278 -327 310 -328 327 -566 560 -399 294 -294 293 -39 35 -282 280 -485 484 -499 485 -341 340 -356 341 -616 615 -615 569 -497 481 -401 305 -305 303 -554 467 -508 491 -597 278 -412 360 -360 359 -252 43 -638 629 -629 488 -211 39 -554 470 -470 467 -320 286 -299 284 -251 53 -46 21 -47 46 -576 546 -620 609 -642 411 -282 281 -297 282 -623 613 -613 612 -596 330 -330 329 -585 574 -618 608 -608 607 -503 489 -489 488 -582 571 -466 449 -408 336 -366 335 -622 611 -619 608 -36 35 -195 36 -554 469 -61 30 -647 626 -408 365 -365 364 -302 287 -195 54 -54 36 -256 47 -623 612 -55 48 -48 37 -597 277 -479 464 -464 463 -480 464 -597 279 -331 314 -401 303 -346 345 -361 346 -404 290 -290 289 -540 524 -251 44 -598 335 -329 312 -331 329 -329 314 -408 352 -328 313 -313 312 -285 284 -299 285 -330 312 -333 315 -404 292 -292 290 -614 602 -284 283 -298 284 -58 26 -638 488 -483 247 -669 150 -246 231 -231 230 -78 77 -79 78 -736 685 -84 65 -86 71 -87 86 -80 77 -81 80 -561 560 -560 550 -534 409 -264 262 -93 92 -92 64 -93 64 -363 347 -430 104 -479 477 -477 405 -93 65 -417 414 -414 413 -94 93 -93 66 -431 101 -96 67 -616 605 -97 68 -446 445 -558 446 -98 97 -97 69 -98 69 -100 71 -445 428 -101 72 -102 101 -101 73 -165 163 -163 162 -362 347 -347 346 -103 74 -451 94 -104 75 -718 670 -670 664 -452 94 -518 410 -105 77 -429 428 -445 429 -451 95 -583 550 -584 583 -79 63 -107 79 -107 63 -446 429 -539 523 -601 600 -624 601 -352 336 -412 362 -362 361 -598 348 -242 229 -229 228 -50 20 -101 100 -100 72 -514 210 -394 377 -102 73 -439 410 -562 411 -411 403 -605 567 -106 78 -108 88 -88 82 -364 349 -349 348 -478 405 -113 80 -413 375 -375 374 -364 348 -109 90 -90 88 -611 568 -608 563 -596 401 -591 570 -592 579 -594 592 -624 613 -599 385 -421 420 -437 421 -374 373 -413 374 -573 546 -546 545 -350 335 -598 350 -463 404 -450 95 -453 92 -605 563 -557 549 -517 410 -599 408 -538 537 -593 538 -582 572 -572 571 -520 410 -505 490 -490 489 -621 610 -598 408 -462 404 -618 552 -619 618 -437 420 -402 399 -596 402 -572 545 -461 406 -117 90 -461 404 -188 170 -113 81 -118 113 -506 400 -508 506 -196 167 -584 574 -574 573 -414 412 -597 399 -494 406 -460 406 -413 99 -534 532 -532 409 -614 567 -515 514 -529 515 -396 378 -438 422 -368 367 -416 368 -588 577 -420 414 -625 604 -414 410 -410 409 -531 515 -591 581 -581 570 -625 614 -614 603 -106 79 -107 106 -419 418 -433 419 -387 385 -385 370 -562 560 -560 411 -406 403 -493 406 -510 509 -509 400 -352 351 -351 335 -382 367 -383 382 -416 370 -370 369 -192 180 -180 179 -427 107 -593 537 -537 536 -567 551 -602 567 -715 692 -437 436 -436 421 -439 414 -586 549 -587 586 -418 414 -453 91 -357 342 -342 341 -476 400 -532 517 -517 516 -491 403 -109 88 -435 419 -599 387 -396 379 -464 404 -366 350 -396 393 -393 378 -524 523 -539 524 -493 403 -534 517 -599 384 -617 606 -437 412 -428 107 -622 612 -612 611 -373 372 -413 373 -491 490 -506 491 -421 414 -439 422 -593 539 -539 538 -490 403 -599 386 -386 385 -553 547 -547 391 -581 571 -571 570 -525 524 -540 525 -420 419 -435 420 -416 369 -369 368 -599 416 -416 408 -412 409 -436 412 -386 384 -384 368 -508 400 -598 347 -387 370 -450 96 -386 368 -606 563 -599 413 -535 533 -533 409 -449 98 -408 364 -364 363 -538 523 -523 522 -398 382 -541 525 -613 600 -600 565 -562 550 -394 392 -392 376 -622 554 -623 622 -618 607 -507 493 -493 492 -573 545 -431 102 -464 449 -449 404 -428 427 -444 428 -562 407 -384 367 -478 476 -476 405 -509 507 -507 400 -429 106 -492 403 -114 109 -109 108 -395 379 -394 376 -519 410 -384 383 -383 367 -428 106 -419 414 -562 403 -587 577 -577 576 -619 609 -609 608 -596 399 -597 596 -355 339 -617 552 -618 617 -480 479 -479 405 -393 377 -599 383 -412 359 -359 358 -594 579 -114 110 -110 109 -115 110 -30 24 -24 12 -632 247 -26 8 -8 7 -129 128 -128 127 -115 111 -111 110 -134 120 -120 119 -135 134 -134 119 -139 130 -140 120 -141 136 -136 123 -144 143 -143 119 -144 119 -334 303 -203 175 -298 283 -145 120 -532 516 -516 515 -502 501 -556 502 -392 341 -600 548 -147 122 -460 459 -475 460 -585 584 -586 585 -418 417 -434 418 -584 550 -550 549 -592 400 -533 518 -534 533 -495 458 -556 501 -501 499 -415 409 -416 367 -154 129 -407 400 -592 407 -399 291 -638 489 -489 403 -351 336 -353 351 -583 572 -592 556 -157 133 -133 119 -260 259 -259 236 -145 144 -144 120 -80 79 -79 77 -147 146 -146 122 -148 124 -616 606 -606 605 -542 526 -526 525 -149 125 -587 575 -162 136 -164 135 -166 134 -479 463 -463 462 -578 576 -166 140 -140 134 -587 576 -576 575 -597 388 -388 274 -548 332 -559 540 -540 539 -570 559 -593 570 -590 579 -519 518 -533 519 -595 591 -591 580 -321 304 -296 279 -279 278 -592 506 -506 505 -598 398 -599 598 -575 546 -389 274 -569 446 -564 554 -622 564 -518 517 -534 518 -612 565 -359 343 -343 342 -516 439 -439 438 -609 568 -621 564 -622 621 -164 139 -354 337 -559 541 -541 540 -322 321 -321 306 -571 559 -118 117 -117 113 -495 459 -402 315 -579 556 -402 310 -160 158 -504 486 -206 157 -594 407 -535 519 -401 315 -402 401 -558 542 -559 558 -201 143 -563 553 -567 563 -334 318 -318 303 -292 273 -296 278 -354 338 -338 337 -316 314 -402 316 -620 610 -610 609 -542 525 -566 415 -595 566 -566 561 -157 119 -583 582 -582 550 -565 548 -548 547 -620 619 -619 564 -398 383 -599 398 -558 444 -444 443 -372 371 -416 372 -613 565 -532 515 -571 545 -475 458 -448 430 -459 406 -494 459 -573 572 -583 573 -479 462 -415 411 -560 415 -611 565 -617 607 -607 606 -520 519 -535 520 -292 274 -274 273 -568 565 -565 547 -412 358 -413 412 -301 300 -304 301 -589 578 -578 577 -556 546 -578 556 -586 584 -584 549 -413 372 -416 413 -165 140 -166 165 -556 499 -205 157 -595 415 -319 303 -153 129 -154 153 -542 541 -559 542 -592 505 -505 503 -575 573 -340 339 -355 340 -457 143 -578 546 -359 342 -584 573 -388 387 -387 372 -588 549 -456 144 -504 487 -487 486 -536 535 -535 409 -569 447 -447 446 -594 590 -590 557 -371 370 -416 371 -595 561 -200 143 -580 570 -593 580 -568 563 -608 568 -445 444 -558 445 -579 578 -589 579 -455 454 -469 455 -555 407 -594 555 -619 552 -590 589 -589 557 -360 344 -344 343 -404 399 -399 292 -589 577 -551 345 -499 484 -500 499 -283 282 -297 283 -356 340 -405 400 -406 405 -202 143 -166 135 -448 431 -431 430 -471 455 -484 483 -500 484 -552 545 -564 552 -595 580 -415 410 -598 412 -457 144 -593 559 -559 539 -564 545 -553 551 -567 553 -302 271 -591 561 -516 410 -288 271 -302 288 -425 152 -476 460 -161 136 -162 161 -599 388 -602 551 -551 412 -404 302 -433 418 -434 433 -458 457 -473 458 -360 343 -353 337 -334 333 -333 318 -557 555 -594 557 -589 588 -588 557 -480 466 -466 464 -603 434 -387 371 -404 288 -320 319 -319 305 -617 616 -616 552 -333 317 -203 143 -587 549 -588 587 -536 520 -470 469 -469 454 -512 474 -474 473 -683 666 -666 665 -174 173 -173 172 -221 184 -183 182 -182 181 -673 148 -187 169 -194 180 -323 284 -270 269 -269 262 -393 339 -389 273 -197 168 -355 354 -379 355 -504 502 -556 504 -196 195 -195 167 -199 170 -354 353 -380 354 -598 351 -673 147 -672 456 -456 146 -510 400 -396 395 -395 338 -404 98 -204 203 -203 176 -597 280 -496 458 -514 423 -423 210 -553 342 -378 355 -379 378 -218 190 -496 481 -481 457 -211 210 -210 182 -211 182 -543 443 -443 442 -302 301 -305 302 -561 550 -582 561 -200 199 -199 171 -200 171 -379 354 -380 379 -670 107 -107 91 -210 208 -438 423 -515 438 -496 457 -298 297 -309 298 -325 324 -324 282 -380 353 -381 380 -322 286 -358 357 -376 358 -392 342 -553 392 -208 207 -207 179 -208 179 -394 393 -393 340 -320 287 -547 320 -297 281 -311 297 -213 192 -192 185 -212 192 -602 435 -435 433 -215 187 -187 186 -390 273 -548 333 -215 186 -397 337 -198 196 -402 311 -311 281 -217 212 -212 185 -217 185 -219 193 -193 188 -214 193 -480 405 -601 480 -376 375 -375 358 -596 280 -599 597 -597 413 -548 334 -334 319 -500 498 -498 469 -597 404 -396 338 -627 484 -353 336 -381 353 -531 432 -432 422 -357 356 -377 357 -325 282 -382 381 -381 336 -398 351 -351 337 -510 476 -476 475 -325 283 -548 319 -322 284 -416 336 -652 633 -436 409 -532 436 -601 466 -531 422 -500 469 -398 337 -327 280 -603 433 -553 391 -323 283 -547 319 -602 433 -603 602 -551 344 -592 504 -322 285 -215 189 -216 215 -377 356 -378 377 -326 280 -356 355 -378 356 -516 438 -598 346 -326 282 -543 542 -542 443 -309 297 -311 309 -222 214 -214 187 -396 339 -222 187 -413 358 -544 543 -543 442 -601 465 -551 346 -598 551 -394 340 -497 473 -473 472 -515 423 -305 301 -581 561 -582 581 -397 338 -558 443 -510 475 -475 474 -304 300 -306 304 -321 286 -416 382 -382 336 -532 531 -531 436 -394 341 -401 302 -554 499 -499 469 -402 281 -210 207 -376 357 -377 376 -308 298 -309 308 -512 473 -472 457 -457 456 -190 185 -185 177 -699 668 -241 234 -234 231 -239 238 -238 223 -243 234 -241 231 -246 241 -220 184 -249 248 -248 225 -712 688 -250 249 -249 225 -250 225 -251 250 -250 227 -90 77 -77 76 -252 227 -253 228 -473 457 -255 230 -234 233 -233 231 -648 626 -257 232 -663 660 -660 152 -258 233 -720 719 -719 716 -259 235 -189 181 -261 237 -237 223 -247 237 -634 524 -635 524 -248 224 -250 226 -252 251 -251 227 -253 252 -252 228 -719 717 -717 716 -254 229 -655 639 -257 256 -256 232 -697 689 -260 236 -630 411 -642 630 -263 262 -262 241 -263 241 -267 238 -243 241 -262 243 -635 634 -654 635 -629 628 -628 488 -257 233 -258 257 -260 258 -628 487 -656 639 -654 634 -647 627 -530 441 -441 440 -111 85 -85 84 -636 634 -634 525 -652 636 -636 633 -270 238 -269 243 -711 688 -688 672 -641 411 -156 132 -209 181 -692 670 -670 91 -113 109 -665 663 -663 425 -711 672 -498 472 -472 471 -710 667 -25 3 -3 2 -704 693 -693 689 -482 249 -668 661 -661 149 -714 692 -718 717 -719 718 -674 667 -667 662 -705 693 -702 662 -720 687 -687 683 -112 84 -84 83 -729 669 -705 681 -202 173 -709 708 -710 709 -245 224 -736 735 -735 703 -707 681 -150 149 -149 126 -62 57 -57 31 -679 669 -669 152 -90 76 -648 632 -632 626 -649 632 -708 678 -669 151 -511 510 -510 474 -736 702 -707 678 -712 707 -707 706 -240 228 -228 227 -165 160 -149 148 -148 125 -544 441 -210 157 -92 91 -91 63 -688 684 -684 455 -691 664 -711 707 -712 711 -136 124 -124 123 -735 704 -704 703 -233 232 -232 231 -713 712 -712 706 -112 110 -110 84 -717 664 -696 684 -714 696 -86 82 -82 72 -498 497 -497 472 -710 708 -711 710 -390 389 -389 374 -737 725 -725 724 -50 19 -714 684 -726 663 -725 663 -717 691 -688 455 -710 672 -692 691 -691 670 -449 97 -729 699 -699 669 -694 666 -698 695 -695 690 -737 724 -736 703 -703 702 -450 97 -711 708 -708 707 -62 31 -31 25 -721 687 -706 681 -242 228 -725 665 -117 109 -514 211 -211 46 -514 46 -25 4 -4 3 -27 10 -10 9 -156 155 -155 132 -214 188 -188 187 -512 511 -511 474 -31 4 -696 692 -692 91 -31 5 -5 4 -33 6 -36 11 -36 10 -40 39 -39 17 -211 50 -50 46 -478 477 -477 461 -477 462 -462 461 -49 48 -48 15 -48 14 -52 51 -51 22 -52 22 -53 44 -44 5 -163 161 -54 34 -34 8 -54 8 -103 102 -102 74 -478 460 -478 461 -461 460 -50 40 -40 18 -50 18 -253 45 -252 45 -45 43 -704 689 -211 40 -528 257 -260 257 -650 632 -650 631 -61 60 -60 59 -60 58 -544 442 -442 441 -195 32 -211 195 -195 39 -195 35 -600 401 -548 401 -596 548 -116 111 -687 666 -290 272 -290 273 -273 272 -294 276 -294 277 -277 276 -361 344 -361 345 -345 344 -327 326 -326 310 -326 311 -311 310 -657 641 -641 637 -289 271 -289 272 -272 271 -301 285 -301 286 -286 285 -500 482 -500 483 -483 482 -332 331 -331 316 -332 316 -316 315 -51 47 -47 21 -51 21 -512 495 -512 496 -496 495 -511 494 -511 495 -495 494 -663 152 -49 37 -49 35 -83 65 -65 63 -218 217 -217 190 -65 64 -64 63 -90 81 -81 77 -96 95 -95 67 -508 507 -507 491 -507 492 -492 491 -105 104 -104 76 -105 76 -106 105 -105 78 -268 264 -386 370 -386 369 -97 96 -96 68 -100 99 -99 71 -202 201 -201 173 -104 103 -103 75 -113 112 -112 80 -112 83 -83 80 -114 108 -108 86 -108 82 -439 421 -422 421 -436 422 -538 521 -538 522 -522 521 -389 388 -388 373 -388 372 -431 103 -430 103 -452 92 -94 92 -397 395 -395 381 -395 380 -521 410 -521 411 -411 410 -398 397 -397 382 -397 381 -543 526 -543 527 -527 526 -414 409 -89 70 -70 69 -544 527 -544 528 -528 527 -586 574 -586 575 -575 574 -443 426 -442 426 -426 425 -537 520 -537 521 -521 520 -417 413 -413 100 -118 81 -117 81 -429 104 -106 104 -133 132 -132 131 -139 135 -135 131 -139 131 -131 130 -456 145 -504 503 -503 487 -503 488 -488 487 -152 151 -151 128 -151 127 -593 536 -536 409 -155 131 -625 603 -615 603 -603 569 -146 145 -145 122 -145 121 -559 545 -558 545 -466 465 -465 449 -465 450 -450 449 -159 158 -158 139 -159 139 -139 137 -160 159 -159 142 -159 137 -441 423 -441 424 -424 423 -624 623 -623 601 -623 554 -637 521 -637 411 -468 451 -465 451 -451 450 -425 153 -444 427 -443 427 -427 426 -407 403 -403 400 -406 400 -442 424 -442 425 -425 424 -293 276 -291 276 -276 275 -596 332 -596 331 -472 456 -471 456 -456 455 -498 482 -497 482 -482 481 -199 196 -199 143 -196 143 -468 467 -467 452 -468 452 -452 451 -204 157 -203 157 -157 143 -321 320 -320 304 -320 305 -305 304 -156 154 -156 153 -603 448 -569 448 -448 447 -194 184 -184 181 -632 631 -631 261 -218 216 -628 486 -498 471 -471 469 -632 261 -261 247 -211 167 -211 183 -183 167 -199 198 -198 170 -203 202 -202 175 -202 174 -659 653 -653 643 -219 218 -218 191 -219 191 -308 307 -307 299 -308 299 -299 298 -197 196 -196 168 -30 28 -28 24 -307 306 -306 300 -307 300 -300 299 -207 157 -481 33 -553 343 -551 343 -391 272 -390 272 -667 661 -86 72 -72 71 -237 236 -236 235 -270 267 -630 403 -256 255 -255 232 -255 231 -636 525 -659 658 -658 657 -157 156 -156 133 -88 76 -76 75 -268 265 -255 254 -254 230 -261 260 -260 237 -718 664 -530 440 -654 653 -656 654 -656 655 -655 654 -653 652 -652 650 -652 651 -651 650 -254 41 -640 522 -26 9 -9 8 -58 56 -683 426 -669 668 -668 150 -668 149 -734 723 -734 724 -724 723 -729 679 -700 668 -700 661 -113 110 -27 9 -673 672 -672 146 -638 403 -702 676 -676 662 -678 674 -676 674 -674 662 -703 689 -721 694 -694 687 -23 22 -22 13 -23 13 -13 12 -636 261 -22 21 -21 13 -21 20 -20 13 -736 698 -736 695 -42 1 -42 24 -24 1 -27 12 -12 11 -27 11 -11 10 -568 553 -568 547 -250 33 -250 53 -53 33 -37 35 -35 11 -37 11 -649 648 -648 644 -245 240 -240 226 -240 227 -227 226 -246 229 -246 230 -230 229 -85 66 -84 66 -66 65 -595 593 -593 415 -593 409 -640 523 -635 523 -95 94 -94 67 -94 66 -45 41 -41 1 -45 1 -447 429 -447 430 -430 429 -116 115 -115 89 -115 87 -115 114 -114 87 -114 86 -116 85 -116 89 -89 85 -644 630 -644 638 -638 630 -696 453 -696 91 -89 87 -87 70 -87 71 -71 70 -148 147 -147 124 -147 123 -728 679 -727 679 -679 660 -99 98 -98 70 -99 70 -163 136 -163 138 -138 136 -502 486 -501 486 -486 485 -544 530 -530 528 -530 513 -406 401 -406 404 -404 401 -438 432 -440 438 -440 423 -601 405 -600 405 -405 401 -28 25 -25 2 -183 181 -189 183 -201 200 -200 173 -200 172 -221 216 -216 189 -221 189 -189 184 -531 529 -529 432 -529 440 -440 432 -601 554 -554 468 -601 468 -468 465 -530 529 -529 513 -529 514 -514 513 -547 271 -547 287 -287 271 -29 26 -26 7 -29 7 -7 6 -697 678 -678 676 -653 634 -652 634 -88 74 -88 75 -75 74 -264 263 -263 242 -263 246 -246 242 -266 265 -265 245 -265 240 -265 264 -264 240 -264 242 -242 240 -268 266 -266 244 -266 245 -245 244 -528 260 -527 260 -735 716 -716 715 -735 715 -715 704 -138 124 -138 125 -125 124 -31 29 -29 5 -29 6 -6 5 -255 41 -255 42 -42 41 -645 638 -645 629 -727 660 -726 660 -723 677 -735 698 -733 698 -698 690 -715 714 -714 705 -715 705 -705 704 -185 178 -178 177 -732 730 -730 686 -730 680 -483 249 -483 248 -142 125 -142 126 -126 125 -89 68 -89 69 -69 68 -724 666 -723 666 -186 169 -169 167 -169 168 -168 167 -734 733 -733 690 -734 690 -690 682 -733 723 -723 722 -733 722 -722 716 -714 713 -713 705 -713 706 -706 705 -716 691 -715 691 -720 683 -719 683 -683 671 -165 158 -82 74 -74 73 -82 73 -73 72 -719 671 -718 671 -671 670 -701 662 -700 662 -662 661 -737 726 -726 725 -155 154 -154 130 -155 130 -696 454 -684 454 -732 686 -731 686 -686 685 -209 208 -208 180 -209 180 -722 721 -721 720 -722 720 -720 716 -39 38 -38 17 -38 16 -54 9 -36 9 -222 218 -392 391 -391 375 -392 375 -602 412 -435 412 -437 435 -133 131 -135 133 -135 119 -137 130 -130 127 -130 129 -129 127 -151 150 -150 126 -151 126 -163 160 -160 138 -160 142 -142 138 -556 554 -564 556 -564 546 -391 390 -390 375 -390 374 -198 197 -197 169 -198 169 -628 627 -627 485 -628 485 -703 676 -703 697 -697 676 -205 204 -204 176 -205 176 -207 206 -206 178 -207 178 -220 194 -213 194 -194 192 -709 674 -709 667 -248 247 -247 223 -248 223 -651 631 -651 633 -633 631 -259 258 -258 235 -258 234 -659 657 -657 656 -659 656 -656 653 -649 644 -644 643 -659 642 -658 642 -642 641 -646 629 -646 628 -210 156 -657 639 -657 637 -713 688 -713 684 -141 121 -140 121 -121 120 -423 156 -528 513 -513 257 -513 256 -732 728 -730 728 -728 727 -28 1 -28 2 -2 1 -722 677 -721 677 -729 728 -732 729 -732 699 -141 123 -123 121 -123 122 -122 121 -636 526 -636 527 -527 261 -62 59 -59 58 -62 58 -58 57 -55 14 -55 13 -62 25 -59 25 -513 46 -256 46 -648 647 -647 645 -648 645 -645 644 -655 640 -654 640 -640 635 -165 162 -162 141 -165 141 -141 140 -189 186 -186 183 -186 167 -206 205 -205 177 -206 177 -256 52 -255 52 -52 42 -697 693 -693 681 -697 681 -681 678 -244 224 -238 224 -224 223 -732 731 -731 701 -737 675 -730 675 -270 262 -268 262 -192 178 -192 179 -179 178 -166 158 -166 164 -164 158 -686 682 -695 685 -690 685 -685 682 -737 730 -730 727 -737 727 -727 726 -60 26 -60 27 -27 26 -222 215 -218 215 -270 268 -268 244 -270 244 -244 238 -237 235 -239 237 -239 223 -243 239 -239 235 -243 235 -235 234 -653 650 -650 643 -650 649 -649 643 -732 701 -701 699 -701 700 -700 699 -221 217 -217 216 -220 213 -213 212 -424 153 -423 153 -737 734 -734 675 -734 682 -682 675 -686 680 -682 680 -680 675 -245 226 -226 225 -245 225 -225 224 -269 267 -267 239 -269 239 -221 220 -220 212 -221 212 -1 2 31 Face Edge Indices Starting from 1 -2161 3 4 -1709 2105 5 -6 1683 1035 -388 7 8 -9 10 61 -11 419 744 -12 50 1126 -16 13 14 -59 15 16 -17 18 55 -899 1052 19 -11 1569 20 -21 22 47 -63 23 24 -25 26 1842 -27 28 25 -29 30 366 -2027 31 1067 -1747 32 33 -33 1362 1320 -9 34 35 -36 37 67 -13 38 39 -40 41 37 -949 42 43 -44 45 1742 -46 47 48 -48 49 40 -50 360 952 -130 51 1609 -52 1801 1351 -53 54 682 -55 56 496 -57 58 1408 -35 59 60 -17 1111 61 -62 686 890 -1992 63 64 -65 66 12 -67 68 1815 -1821 171 69 -1313 70 71 -72 73 312 -1933 79 74 -1501 329 75 -1463 76 685 -289 77 178 -78 79 76 -80 1487 81 -82 778 83 -84 350 1740 -85 86 1016 -87 262 237 -88 200 89 -90 91 215 -92 981 1007 -1393 93 464 -561 1080 94 -21 1471 95 -96 2083 2119 -97 98 1017 -347 99 127 -102 100 101 -1428 123 102 -103 1541 377 -1382 689 104 -105 106 817 -994 107 108 -1315 101 109 -460 110 628 -1475 111 109 -719 630 112 -1814 293 113 -160 538 114 -115 116 2188 -117 1535 118 -1272 223 119 -120 379 121 -1246 1882 122 -1441 1460 123 -124 125 1175 -126 127 811 -49 2050 128 -1784 129 130 -118 131 128 -132 228 133 -53 1819 134 -249 135 136 -19 137 138 -2179 139 134 -195 140 141 -1810 2155 142 -143 1009 1997 -144 145 142 -511 146 147 -148 149 62 -43 150 7 -151 152 1958 -1034 153 746 -1968 241 154 -155 797 156 -157 320 158 -159 180 160 -161 207 302 -100 341 162 -165 163 164 -1965 1344 165 -166 731 167 -168 1515 169 -1930 164 170 -171 2208 172 -173 828 174 -177 175 176 -1735 318 177 -1691 178 179 -180 636 648 -1054 181 182 -183 184 218 -1513 1745 185 -1131 186 273 -234 257 187 -508 188 189 -8 190 433 -112 191 192 -1528 193 194 -195 998 196 -197 1265 198 -307 895 199 -200 348 126 -1759 201 1509 -1174 1507 202 -203 264 161 -868 204 205 -206 351 207 -247 469 208 -321 209 445 -210 796 833 -1853 1473 211 -227 212 213 -214 215 1780 -1212 256 216 -217 218 520 -282 219 220 -271 725 221 -222 223 2115 -224 1626 1159 -238 225 226 -1729 240 227 -228 427 229 -230 231 105 -232 254 225 -205 233 234 -235 854 236 -237 266 238 -1462 323 239 -1075 240 216 -241 1442 1829 -242 243 484 -1456 2177 244 -77 245 246 -247 209 248 -1737 213 249 -344 1680 250 -428 251 337 -252 617 865 -253 83 254 -202 255 256 -257 1678 75 -258 352 259 -781 260 482 -261 1500 262 -263 99 264 -265 372 837 -167 266 267 -2048 268 117 -253 298 269 -270 940 271 -272 944 273 -196 274 275 -1051 194 276 -277 278 335 -1690 1920 279 -500 280 588 -779 333 281 -675 282 283 -284 162 1259 -285 286 359 -1445 1477 287 -279 288 289 -168 1089 290 -291 357 1732 -292 1828 1233 -293 1525 294 -295 784 764 -843 296 664 -2117 297 1302 -298 1091 299 -300 301 326 -302 303 250 -714 304 502 -305 306 635 -1628 307 308 -1191 309 598 -640 991 310 -426 346 311 -468 572 312 -798 313 242 -488 314 305 -315 1490 316 -1004 288 317 -318 172 1482 -319 65 1289 -622 320 321 -1058 322 169 -323 324 316 -1524 244 325 -634 326 583 -327 328 144 -261 281 329 -758 330 331 -671 332 330 -82 1043 333 -830 1521 334 -825 230 335 -336 1503 337 -107 338 339 -576 769 340 -1459 292 341 -342 541 1033 -345 343 88 -334 344 345 -158 346 72 -206 347 348 -349 291 350 -303 351 343 -106 999 352 -338 353 354 -1157 527 355 -356 703 357 -358 170 1783 -359 308 732 -1990 360 2100 -1352 361 2067 -362 363 1840 -364 745 365 -366 2200 1817 -367 1536 1331 -368 1875 369 -370 1543 371 -1060 372 373 -620 722 374 -375 1273 1941 -378 376 377 -1540 383 378 -379 404 132 -380 1617 1858 -672 381 382 -387 383 1844 -1613 384 385 -1852 386 387 -400 639 388 -28 1559 389 -274 390 183 -1996 395 391 -392 924 393 -396 394 395 -1600 1884 396 -1749 434 397 -643 923 398 -2024 401 399 -400 401 437 -2167 402 403 -251 404 405 -1940 1565 406 -1850 416 407 -1551 408 1763 -1769 409 410 -407 1693 411 -475 789 412 -364 1554 413 -414 398 415 -416 471 1665 -417 718 418 -419 421 420 -1068 421 1367 -422 415 392 -423 624 592 -424 110 425 -734 540 426 -219 427 428 -446 208 429 -430 431 1421 -113 1448 432 -399 433 434 -1424 435 1053 -1087 436 673 -2022 1466 437 -521 556 438 -661 439 440 -441 147 184 -528 442 365 -1572 443 444 -451 445 446 -382 1449 447 -371 497 448 -449 450 465 -451 121 623 -567 452 453 -210 243 454 -455 252 306 -456 818 491 -457 919 776 -458 677 459 -1658 460 300 -461 532 569 -462 489 463 -464 586 465 -466 467 638 -468 342 469 -486 759 470 -1544 615 471 -472 1584 179 -473 823 441 -192 986 474 -967 565 475 -476 485 783 -477 549 478 -479 480 309 -656 866 481 -199 482 483 -156 484 832 -229 958 485 -495 1452 486 -487 931 488 -2059 489 603 -490 666 491 -853 480 492 -507 1469 493 -494 452 1423 -1896 493 495 -1434 496 85 -497 1615 498 -499 612 500 -501 2002 1734 -502 503 902 -873 385 504 -936 1124 505 -537 159 506 -856 712 507 -1614 508 1560 -374 509 510 -552 355 511 -512 1925 513 -570 514 1049 -1130 1898 515 -516 727 517 -1002 518 662 -660 602 519 -520 146 526 -521 522 1598 -1915 523 513 -524 525 457 -526 527 1636 -528 420 529 -530 978 531 -532 533 614 -534 535 439 -536 577 537 -1037 538 539 -73 540 541 -542 658 543 -544 545 604 -546 547 2194 -548 2 1669 -549 550 1633 -551 975 552 -1980 553 1321 -463 554 555 -589 1573 556 -557 1001 558 -559 384 716 -560 1366 472 -186 561 562 -563 945 647 -705 564 565 -593 587 566 -567 443 653 -531 1097 568 -569 903 974 -1038 570 654 -470 331 571 -572 248 157 -514 573 574 -575 423 576 -651 637 577 -578 564 509 -610 594 579 -997 580 749 -609 554 581 -582 548 642 -583 584 313 -585 882 586 -587 260 588 -519 462 589 -795 590 515 -591 592 478 -733 483 593 -594 595 461 -596 597 1153 -598 599 525 -600 340 601 -602 568 603 -604 605 517 -606 607 476 -608 1145 609 -616 610 611 -649 1546 612 -120 429 613 -915 993 614 -1414 615 1558 -605 1557 616 -617 473 750 -618 883 606 -910 619 620 -621 1040 641 -622 623 133 -1577 624 625 -626 543 845 -601 802 627 -851 628 629 -630 373 534 -655 631 632 -633 1660 634 -670 635 864 -1548 636 637 -638 492 858 -1465 1582 639 -571 640 641 -642 1667 643 -929 191 644 -516 611 645 -447 646 647 -539 648 649 -650 659 414 -566 1549 651 -652 653 1570 -1066 1588 654 -1210 436 655 -412 773 656 -645 657 658 -529 582 659 -559 530 660 -1670 644 661 -662 663 763 -664 665 314 -666 505 667 -668 174 1024 -669 487 670 -1113 671 672 -574 673 1164 -657 579 674 -675 676 872 -772 913 677 -678 679 652 -678 1862 680 -681 682 69 -1349 683 66 -1931 684 685 -686 687 2066 -680 688 689 -693 690 691 -692 693 2062 -2063 1651 694 -762 695 690 -2143 696 697 -698 699 700 -691 743 700 -1121 701 889 -1042 702 14 -703 943 1073 -1641 704 2127 -705 706 852 -707 724 708 -709 562 1082 -710 841 629 -2145 1879 711 -712 236 713 -714 880 715 -716 150 717 -718 719 881 -720 499 780 -721 790 722 -235 808 723 -724 725 886 -726 522 957 -727 542 1199 -2065 2034 728 -729 720 730 -731 204 937 -732 733 1798 -734 1127 735 -839 736 479 -737 810 458 -838 738 739 -740 741 1270 -704 742 743 -744 745 370 -711 746 747 -1964 1363 748 -749 750 390 -751 752 834 -1993 1342 753 -558 754 1605 -696 2168 755 -1621 799 756 -692 948 757 -758 759 860 -877 760 663 -757 761 762 -763 764 754 -187 765 766 -767 259 1101 -768 769 961 -770 960 771 -772 926 932 -773 721 774 -775 776 956 -777 1197 804 -778 779 827 -894 780 781 -782 846 783 -784 466 896 -766 1579 785 -140 786 393 -787 633 788 -789 578 790 -791 863 584 -792 793 901 -1168 794 795 -796 922 665 -797 788 798 -799 1649 2198 -1031 800 983 -801 802 768 -803 804 136 -599 805 770 -498 806 807 -857 1532 808 -1523 831 809 -810 879 925 -811 1508 1105 -1648 1652 812 -1026 813 1889 -814 887 2174 -815 730 459 -816 774 619 -817 809 818 -819 893 820 -918 1908 821 -822 964 823 -824 825 701 -354 826 1497 -226 827 87 -828 829 800 -830 89 831 -832 833 296 -892 834 627 -835 862 265 -917 836 837 -838 699 1696 -839 840 417 -841 842 871 -843 844 155 -845 674 846 -847 848 1193 -849 916 850 -851 791 301 -1201 852 523 -853 1642 805 -92 1195 854 -1705 855 1857 -856 506 857 -858 736 859 -381 860 1451 -861 535 862 -870 454 863 -864 865 580 -866 816 867 -868 869 826 -870 871 1826 -872 1179 873 -874 1196 875 -876 877 938 -878 900 879 -880 881 557 -882 850 883 -884 761 885 -2074 886 1205 -1694 2089 887 -888 835 836 -889 278 996 -890 728 891 -892 801 893 -224 894 895 -1606 896 503 -897 668 898 -698 959 899 -900 295 760 -676 901 94 -902 859 418 -903 904 1581 -905 474 989 -906 742 1625 -907 908 813 -909 910 1634 -911 912 786 -913 914 987 -915 544 916 -917 966 775 -1688 1062 918 -919 771 920 -921 455 922 -923 847 924 -925 876 926 -927 1005 928 -929 815 930 -931 955 844 -932 933 914 -934 935 982 -936 937 353 -988 938 518 -336 1183 939 -940 953 941 -942 299 943 -944 898 1166 -945 1672 946 -821 1562 947 -948 756 2197 -949 950 855 -951 928 1713 -952 1518 953 -954 962 955 -1845 956 920 -861 957 1591 -1184 958 976 -906 1215 959 -960 961 591 -467 2076 962 -963 551 964 -1929 322 965 -966 1190 524 -967 438 794 -968 965 969 -1666 970 148 -713 1139 971 -972 755 973 -1118 974 765 -975 976 2057 -1897 977 1204 -978 717 979 -980 1239 981 -283 982 792 -1137 735 983 -984 985 824 -986 930 987 -988 989 933 -332 990 991 -1703 992 42 -993 849 904 -994 969 977 -995 996 1699 -669 997 998 -999 231 985 -1000 947 1721 -1001 905 1002 -1003 867 909 -245 1004 1005 -1006 1007 1213 -1008 1009 129 -1010 1011 10 -2251 1012 1226 -1906 1013 1014 -32 71 1015 -1016 1999 1099 -1017 546 2097 -135 1018 1142 -1019 1020 2191 -1021 897 1088 -869 785 1022 -2001 2081 1023 -1024 1065 1025 -1026 708 1027 -1028 1029 501 -56 1063 1030 -1031 1077 1032 -1033 1136 782 -1015 1034 1877 -1035 1036 1797 -1037 563 1138 -1038 1039 1125 -189 1040 1883 -2090 1041 1042 -1043 1117 667 -723 1529 1044 -435 1045 1046 -793 1743 1047 -1048 1025 1049 -1050 15 1727 -1072 1051 1052 -1055 1053 1054 -1013 1717 1055 -1056 1057 1181 -1058 1189 1059 -1060 840 1061 -1064 1062 1063 -18 1910 1064 -1065 1032 1066 -1067 1068 1306 -1069 2041 181 -1070 1188 1071 -980 1044 1072 -1073 1173 1074 -1075 1076 1133 -1077 1128 1078 -803 1079 1198 -1080 1209 1081 -1082 1047 1083 -1086 1084 1085 -547 2042 1086 -1087 1088 1185 -1089 1928 1090 -1091 1106 1092 -1095 2234 1093 -1094 1108 1095 -1156 1096 1097 -1102 1098 1099 -1022 1392 1100 -1101 984 1120 -1161 1102 2171 -1103 829 1192 -2080 1104 1733 -1105 1106 1207 -1109 1107 1108 -1216 1539 1109 -1112 125 1110 -1111 1433 1112 -1113 1901 1114 -1081 1115 1116 -1117 1151 203 -1118 1119 618 -1120 1121 1141 -1122 1123 1149 -1124 188 1119 -1125 173 1177 -2084 1126 270 -1127 1135 1128 -1129 1130 1148 -1131 1163 1132 -1133 942 1140 -1134 1135 1200 -1136 1137 1150 -1194 1138 1139 -212 1140 1154 -842 1141 1155 -1142 349 1160 -607 1143 311 -1144 2104 1777 -1145 510 1146 -990 1114 1147 -1148 1575 1202 -941 1149 1206 -1592 1150 1103 -1165 1505 1151 -979 992 1152 -2054 1083 1153 -1154 356 1018 -995 1090 1155 -1156 1152 1157 -1504 939 1158 -1159 1027 737 -1160 1516 1079 -1161 1912 1162 -1163 1167 1164 -1165 269 1170 -1166 1048 1167 -1168 1071 706 -405 613 1169 -255 1170 1076 -1056 1171 1172 -1173 1092 1174 -1178 1175 1176 -573 1177 1021 -1178 1098 2210 -1179 1116 449 -1180 1181 1485 -1644 1147 1182 -1183 1169 1184 -1185 272 1203 -1186 1187 1389 -512 1188 1045 -875 1700 1189 -1190 1061 1191 -1586 1192 1039 -1193 1172 819 -1354 1194 1195 -1196 1738 1197 -1697 1198 290 -1199 1200 1143 -1201 1202 1146 -631 1203 709 -1204 1059 277 -1205 1206 317 -490 1207 232 -1069 1208 1084 -1209 1132 1210 -1211 1074 1212 -193 1213 1186 -1214 1215 1681 -1216 1217 38 -1218 1785 1407 -1224 1219 1220 -1221 1222 2218 -1219 1277 1223 -1224 362 1225 -1226 1706 2095 -1231 1227 1228 -1372 1229 1300 -1232 1230 1231 -2245 1258 1232 -1260 1233 1234 -1235 1236 1347 -1360 1262 1237 -431 197 1238 -1187 1239 1214 -363 1756 1240 -1220 1241 1242 -2160 1243 319 -1377 1283 1244 -1245 1246 1533 -1241 2108 1247 -2047 1248 1249 -1751 741 1250 -1914 1251 1707 -1715 1252 1254 -1253 2101 1254 -1295 1255 600 -1279 1256 1255 -2247 1228 1257 -1838 1234 1258 -1237 1259 1260 -1238 1261 1262 -1249 1263 1264 -1841 1766 1265 -214 2164 1266 -1244 1267 1268 -1269 1317 2180 -1750 1768 1270 -1271 297 1272 -1275 1273 1274 -1225 1943 1275 -1221 2249 1276 -1277 1274 1278 -1279 1288 1280 -1281 1282 286 -1283 1247 1284 -740 1285 2106 -1282 1286 1629 -1287 1266 1773 -1288 1936 1771 -1289 96 3 -1770 1290 1291 -104 1292 1293 -1294 1295 1757 -1296 1297 1144 -1298 1276 1752 -1299 1278 1020 -1300 1301 1310 -1510 1302 1662 -1761 1303 1619 -182 1304 1014 -1305 1306 1439 -1794 1307 679 -1308 1309 51 -1391 1310 1402 -1311 1312 1712 -2099 1336 1313 -1905 1314 1315 -1316 1317 1476 -44 1686 1318 -1319 1320 1787 -1321 1438 1385 -1322 1263 1323 -1324 1325 1803 -1983 1326 1316 -116 1327 2028 -1328 1329 2017 -1330 1331 1568 -1791 1332 1345 -1333 2181 1326 -1334 1010 1723 -1335 1390 1336 -2184 1955 1337 -1338 1339 1412 -1340 1420 1358 -1341 1342 2068 -1343 1344 1417 -122 1345 1346 -453 1347 1762 -1348 1349 1243 -1833 1350 1348 -1416 1351 1356 -1346 1352 1630 -1353 1354 1436 -115 29 1355 -1356 2183 1340 -1380 1357 1358 -1359 1360 1837 -1361 2070 402 -1362 1363 753 -1290 1892 1364 -1365 1741 1208 -1366 1367 103 -1368 1369 1401 -1404 1370 410 -1371 1357 1372 -1373 1374 697 -1339 1375 1376 -1242 1377 1378 -1379 1380 2013 -1381 1382 1330 -1370 1400 1383 -1384 1397 1385 -1386 1387 1748 -1388 1389 1311 -1390 1415 1391 -2079 1392 1393 -1411 1394 1395 -432 1396 36 -2011 1397 2124 -2032 1398 1399 -1422 1399 1308 -1264 1400 2015 -6 1301 1401 -1402 1796 70 -1305 1403 1404 -1405 394 621 -1406 1407 1332 -1806 1408 1495 -1409 1410 1979 -1789 2237 1411 -1355 1412 1413 -1647 1414 1405 -1371 1415 1416 -1417 1418 2156 -2045 1419 1328 -2014 1420 1333 -1359 1951 1421 -1395 1422 143 -807 1423 1307 -1426 1424 1425 -2158 1926 1426 -1314 1427 1428 -1429 1430 1795 -1303 1431 1432 -1176 1433 1434 -1435 1436 1006 -1418 1437 1427 -1438 1439 1872 -1440 1441 1437 -80 1442 74 -1831 315 1443 -1443 1444 1824 -1445 1446 95 -1425 1447 1448 -1468 1449 1450 -1450 1451 1452 -131 1453 1454 -1454 1455 41 -1456 1457 1458 -1458 1807 139 -154 1459 1460 -403 1461 973 -1462 1463 1464 -1464 1782 2051 -406 1465 1466 -971 646 1467 -1467 1468 1469 -1470 1471 1472 -1472 46 1396 -1261 1473 1474 -1474 1475 284 -1376 1476 1804 -1447 1477 1470 -1956 1478 1479 -1479 1284 1285 -1350 2225 1480 -1480 1481 1708 -175 1482 1483 -1483 1484 2151 -1364 1485 1486 -239 1487 78 -287 1488 1489 -1489 1490 268 -710 1491 1492 -1492 456 1493 -1859 1494 688 -1329 1495 1008 -1512 339 1496 -1496 1497 1498 -1676 267 1499 -1499 1500 1501 -934 220 1502 -1502 1503 1504 -263 1505 1506 -1506 1507 1508 -1509 1510 2122 -968 108 1511 -1511 1512 1513 -84 874 1514 -1514 1515 1516 -1684 1122 1517 -1517 1518 1519 -1520 1521 1522 -1522 1523 258 -1524 1525 1526 -1526 1812 1457 -1531 1435 1527 -1527 1528 1529 -114 1353 1530 -1530 1531 1532 -1533 970 1309 -328 1453 1534 -1534 1535 1830 -20 1536 1537 -1538 1539 1050 -1537 1540 1541 -1542 1543 1235 -1544 1545 389 -280 1546 1547 -1547 1548 1549 -1550 1551 1552 -1552 1236 413 -442 1553 1554 -1948 1764 1555 -533 595 1556 -1556 1557 545 -391 1558 1559 -397 1560 1561 -1562 1563 1334 -408 1564 1565 -448 1566 1567 -1567 1568 1569 -1864 1570 1571 -1571 1572 1386 -590 1573 1574 -1574 555 1575 -1611 477 1576 -1576 1577 1578 -93 1579 1580 -1580 1581 585 -950 1582 1583 -1583 1564 380 -411 1584 1585 -1585 376 386 -1594 1586 1587 -1587 1588 1078 -481 1612 1589 -1589 1590 1591 -626 1592 1593 -1593 1594 1134 -751 1171 1595 -1595 1596 1597 -504 1598 608 -1599 1600 1995 -1596 1180 1601 -1601 1602 1603 -304 715 1604 -1604 1605 1606 -1057 1607 1608 -1608 1609 1674 -1003 550 1610 -1610 1611 1612 -190 1613 1614 -806 1615 1616 -1616 1542 494 -650 1617 1618 -1618 1550 1553 -2060 1619 1620 -1621 1622 1623 -1623 1624 694 -1036 1625 1639 -907 1626 1627 -1627 1628 1629 -149 1630 1631 -1631 1632 687 -1847 1633 1634 -1432 1635 1620 -217 1636 1637 -1637 1638 275 -747 1639 1640 -1640 1641 2146 -820 1642 1643 -1643 954 141 -310 1644 1645 -1645 1646 1647 -1648 1649 1650 -1650 1651 1654 -2072 1652 1653 -1653 1654 23 -1900 1291 1655 -1655 1656 1657 -425 1658 1659 -1659 1660 1919 -1578 91 1661 -1661 1662 1590 -1922 1663 1664 -1664 1665 1646 -1675 1666 2235 -848 1667 1668 -1668 1669 1607 -729 1670 1671 -1671 536 1672 -1656 1486 1673 -1673 1674 1675 -166 1676 1677 -1677 1678 233 -767 1493 1679 -1679 1680 1520 -1312 1681 1682 -1682 1683 951 -1388 1684 1685 -1685 1686 276 -1104 1719 1687 -1687 1688 1689 -138 1028 1689 -1690 1691 1692 -1692 1693 1663 -1041 1694 1695 -1695 1696 1000 -777 1697 1698 -1698 1699 1700 -2033 1431 1701 -1701 1702 891 -1638 1703 1704 -1704 1705 911 -1706 1707 97 -1708 1709 1714 -1538 1710 2232 -1711 908 1286 -1712 1713 1123 -1714 1715 683 -1029 1488 1716 -1716 1717 1718 -1030 1719 1720 -702 1721 1722 -1722 1723 60 -1724 1725 222 -1726 1727 1728 -1728 34 1110 -1729 1730 1731 -1731 1732 1211 -1733 1734 1023 -681 1735 1736 -1737 1738 1739 -1739 1740 1730 -1741 814 2092 -1742 81 137 -963 1743 1744 -1744 935 1158 -2077 1745 1746 -1746 1498 1100 -2030 1325 1747 -1748 1749 368 -2216 1750 1751 -1019 1752 2248 -1753 440 1271 -1268 1754 1755 -1755 1756 1378 -2147 1757 752 -2109 1758 1759 -738 1760 1761 -1762 1763 1939 -1945 1952 1764 -1765 1766 1240 -1767 1768 1252 -1383 1322 1769 -1917 1923 1770 -1771 2112 1772 -1772 1773 1774 -2223 1775 1776 -1776 1777 1778 -1779 211 198 -1848 1780 625 -684 1781 1782 -2153 1783 163 -1 2019 1784 -361 1785 1786 -1786 1787 1341 -2007 2003 1788 -1788 1789 1790 -1880 2140 1791 -1218 2230 1792 -1792 1793 1319 -1381 1566 1794 -2209 1795 1781 -153 1796 1797 -1870 1798 1753 -1799 1800 1327 -1935 1801 1802 -1802 1803 1800 -1804 1269 2087 -1805 1806 1419 -1807 1808 1809 -1809 1810 54 -5 1297 1811 -1808 1812 1813 -1813 1814 1815 -1977 1338 1816 -1816 1817 1409 -1854 1971 1818 -1818 1819 1820 -1821 1822 1823 -1823 1824 1429 -822 921 1825 -1825 1826 596 -45 1230 1827 -1827 1828 1829 -1830 1831 1832 -1832 1822 145 -2113 1833 1834 -2244 1835 1836 -1836 1837 1838 -430 1944 1839 -1839 1840 1841 -1293 1842 1843 -1843 1844 367 -888 1845 1846 -1846 1847 726 -2166 1848 1849 -1849 575 1256 -1545 1850 1851 -1851 1852 26 -1853 1854 1855 -1855 2137 111 -422 912 1856 -1856 1857 1858 -1866 1859 1860 -1860 1861 1873 -1861 1862 1863 -1863 1864 369 -1292 1494 1865 -1865 1866 1867 -119 2114 1868 -1868 1869 1870 -246 2036 1871 -1871 1872 560 -1599 1873 1874 -1874 1875 1876 -748 1877 1878 -1878 1879 1374 -2134 1880 1881 -1881 1882 1974 -1883 1884 1885 -1885 1876 1561 -972 1461 1886 -1886 1887 1888 -707 1889 1890 -1890 1891 221 -1602 1892 1893 -1893 1894 2129 -1903 946 1895 -1895 1896 1897 -1898 1918 1899 -1899 1900 1070 -424 1901 1902 -1902 1903 1491 -1904 1905 2136 -1906 1251 1907 -1563 1908 1909 -1909 1910 1011 -1911 1912 1913 -1913 1914 1012 -1129 1915 1916 -1916 1917 1918 -1919 1920 1921 -1921 1922 1182 -1894 1923 1924 -1924 1925 1926 -185 597 1927 -1927 1928 1929 -1930 1931 1932 -1932 1933 1967 -1934 1935 2088 -1775 1936 1937 -1937 1294 1296 -2021 444 1938 -1938 1939 1940 -1950 1941 1942 -1942 1943 1944 -1954 1945 1946 -1946 1947 1835 -1947 1948 1949 -1949 1950 1951 -2213 1952 1953 -1953 1954 1955 -1603 1956 1957 -1957 1767 2149 -1958 1959 1960 -1960 1961 1375 -1373 1888 1962 -1962 1963 1964 -1440 1965 1966 -1966 1967 1968 -1779 1765 1969 -1969 1970 1971 -1869 2163 1972 -1972 1973 285 -2206 1974 1975 -1975 1245 1398 -2008 1976 2138 -151 1977 1978 -1978 1979 2004 -1980 1981 1982 -1982 1983 1961 -1984 1985 1217 -2038 1986 1987 -1987 1988 2241 -1318 1519 1989 -1989 1990 1227 -1963 2073 1991 -1991 1992 1993 -27 1867 1994 -1994 1995 1996 -1790 1997 1998 -1998 58 1976 -2173 1999 2000 -2000 2001 2002 -2003 2004 2005 -2005 2006 2239 -2007 2008 2009 -2009 2010 152 -1981 2011 2012 -2012 2013 2014 -1959 2015 2016 -2016 1403 553 -1248 2017 2018 -2018 2019 2025 -2020 812 1361 -2021 2022 2023 -2023 2024 1387 -1323 2025 2026 -2026 2027 409 -2229 2028 2029 -2029 2030 1793 -2031 2032 1394 -2033 2034 2035 -2035 1624 1635 -1384 2036 2037 -2037 927 1369 -2187 2038 2039 -2039 2040 30 -2041 2042 2043 -2043 98 1304 -2044 2045 2046 -2046 2047 2010 -1446 2048 2049 -2049 2050 22 -324 2051 2052 -2052 1430 1444 -1726 124 2053 -2054 2055 2056 -2056 1115 632 -1096 2057 2058 -2058 581 2059 -2060 1622 2061 -2061 2062 739 -24 2063 2064 -2064 2065 2066 -2067 2068 2069 -2069 64 1632 -1887 2070 2071 -2071 2072 2073 -2074 787 2075 -2075 2076 878 -2055 2077 2078 -2078 2079 450 -2080 2081 2082 -2082 86 1720 -2083 2084 2085 -2085 1891 1711 -1799 1413 2086 -2086 2087 2088 -2089 2090 2091 -2091 39 2175 -2092 2093 2094 -2094 2195 1085 -2233 2095 2096 -2096 2097 1093 -52 1335 2098 -2098 2099 1324 -2100 2101 2102 -2102 2186 1257 -1481 1778 2103 -2103 2104 2105 -1250 2106 2107 -2107 2108 2222 -2109 2110 2111 -2111 2112 1724 -2226 2113 2114 -1758 2115 2116 -2116 2117 201 -1973 4 2118 -2118 2119 1281 -2120 1760 1365 -1287 2110 2121 -2121 2122 90 -1229 1379 2123 -2123 2124 1368 -2170 2125 2126 -2126 2127 695 -2128 2120 1046 -1478 2129 2130 -2130 2131 1267 -1986 2132 2133 -2133 2134 2204 -1820 1736 2135 -2135 2136 2137 -2044 2138 2139 -2139 57 1805 -2140 2132 2141 -2141 2142 1406 -2125 2143 2144 -2144 2145 2146 -2147 1597 2148 -2148 2149 1811 -2150 2151 2152 -2152 2153 1343 -1455 327 2154 -2154 2155 68 -2150 2156 2157 -2157 1904 176 -2131 2158 2159 -2159 294 325 -2160 2161 2162 -2162 2163 1834 -1774 2164 2165 -2165 2166 1280 -2167 2168 2169 -2169 2170 884 -1907 2171 2172 -2172 2173 1718 -2174 2175 2176 -2176 1985 2093 -1754 2177 2178 -2178 2179 1970 -2180 2181 2182 -2182 2183 1934 -2215 2184 2185 -2185 2186 1222 -2187 2188 2227 -2203 2189 2190 -2190 2243 1988 -2212 2191 2192 -2192 375 1555 -1984 1094 2193 -2193 2194 2195 -2020 885 2196 -2196 2197 2198 -2202 2040 2199 -1410 2200 2201 -2201 2202 2006 -2203 2204 2205 -2205 2206 2031 -358 1484 2207 -2207 2208 2209 -2053 2210 2211 -2211 1162 1710 -2212 2213 2214 -2214 2215 1298 -2216 2220 2217 -2217 2218 1253 -2219 2220 2221 -2221 2222 1223 -1725 2223 2224 -2224 2225 2226 -2142 2227 2228 -2228 2229 2230 -2231 2232 1911 -2252 2233 2234 -1657 2235 2236 -2236 1702 2128 -2189 2237 2238 -2238 2239 2240 -2199 2241 2242 -2242 2243 2240 -2244 2245 2246 -2246 2247 1337 -2248 2249 2250 -2250 2219 1299 -2251 2252 2253 -2253 1107 2231 diff --git a/skeinforge/models/box.obj b/skeinforge/models/box.obj deleted file mode 100644 index 1e1c785..0000000 --- a/skeinforge/models/box.obj +++ /dev/null @@ -1,79 +0,0 @@ -# ----------------- -# Start of obj file -g Box01 -mtllib box.mat -usemtl box -v -62.0579 -41.4791 0.0 -v 58.8424 -41.4791 0.0 -v -62.0579 22.1865 0.0 -v 58.8424 22.1865 0.0 -v -62.0579 -41.4791 39.8714 -v 58.8424 -41.4791 39.8714 -v -62.0579 22.1865 39.8714 -v 58.8424 22.1865 39.8714 - -vt 0.843206 0.405444 0.000499517 -vt 0.482802 0.71377 0.9995 -vt 0.478066 0.404023 0.000499636 -vt 0.482802 0.716612 0.9995 -vt 0.841627 0.688332 0.000499517 -vt 0.482013 0.981029 0.9995 -vt 0.480434 0.688332 0.000499636 -vt 0.485959 0.978188 0.9995 -vt 0.450102 0.00618343 0.000499547 -vt 0.45247 0.509304 0.000499547 -vt 0.000499517 0.512146 0.000499547 -vt 0.000499517 0.512146 0.000499547 -vt -0.0010791 0.00618302 0.000499547 -vt 0.450102 0.00618343 0.000499547 -vt 0.000499517 0.512009 0.9995 -vt 0.450891 0.510588 0.9995 -vt 0.45247 0.995237 0.9995 -vt 0.45247 0.996658 0.9995 -vt 0.000499636 0.9995 0.9995 -vt 0.000499517 0.51343 0.9995 -vt 0.478855 0.405444 0.000500023 -vt 0.841627 0.408286 0.000499576 -vt 0.83847 0.688332 0.000499576 -vt 0.83847 0.688332 0.000499576 -vt 0.477276 0.694016 0.000500023 -vt 0.478855 0.405444 0.000500023 -vt 0.482802 0.71377 0.9995 -vt 0.845574 0.71377 0.999501 -vt 0.844784 0.976767 0.999501 -vt 0.844784 0.976767 0.999501 -vt 0.482802 0.716612 0.9995 -vt 0.842417 0.710929 0.9995 -vt 0.843995 0.975346 0.9995 -vt 0.843995 0.975346 0.9995 -vt 0.478066 0.404023 0.000499636 -vt 0.841627 0.688332 0.000499517 - -vn 0.0 0.0 -1.0 -vn 0.0 0.0 -1.0 -vn 0.0 0.0 1.0 -vn 0.0 0.0 1.0 -vn 0.0 -1.0 0.0 -vn 0.0 -1.0 0.0 -vn 1.0 0.0 0.0 -vn 1.0 0.0 0.0 -vn 0.0 1.0 0.0 -vn 0.0 1.0 0.0 -vn -1.0 0.0 0.0 -vn -1.0 0.0 0.0 - -f 1/9/1 3/10/1 4/11/1 -f 4/12/2 2/13/2 1/14/2 -f 5/15/3 6/16/3 8/17/3 -f 8/18/4 7/19/4 5/20/4 -f 1/21/5 2/22/5 6/23/5 -f 6/24/6 5/25/6 1/26/6 -f 2/27/7 4/28/7 8/29/7 -f 8/30/8 6/6/8 2/2/8 -f 4/31/9 3/32/9 7/33/9 -f 7/34/10 8/8/10 4/4/10 -f 3/35/11 1/1/11 5/36/11 -f 5/5/12 7/7/12 3/3/12 - -# end of obj file -# --------------- diff --git a/skeinforge/models/inkscape_star.svg b/skeinforge/models/inkscape_star.svg deleted file mode 100644 index 8d99449..0000000 --- a/skeinforge/models/inkscape_star.svg +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - image/svg+xml - - - - - - - - diff --git a/skeinforge/models/xml_models/art_of_illusion/art_of_illusion_boolean.xml b/skeinforge/models/xml_models/art_of_illusion/art_of_illusion_boolean.xml deleted file mode 100644 index b426a64..0000000 --- a/skeinforge/models/xml_models/art_of_illusion/art_of_illusion_boolean.xml +++ /dev/null @@ -1,516 +0,0 @@ - - - - - - - - - - - - - - - - Default Texture - - - - - - - - - - - - - - - - - - - - - - - - - - Camera 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - Light 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cube 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cube 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Boolean1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/art_of_illusion/art_of_illusion_cylinder.xml b/skeinforge/models/xml_models/art_of_illusion/art_of_illusion_cylinder.xml deleted file mode 100644 index a5c1198..0000000 --- a/skeinforge/models/xml_models/art_of_illusion/art_of_illusion_cylinder.xml +++ /dev/null @@ -1,328 +0,0 @@ - - - - - - - - - - - - - - - - Default Texture - - - - - - - - - - - - - - - - - - - - - - - - - - Camera 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - Light 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cylinder 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/art_of_illusion/art_of_illusion_group.xml b/skeinforge/models/xml_models/art_of_illusion/art_of_illusion_group.xml deleted file mode 100644 index 5352bce..0000000 --- a/skeinforge/models/xml_models/art_of_illusion/art_of_illusion_group.xml +++ /dev/null @@ -1,537 +0,0 @@ - - - - - - - - - - - - - - - - Default Texture - - - - - - - - - - - - - - - - - - - - - - - - - - Camera 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - Light 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - Array of Cylinder 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cylinder 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cylinder 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - Cylinder 2 - - - - - - - - - - - Cylinder 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/art_of_illusion/art_of_illusion_sphere.xml b/skeinforge/models/xml_models/art_of_illusion/art_of_illusion_sphere.xml deleted file mode 100644 index 81514fd..0000000 --- a/skeinforge/models/xml_models/art_of_illusion/art_of_illusion_sphere.xml +++ /dev/null @@ -1,328 +0,0 @@ - - - - - - - - - - - - - - - - Default Texture - - - - - - - - - - - - - - - - - - - - - - - - - - Camera 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - Light 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Sphere1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/art_of_illusion/art_of_illusion_tetrahedron.xml b/skeinforge/models/xml_models/art_of_illusion/art_of_illusion_tetrahedron.xml deleted file mode 100644 index 5007bfd..0000000 --- a/skeinforge/models/xml_models/art_of_illusion/art_of_illusion_tetrahedron.xml +++ /dev/null @@ -1,389 +0,0 @@ - - - - - - - - - - - - - - - - Default Texture - - - - - - - - - - - - - - - - - - - - - - - - - - Camera 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - Light 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - tetrahedron - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/combined.xml b/skeinforge/models/xml_models/combined.xml deleted file mode 100644 index f00fa61..0000000 --- a/skeinforge/models/xml_models/combined.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/creation/circle.xml b/skeinforge/models/xml_models/creation/circle.xml deleted file mode 100644 index db41974..0000000 --- a/skeinforge/models/xml_models/creation/circle.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/creation/concatenate.xml b/skeinforge/models/xml_models/creation/concatenate.xml deleted file mode 100644 index 0a6223f..0000000 --- a/skeinforge/models/xml_models/creation/concatenate.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - diff --git a/skeinforge/models/xml_models/creation/drill.xml b/skeinforge/models/xml_models/creation/drill.xml deleted file mode 100644 index 787befa..0000000 --- a/skeinforge/models/xml_models/creation/drill.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/skeinforge/models/xml_models/creation/extrude.xml b/skeinforge/models/xml_models/creation/extrude.xml deleted file mode 100644 index 0040fb3..0000000 --- a/skeinforge/models/xml_models/creation/extrude.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - diff --git a/skeinforge/models/xml_models/creation/gear/bevel.svg b/skeinforge/models/xml_models/creation/gear/bevel.svg deleted file mode 100644 index 8f56668..0000000 --- a/skeinforge/models/xml_models/creation/gear/bevel.svg +++ /dev/null @@ -1,644 +0,0 @@ - - - - - - - - bevel.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - Layer 2, z:1.0 - - - - - Layer 3, z:1.4 - - - - - Layer 4, z:1.8 - - - - - Layer 5, z:2.2 - - - - - Layer 6, z:2.6 - - - - - Layer 7, z:3.0 - - - - - Layer 8, z:3.4 - - - - - Layer 9, z:3.8 - - - - - Layer 10, z:4.2 - - - - - Layer 11, z:4.6 - - - - - Layer 12, z:5.0 - - - - - Layer 13, z:5.4 - - - - - Layer 14, z:5.8 - - - - - Layer 15, z:6.2 - - - - - Layer 16, z:6.6 - - - - - Layer 17, z:7.0 - - - - - Layer 18, z:7.4 - - - - - Layer 19, z:7.8 - - - - - Layer 20, z:8.2 - - - - - Layer 21, z:8.6 - - - - - Layer 22, z:9.0 - - - - - Layer 23, z:9.4 - - - - - Layer 24, z:9.8 - - - - - Layer 25, z:10.2 - - - - - Layer 26, z:10.6 - - - - - Layer 27, z:11.0 - - - - - Layer 28, z:11.4 - - - - - Layer 29, z:11.8 - - - - - Layer 30, z:12.2 - - - - - Layer 31, z:12.6 - - - - - Layer 32, z:13.0 - - - - - Layer 33, z:13.4 - - - - - Layer 34, z:13.8 - - - - - Layer 35, z:14.2 - - - - - Layer 36, z:14.6 - - - - - Layer 37, z:15.0 - - - - - Layer 38, z:15.4 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -49.2741 mm - Y: -148.9752 mm - Z: 0.0 mm - - - Max - X: 49.2741 mm - Y: 21.6669 mm - Z: 15.6 mm - - - Dimension - X: 98.5482 mm - Y: 170.6421 mm - Z: 15.6 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 39 - Volume: 262.5277 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -49.2741 mm - Y: -148.9752 mm - Z: 0.0 mm - - - Max - X: 49.2741 mm - Y: 21.6669 mm - Z: 15.6 mm - - - Dimension - X: 98.5482 mm - Y: 170.6421 mm - Z: 15.6 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 39 - Volume: 262.5277 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -49.2741 mm - Y: -148.9752 mm - Z: 0.0 mm - - - Max - X: 49.2741 mm - Y: 21.6669 mm - Z: 15.6 mm - - - Dimension - X: 98.5482 mm - Y: 170.6421 mm - Z: 15.6 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 39 - Volume: 262.5277 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/creation/gear/bevel.xml b/skeinforge/models/xml_models/creation/gear/bevel.xml deleted file mode 100644 index e93586a..0000000 --- a/skeinforge/models/xml_models/creation/gear/bevel.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/creation/gear/collar.svg b/skeinforge/models/xml_models/creation/gear/collar.svg deleted file mode 100644 index 983fbf5..0000000 --- a/skeinforge/models/xml_models/creation/gear/collar.svg +++ /dev/null @@ -1,699 +0,0 @@ - - - - - - - - collar.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - Layer 2, z:1.0 - - - - - Layer 3, z:1.4 - - - - - Layer 4, z:1.8 - - - - - Layer 5, z:2.2 - - - - - Layer 6, z:2.6 - - - - - Layer 7, z:3.0 - - - - - Layer 8, z:3.4 - - - - - Layer 9, z:3.8 - - - - - Layer 10, z:4.2 - - - - - Layer 11, z:4.6 - - - - - Layer 12, z:5.0 - - - - - Layer 13, z:5.4 - - - - - Layer 14, z:5.8 - - - - - Layer 15, z:6.2 - - - - - Layer 16, z:6.6 - - - - - Layer 17, z:7.0 - - - - - Layer 18, z:7.4 - - - - - Layer 19, z:7.8 - - - - - Layer 20, z:8.2 - - - - - Layer 21, z:8.6 - - - - - Layer 22, z:9.0 - - - - - Layer 23, z:9.4 - - - - - Layer 24, z:9.8 - - - - - Layer 25, z:10.2 - - - - - Layer 26, z:10.6 - - - - - Layer 27, z:11.0 - - - - - Layer 28, z:11.4 - - - - - Layer 29, z:11.8 - - - - - Layer 30, z:12.2 - - - - - Layer 31, z:12.6 - - - - - Layer 32, z:13.0 - - - - - Layer 33, z:13.4 - - - - - Layer 34, z:13.8 - - - - - Layer 35, z:14.2 - - - - - Layer 36, z:14.6 - - - - - Layer 37, z:15.0 - - - - - Layer 38, z:15.4 - - - - - Layer 39, z:15.8 - - - - - Layer 40, z:16.2 - - - - - Layer 41, z:16.6 - - - - - Layer 42, z:17.0 - - - - - Layer 43, z:17.4 - - - - - Layer 44, z:17.8 - - - - - Layer 45, z:18.2 - - - - - Layer 46, z:18.6 - - - - - Layer 47, z:19.0 - - - - - Layer 48, z:19.4 - - - - - Layer 49, z:19.8 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 20.0 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 20.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 50 - Volume: 164.2662 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 20.0 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 20.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 50 - Volume: 164.2662 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 20.0 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 20.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 50 - Volume: 164.2662 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/creation/gear/collar.xml b/skeinforge/models/xml_models/creation/gear/collar.xml deleted file mode 100644 index 0f2c59c..0000000 --- a/skeinforge/models/xml_models/creation/gear/collar.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/creation/gear/default_gear.svg b/skeinforge/models/xml_models/creation/gear/default_gear.svg deleted file mode 100644 index d5c770f..0000000 --- a/skeinforge/models/xml_models/creation/gear/default_gear.svg +++ /dev/null @@ -1,574 +0,0 @@ - - - - - - - - default_gear.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - Layer 2, z:1.0 - - - - - Layer 3, z:1.4 - - - - - Layer 4, z:1.8 - - - - - Layer 5, z:2.2 - - - - - Layer 6, z:2.6 - - - - - Layer 7, z:3.0 - - - - - Layer 8, z:3.4 - - - - - Layer 9, z:3.8 - - - - - Layer 10, z:4.2 - - - - - Layer 11, z:4.6 - - - - - Layer 12, z:5.0 - - - - - Layer 13, z:5.4 - - - - - Layer 14, z:5.8 - - - - - Layer 15, z:6.2 - - - - - Layer 16, z:6.6 - - - - - Layer 17, z:7.0 - - - - - Layer 18, z:7.4 - - - - - Layer 19, z:7.8 - - - - - Layer 20, z:8.2 - - - - - Layer 21, z:8.6 - - - - - Layer 22, z:9.0 - - - - - Layer 23, z:9.4 - - - - - Layer 24, z:9.8 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 10.0 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 151.0364 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 10.0 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 151.0364 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 10.0 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 151.0364 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/creation/gear/default_gear.xml b/skeinforge/models/xml_models/creation/gear/default_gear.xml deleted file mode 100644 index 0843e61..0000000 --- a/skeinforge/models/xml_models/creation/gear/default_gear.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/creation/gear/gear.xml b/skeinforge/models/xml_models/creation/gear/gear.xml deleted file mode 100644 index 0638192..0000000 --- a/skeinforge/models/xml_models/creation/gear/gear.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/creation/gear/keyway.svg b/skeinforge/models/xml_models/creation/gear/keyway.svg deleted file mode 100644 index 577adde..0000000 --- a/skeinforge/models/xml_models/creation/gear/keyway.svg +++ /dev/null @@ -1,699 +0,0 @@ - - - - - - - - keyway.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - Layer 2, z:1.0 - - - - - Layer 3, z:1.4 - - - - - Layer 4, z:1.8 - - - - - Layer 5, z:2.2 - - - - - Layer 6, z:2.6 - - - - - Layer 7, z:3.0 - - - - - Layer 8, z:3.4 - - - - - Layer 9, z:3.8 - - - - - Layer 10, z:4.2 - - - - - Layer 11, z:4.6 - - - - - Layer 12, z:5.0 - - - - - Layer 13, z:5.4 - - - - - Layer 14, z:5.8 - - - - - Layer 15, z:6.2 - - - - - Layer 16, z:6.6 - - - - - Layer 17, z:7.0 - - - - - Layer 18, z:7.4 - - - - - Layer 19, z:7.8 - - - - - Layer 20, z:8.2 - - - - - Layer 21, z:8.6 - - - - - Layer 22, z:9.0 - - - - - Layer 23, z:9.4 - - - - - Layer 24, z:9.8 - - - - - Layer 25, z:10.2 - - - - - Layer 26, z:10.6 - - - - - Layer 27, z:11.0 - - - - - Layer 28, z:11.4 - - - - - Layer 29, z:11.8 - - - - - Layer 30, z:12.2 - - - - - Layer 31, z:12.6 - - - - - Layer 32, z:13.0 - - - - - Layer 33, z:13.4 - - - - - Layer 34, z:13.8 - - - - - Layer 35, z:14.2 - - - - - Layer 36, z:14.6 - - - - - Layer 37, z:15.0 - - - - - Layer 38, z:15.4 - - - - - Layer 39, z:15.8 - - - - - Layer 40, z:16.2 - - - - - Layer 41, z:16.6 - - - - - Layer 42, z:17.0 - - - - - Layer 43, z:17.4 - - - - - Layer 44, z:17.8 - - - - - Layer 45, z:18.2 - - - - - Layer 46, z:18.6 - - - - - Layer 47, z:19.0 - - - - - Layer 48, z:19.4 - - - - - Layer 49, z:19.8 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 20.0 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 20.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 50 - Volume: 164.504 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 20.0 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 20.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 50 - Volume: 164.504 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 20.0 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 20.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 50 - Volume: 164.504 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/creation/gear/keyway.xml b/skeinforge/models/xml_models/creation/gear/keyway.xml deleted file mode 100644 index 720e518..0000000 --- a/skeinforge/models/xml_models/creation/gear/keyway.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/creation/gear/rack.svg b/skeinforge/models/xml_models/creation/gear/rack.svg deleted file mode 100644 index 60f067b..0000000 --- a/skeinforge/models/xml_models/creation/gear/rack.svg +++ /dev/null @@ -1,574 +0,0 @@ - - - - - - - - rack.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - Layer 2, z:1.0 - - - - - Layer 3, z:1.4 - - - - - Layer 4, z:1.8 - - - - - Layer 5, z:2.2 - - - - - Layer 6, z:2.6 - - - - - Layer 7, z:3.0 - - - - - Layer 8, z:3.4 - - - - - Layer 9, z:3.8 - - - - - Layer 10, z:4.2 - - - - - Layer 11, z:4.6 - - - - - Layer 12, z:5.0 - - - - - Layer 13, z:5.4 - - - - - Layer 14, z:5.8 - - - - - Layer 15, z:6.2 - - - - - Layer 16, z:6.6 - - - - - Layer 17, z:7.0 - - - - - Layer 18, z:7.4 - - - - - Layer 19, z:7.8 - - - - - Layer 20, z:8.2 - - - - - Layer 21, z:8.6 - - - - - Layer 22, z:9.0 - - - - - Layer 23, z:9.4 - - - - - Layer 24, z:9.8 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -62.8319 mm - Y: -54.0 mm - Z: 0.0 mm - - - Max - X: 62.8319 mm - Y: 21.8248 mm - Z: 10.0 mm - - - Dimension - X: 125.6637 mm - Y: 75.8248 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 55.6493 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -62.8319 mm - Y: -54.0 mm - Z: 0.0 mm - - - Max - X: 62.8319 mm - Y: 21.8248 mm - Z: 10.0 mm - - - Dimension - X: 125.6637 mm - Y: 75.8248 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 55.6493 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -62.8319 mm - Y: -54.0 mm - Z: 0.0 mm - - - Max - X: 62.8319 mm - Y: 21.8248 mm - Z: 10.0 mm - - - Dimension - X: 125.6637 mm - Y: 75.8248 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 55.6493 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/creation/gear/rack.xml b/skeinforge/models/xml_models/creation/gear/rack.xml deleted file mode 100644 index 2f01a1d..0000000 --- a/skeinforge/models/xml_models/creation/gear/rack.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/creation/gear/rack_hole.svg b/skeinforge/models/xml_models/creation/gear/rack_hole.svg deleted file mode 100644 index 03da33b..0000000 --- a/skeinforge/models/xml_models/creation/gear/rack_hole.svg +++ /dev/null @@ -1,574 +0,0 @@ - - - - - - - - rack_hole.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - Layer 2, z:1.0 - - - - - Layer 3, z:1.4 - - - - - Layer 4, z:1.8 - - - - - Layer 5, z:2.2 - - - - - Layer 6, z:2.6 - - - - - Layer 7, z:3.0 - - - - - Layer 8, z:3.4 - - - - - Layer 9, z:3.8 - - - - - Layer 10, z:4.2 - - - - - Layer 11, z:4.6 - - - - - Layer 12, z:5.0 - - - - - Layer 13, z:5.4 - - - - - Layer 14, z:5.8 - - - - - Layer 15, z:6.2 - - - - - Layer 16, z:6.6 - - - - - Layer 17, z:7.0 - - - - - Layer 18, z:7.4 - - - - - Layer 19, z:7.8 - - - - - Layer 20, z:8.2 - - - - - Layer 21, z:8.6 - - - - - Layer 22, z:9.0 - - - - - Layer 23, z:9.4 - - - - - Layer 24, z:9.8 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -62.8319 mm - Y: -64.0 mm - Z: 0.0 mm - - - Max - X: 62.8319 mm - Y: 21.8248 mm - Z: 10.0 mm - - - Dimension - X: 125.6637 mm - Y: 85.8248 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 81.0238 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -62.8319 mm - Y: -64.0 mm - Z: 0.0 mm - - - Max - X: 62.8319 mm - Y: 21.8248 mm - Z: 10.0 mm - - - Dimension - X: 125.6637 mm - Y: 85.8248 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 81.0238 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -62.8319 mm - Y: -64.0 mm - Z: 0.0 mm - - - Max - X: 62.8319 mm - Y: 21.8248 mm - Z: 10.0 mm - - - Dimension - X: 125.6637 mm - Y: 85.8248 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 81.0238 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/creation/gear/rack_hole.xml b/skeinforge/models/xml_models/creation/gear/rack_hole.xml deleted file mode 100644 index 4383a5f..0000000 --- a/skeinforge/models/xml_models/creation/gear/rack_hole.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/creation/gear/ring.svg b/skeinforge/models/xml_models/creation/gear/ring.svg deleted file mode 100644 index 3d9236f..0000000 --- a/skeinforge/models/xml_models/creation/gear/ring.svg +++ /dev/null @@ -1,639 +0,0 @@ - - - - - - - - ring.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - Layer 2, z:1.0 - - - - - Layer 3, z:1.4 - - - - - Layer 4, z:1.8 - - - - - Layer 5, z:2.2 - - - - - Layer 6, z:2.6 - - - - - Layer 7, z:3.0 - - - - - Layer 8, z:3.4 - - - - - Layer 9, z:3.8 - - - - - Layer 10, z:4.2 - - - - - Layer 11, z:4.6 - - - - - Layer 12, z:5.0 - - - - - Layer 13, z:5.4 - - - - - Layer 14, z:5.8 - - - - - Layer 15, z:6.2 - - - - - Layer 16, z:6.6 - - - - - Layer 17, z:7.0 - - - - - Layer 18, z:7.4 - - - - - Layer 19, z:7.8 - - - - - Layer 20, z:8.2 - - - - - Layer 21, z:8.6 - - - - - Layer 22, z:9.0 - - - - - Layer 23, z:9.4 - - - - - Layer 24, z:9.8 - - - - - Layer 25, z:10.2 - - - - - Layer 26, z:10.6 - - - - - Layer 27, z:11.0 - - - - - Layer 28, z:11.4 - - - - - Layer 29, z:11.8 - - - - - Layer 30, z:12.2 - - - - - Layer 31, z:12.6 - - - - - Layer 32, z:13.0 - - - - - Layer 33, z:13.4 - - - - - Layer 34, z:13.8 - - - - - Layer 35, z:14.2 - - - - - Layer 36, z:14.6 - - - - - Layer 37, z:15.0 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -73.4936 mm - Y: -191.9792 mm - Z: 0.0 mm - - - Max - X: 73.4936 mm - Y: 21.8248 mm - Z: 15.2 mm - - - Dimension - X: 146.9872 mm - Y: 213.804 mm - Z: 15.2 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 38 - Volume: 230.2172 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -73.4936 mm - Y: -191.9792 mm - Z: 0.0 mm - - - Max - X: 73.4936 mm - Y: 21.8248 mm - Z: 15.2 mm - - - Dimension - X: 146.9872 mm - Y: 213.804 mm - Z: 15.2 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 38 - Volume: 230.2172 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -73.4936 mm - Y: -191.9792 mm - Z: 0.0 mm - - - Max - X: 73.4936 mm - Y: 21.8248 mm - Z: 15.2 mm - - - Dimension - X: 146.9872 mm - Y: 213.804 mm - Z: 15.2 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 38 - Volume: 230.2172 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/creation/gear/ring.xml b/skeinforge/models/xml_models/creation/gear/ring.xml deleted file mode 100644 index 1fb56af..0000000 --- a/skeinforge/models/xml_models/creation/gear/ring.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/creation/gear/shaft.svg b/skeinforge/models/xml_models/creation/gear/shaft.svg deleted file mode 100644 index 6da8462..0000000 --- a/skeinforge/models/xml_models/creation/gear/shaft.svg +++ /dev/null @@ -1,574 +0,0 @@ - - - - - - - - shaft.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - Layer 2, z:1.0 - - - - - Layer 3, z:1.4 - - - - - Layer 4, z:1.8 - - - - - Layer 5, z:2.2 - - - - - Layer 6, z:2.6 - - - - - Layer 7, z:3.0 - - - - - Layer 8, z:3.4 - - - - - Layer 9, z:3.8 - - - - - Layer 10, z:4.2 - - - - - Layer 11, z:4.6 - - - - - Layer 12, z:5.0 - - - - - Layer 13, z:5.4 - - - - - Layer 14, z:5.8 - - - - - Layer 15, z:6.2 - - - - - Layer 16, z:6.6 - - - - - Layer 17, z:7.0 - - - - - Layer 18, z:7.4 - - - - - Layer 19, z:7.8 - - - - - Layer 20, z:8.2 - - - - - Layer 21, z:8.6 - - - - - Layer 22, z:9.0 - - - - - Layer 23, z:9.4 - - - - - Layer 24, z:9.8 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 10.0 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 151.8979 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 10.0 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 151.8979 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 10.0 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 151.8979 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/creation/gear/shaft.xml b/skeinforge/models/xml_models/creation/gear/shaft.xml deleted file mode 100644 index fbaa52e..0000000 --- a/skeinforge/models/xml_models/creation/gear/shaft.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/creation/gear/shaft_top.svg b/skeinforge/models/xml_models/creation/gear/shaft_top.svg deleted file mode 100644 index 7f35d90..0000000 --- a/skeinforge/models/xml_models/creation/gear/shaft_top.svg +++ /dev/null @@ -1,574 +0,0 @@ - - - - - - - - shaft_top.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - Layer 2, z:1.0 - - - - - Layer 3, z:1.4 - - - - - Layer 4, z:1.8 - - - - - Layer 5, z:2.2 - - - - - Layer 6, z:2.6 - - - - - Layer 7, z:3.0 - - - - - Layer 8, z:3.4 - - - - - Layer 9, z:3.8 - - - - - Layer 10, z:4.2 - - - - - Layer 11, z:4.6 - - - - - Layer 12, z:5.0 - - - - - Layer 13, z:5.4 - - - - - Layer 14, z:5.8 - - - - - Layer 15, z:6.2 - - - - - Layer 16, z:6.6 - - - - - Layer 17, z:7.0 - - - - - Layer 18, z:7.4 - - - - - Layer 19, z:7.8 - - - - - Layer 20, z:8.2 - - - - - Layer 21, z:8.6 - - - - - Layer 22, z:9.0 - - - - - Layer 23, z:9.4 - - - - - Layer 24, z:9.8 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 10.0 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 151.1382 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 10.0 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 151.1382 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 10.0 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 151.1382 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/creation/gear/shaft_top.xml b/skeinforge/models/xml_models/creation/gear/shaft_top.xml deleted file mode 100644 index e5568e7..0000000 --- a/skeinforge/models/xml_models/creation/gear/shaft_top.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/creation/gear/spur_helix.svg b/skeinforge/models/xml_models/creation/gear/spur_helix.svg deleted file mode 100644 index 161d4e9..0000000 --- a/skeinforge/models/xml_models/creation/gear/spur_helix.svg +++ /dev/null @@ -1,574 +0,0 @@ - - - - - - - - spur_helix.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - Layer 2, z:1.0 - - - - - Layer 3, z:1.4 - - - - - Layer 4, z:1.8 - - - - - Layer 5, z:2.2 - - - - - Layer 6, z:2.6 - - - - - Layer 7, z:3.0 - - - - - Layer 8, z:3.4 - - - - - Layer 9, z:3.8 - - - - - Layer 10, z:4.2 - - - - - Layer 11, z:4.6 - - - - - Layer 12, z:5.0 - - - - - Layer 13, z:5.4 - - - - - Layer 14, z:5.8 - - - - - Layer 15, z:6.2 - - - - - Layer 16, z:6.6 - - - - - Layer 17, z:7.0 - - - - - Layer 18, z:7.4 - - - - - Layer 19, z:7.8 - - - - - Layer 20, z:8.2 - - - - - Layer 21, z:8.6 - - - - - Layer 22, z:9.0 - - - - - Layer 23, z:9.4 - - - - - Layer 24, z:9.8 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -50.4346 mm - Y: -150.4247 mm - Z: 0.0 mm - - - Max - X: 50.4288 mm - Y: 22.1224 mm - Z: 10.0 mm - - - Dimension - X: 100.8635 mm - Y: 172.5471 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 150.9143 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -50.4346 mm - Y: -150.4247 mm - Z: 0.0 mm - - - Max - X: 50.4288 mm - Y: 22.1224 mm - Z: 10.0 mm - - - Dimension - X: 100.8635 mm - Y: 172.5471 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 150.9143 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -50.4346 mm - Y: -150.4247 mm - Z: 0.0 mm - - - Max - X: 50.4288 mm - Y: 22.1224 mm - Z: 10.0 mm - - - Dimension - X: 100.8635 mm - Y: 172.5471 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 150.9143 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/creation/gear/spur_helix.xml b/skeinforge/models/xml_models/creation/gear/spur_helix.xml deleted file mode 100644 index a0bc6d8..0000000 --- a/skeinforge/models/xml_models/creation/gear/spur_helix.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/creation/gear/spur_herringbone.svg b/skeinforge/models/xml_models/creation/gear/spur_herringbone.svg deleted file mode 100644 index 813f0ea..0000000 --- a/skeinforge/models/xml_models/creation/gear/spur_herringbone.svg +++ /dev/null @@ -1,574 +0,0 @@ - - - - - - - - spur_herringbone.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - Layer 2, z:1.0 - - - - - Layer 3, z:1.4 - - - - - Layer 4, z:1.8 - - - - - Layer 5, z:2.2 - - - - - Layer 6, z:2.6 - - - - - Layer 7, z:3.0 - - - - - Layer 8, z:3.4 - - - - - Layer 9, z:3.8 - - - - - Layer 10, z:4.2 - - - - - Layer 11, z:4.6 - - - - - Layer 12, z:5.0 - - - - - Layer 13, z:5.4 - - - - - Layer 14, z:5.8 - - - - - Layer 15, z:6.2 - - - - - Layer 16, z:6.6 - - - - - Layer 17, z:7.0 - - - - - Layer 18, z:7.4 - - - - - Layer 19, z:7.8 - - - - - Layer 20, z:8.2 - - - - - Layer 21, z:8.6 - - - - - Layer 22, z:9.0 - - - - - Layer 23, z:9.4 - - - - - Layer 24, z:9.8 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -50.4225 mm - Y: -150.4395 mm - Z: 0.0 mm - - - Max - X: 50.4306 mm - Y: 22.1224 mm - Z: 10.0 mm - - - Dimension - X: 100.8531 mm - Y: 172.5619 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 150.9346 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -50.4225 mm - Y: -150.4395 mm - Z: 0.0 mm - - - Max - X: 50.4306 mm - Y: 22.1224 mm - Z: 10.0 mm - - - Dimension - X: 100.8531 mm - Y: 172.5619 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 150.9346 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -50.4225 mm - Y: -150.4395 mm - Z: 0.0 mm - - - Max - X: 50.4306 mm - Y: 22.1224 mm - Z: 10.0 mm - - - Dimension - X: 100.8531 mm - Y: 172.5619 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 150.9346 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/creation/gear/spur_herringbone.xml b/skeinforge/models/xml_models/creation/gear/spur_herringbone.xml deleted file mode 100644 index ef8b8de..0000000 --- a/skeinforge/models/xml_models/creation/gear/spur_herringbone.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/creation/gear/spur_parabolic.svg b/skeinforge/models/xml_models/creation/gear/spur_parabolic.svg deleted file mode 100644 index 65414c2..0000000 --- a/skeinforge/models/xml_models/creation/gear/spur_parabolic.svg +++ /dev/null @@ -1,574 +0,0 @@ - - - - - - - - spur_parabolic.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - Layer 2, z:1.0 - - - - - Layer 3, z:1.4 - - - - - Layer 4, z:1.8 - - - - - Layer 5, z:2.2 - - - - - Layer 6, z:2.6 - - - - - Layer 7, z:3.0 - - - - - Layer 8, z:3.4 - - - - - Layer 9, z:3.8 - - - - - Layer 10, z:4.2 - - - - - Layer 11, z:4.6 - - - - - Layer 12, z:5.0 - - - - - Layer 13, z:5.4 - - - - - Layer 14, z:5.8 - - - - - Layer 15, z:6.2 - - - - - Layer 16, z:6.6 - - - - - Layer 17, z:7.0 - - - - - Layer 18, z:7.4 - - - - - Layer 19, z:7.8 - - - - - Layer 20, z:8.2 - - - - - Layer 21, z:8.6 - - - - - Layer 22, z:9.0 - - - - - Layer 23, z:9.4 - - - - - Layer 24, z:9.8 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -50.4272 mm - Y: -150.3492 mm - Z: 0.0 mm - - - Max - X: 50.4412 mm - Y: 22.1077 mm - Z: 10.0 mm - - - Dimension - X: 100.8684 mm - Y: 172.4569 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 151.0364 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -50.4272 mm - Y: -150.3492 mm - Z: 0.0 mm - - - Max - X: 50.4412 mm - Y: 22.1077 mm - Z: 10.0 mm - - - Dimension - X: 100.8684 mm - Y: 172.4569 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 151.0364 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -50.4272 mm - Y: -150.3492 mm - Z: 0.0 mm - - - Max - X: 50.4412 mm - Y: 22.1077 mm - Z: 10.0 mm - - - Dimension - X: 100.8684 mm - Y: 172.4569 mm - Z: 10.0 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 25 - Volume: 151.0364 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/creation/gear/spur_parabolic.xml b/skeinforge/models/xml_models/creation/gear/spur_parabolic.xml deleted file mode 100644 index a0e8a4f..0000000 --- a/skeinforge/models/xml_models/creation/gear/spur_parabolic.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/creation/gear/spur_profile.svg b/skeinforge/models/xml_models/creation/gear/spur_profile.svg deleted file mode 100644 index ff53ba5..0000000 --- a/skeinforge/models/xml_models/creation/gear/spur_profile.svg +++ /dev/null @@ -1,460 +0,0 @@ - - - - - - - - spur_profile.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 0.8 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 0.8 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 2 - Volume: 16.6701 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 0.8 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 0.8 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 2 - Volume: 16.6701 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -50.4319 mm - Y: -150.126 mm - Z: 0.0 mm - - - Max - X: 50.4319 mm - Y: 21.8248 mm - Z: 0.8 mm - - - Dimension - X: 100.8638 mm - Y: 171.9508 mm - Z: 0.8 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 2 - Volume: 16.6701 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/creation/gear/spur_profile.xml b/skeinforge/models/xml_models/creation/gear/spur_profile.xml deleted file mode 100644 index 1d8c643..0000000 --- a/skeinforge/models/xml_models/creation/gear/spur_profile.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/creation/grid.xml b/skeinforge/models/xml_models/creation/grid.xml deleted file mode 100644 index c9333bd..0000000 --- a/skeinforge/models/xml_models/creation/grid.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/skeinforge/models/xml_models/creation/heightmap.xml b/skeinforge/models/xml_models/creation/heightmap.xml deleted file mode 100644 index bc982d2..0000000 --- a/skeinforge/models/xml_models/creation/heightmap.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/creation/heightmap_1.pgm b/skeinforge/models/xml_models/creation/heightmap_1.pgm deleted file mode 100644 index c8e23b4..0000000 --- a/skeinforge/models/xml_models/creation/heightmap_1.pgm +++ /dev/null @@ -1,9 +0,0 @@ -P1 -# CREATOR: GIMP PNM Filter Version 1.1 -3 2 -1 -0 -1 -1 -0 -1 \ No newline at end of file diff --git a/skeinforge/models/xml_models/creation/heightmap_255.pgm b/skeinforge/models/xml_models/creation/heightmap_255.pgm deleted file mode 100644 index 2425437..0000000 --- a/skeinforge/models/xml_models/creation/heightmap_255.pgm +++ /dev/null @@ -1,201 +0,0 @@ -P2 -# CREATOR: GIMP PNM Filter Version 1.1 -20 10 -255 -255 -255 -255 -255 -229 120 19 0 -0 -0 -0 -0 -0 -19 -120 -229 -255 -255 -255 -255 -255 -255 -255 -255 -197 -70 -0 -0 -0 -0 -0 -0 -0 -0 -70 -197 -255 -255 -255 -255 -255 -255 -255 -255 -140 -12 -0 -0 -0 -0 -0 -0 -0 -0 -12 -140 -255 -255 -255 -255 -255 -255 -255 -255 -128 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -128 -255 -255 -255 -255 -255 -255 -255 -255 -128 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -128 -255 -255 -255 -255 -255 -255 -255 -255 -179 -51 -0 -0 -0 -0 -0 -0 -0 -0 -51 -179 -255 -255 -255 -255 -255 -255 -255 -255 -217 -89 -0 -0 -0 -0 -0 -0 -0 -0 -89 -217 -255 -255 -255 -255 -255 -255 -255 -255 -249 -198 -77 -0 -0 -0 -0 -0 -0 -77 -198 -249 -255 -255 -255 -255 -255 -255 -255 -255 -255 -249 -198 -128 -51 -0 -0 -51 -128 -198 -249 -255 -255 -255 -255 -255 -255 -255 -255 -255 -255 -255 -249 -236 -218 -205 -205 -218 -236 -249 -255 -255 -255 -255 -255 -255 diff --git a/skeinforge/models/xml_models/creation/lathe.xml b/skeinforge/models/xml_models/creation/lathe.xml deleted file mode 100644 index 8f1e5a2..0000000 --- a/skeinforge/models/xml_models/creation/lathe.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/creation/line.xml b/skeinforge/models/xml_models/creation/line.xml deleted file mode 100644 index 3c94c1e..0000000 --- a/skeinforge/models/xml_models/creation/line.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/creation/linear_bearing_cage.xml b/skeinforge/models/xml_models/creation/linear_bearing_cage.xml deleted file mode 100644 index 14b9ed9..0000000 --- a/skeinforge/models/xml_models/creation/linear_bearing_cage.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/creation/lineation.xml b/skeinforge/models/xml_models/creation/lineation.xml deleted file mode 100644 index 9028433..0000000 --- a/skeinforge/models/xml_models/creation/lineation.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/creation/mechaslab.xml b/skeinforge/models/xml_models/creation/mechaslab.xml deleted file mode 100644 index e98cc66..0000000 --- a/skeinforge/models/xml_models/creation/mechaslab.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/creation/peg.xml b/skeinforge/models/xml_models/creation/peg.xml deleted file mode 100644 index 8a6d296..0000000 --- a/skeinforge/models/xml_models/creation/peg.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/creation/polygon.xml b/skeinforge/models/xml_models/creation/polygon.xml deleted file mode 100644 index ac8bc0f..0000000 --- a/skeinforge/models/xml_models/creation/polygon.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/creation/shaft.xml b/skeinforge/models/xml_models/creation/shaft.xml deleted file mode 100644 index 443a122..0000000 --- a/skeinforge/models/xml_models/creation/shaft.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/creation/square.xml b/skeinforge/models/xml_models/creation/square.xml deleted file mode 100644 index a322f41..0000000 --- a/skeinforge/models/xml_models/creation/square.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/creation/svg.xml b/skeinforge/models/xml_models/creation/svg.xml deleted file mode 100644 index 45f9961..0000000 --- a/skeinforge/models/xml_models/creation/svg.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - diff --git a/skeinforge/models/xml_models/creation/teardrop.xml b/skeinforge/models/xml_models/creation/teardrop.xml deleted file mode 100644 index a3a2636..0000000 --- a/skeinforge/models/xml_models/creation/teardrop.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/creation/text.xml b/skeinforge/models/xml_models/creation/text.xml deleted file mode 100644 index 9880fed..0000000 --- a/skeinforge/models/xml_models/creation/text.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - hi - - diff --git a/skeinforge/models/xml_models/geometry.csv b/skeinforge/models/xml_models/geometry.csv deleted file mode 100644 index 5d6b1a0..0000000 --- a/skeinforge/models/xml_models/geometry.csv +++ /dev/null @@ -1,25 +0,0 @@ -Format is tab separated boolean geometry. -Name Value -_object booleangeometry -version 2010-03-29 -_object trianglemesh -id tetrahedron - _object matrix4x4 - m11 0.0 - m13 1.0 - m21 -1.0 - m22 0.0 - m32 -1.0 - m33 0.0 - _table vertex - x y z - -5.0 2.89 - -5.77 - 5.0 2.89 - 8.66 - _table face - vertex0 vertex1 vertex2 - 3 0 1 - 3 1 2 - 3 2 0 - 0 2 1 diff --git a/skeinforge/models/xml_models/geometry_tools/path_elements/arc.xml b/skeinforge/models/xml_models/geometry_tools/path_elements/arc.xml deleted file mode 100644 index 2315b3d..0000000 --- a/skeinforge/models/xml_models/geometry_tools/path_elements/arc.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/geometry_tools/path_elements/cubic.xml b/skeinforge/models/xml_models/geometry_tools/path_elements/cubic.xml deleted file mode 100644 index bb38791..0000000 --- a/skeinforge/models/xml_models/geometry_tools/path_elements/cubic.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/geometry_tools/path_elements/quadratic.xml b/skeinforge/models/xml_models/geometry_tools/path_elements/quadratic.xml deleted file mode 100644 index 7364d9f..0000000 --- a/skeinforge/models/xml_models/geometry_tools/path_elements/quadratic.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/geometry_utilities/evaluate.xml b/skeinforge/models/xml_models/geometry_utilities/evaluate.xml deleted file mode 100644 index e77b671..0000000 --- a/skeinforge/models/xml_models/geometry_utilities/evaluate.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/geometry_utilities/evaluate_elements/creation.xml b/skeinforge/models/xml_models/geometry_utilities/evaluate_elements/creation.xml deleted file mode 100644 index 3f8806c..0000000 --- a/skeinforge/models/xml_models/geometry_utilities/evaluate_elements/creation.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/geometry_utilities/evaluate_elements/document.xml b/skeinforge/models/xml_models/geometry_utilities/evaluate_elements/document.xml deleted file mode 100644 index a6cd11e..0000000 --- a/skeinforge/models/xml_models/geometry_utilities/evaluate_elements/document.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/geometry_utilities/evaluate_elements/setting.xml b/skeinforge/models/xml_models/geometry_utilities/evaluate_elements/setting.xml deleted file mode 100644 index 39312cd..0000000 --- a/skeinforge/models/xml_models/geometry_utilities/evaluate_elements/setting.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/geometry_utilities/evaluate_enumerables/dictionary.xml b/skeinforge/models/xml_models/geometry_utilities/evaluate_enumerables/dictionary.xml deleted file mode 100644 index 8b072b0..0000000 --- a/skeinforge/models/xml_models/geometry_utilities/evaluate_enumerables/dictionary.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/geometry_utilities/evaluate_enumerables/list.xml b/skeinforge/models/xml_models/geometry_utilities/evaluate_enumerables/list.xml deleted file mode 100644 index 7efb1d3..0000000 --- a/skeinforge/models/xml_models/geometry_utilities/evaluate_enumerables/list.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/geometry_utilities/evaluate_enumerables/string.xml b/skeinforge/models/xml_models/geometry_utilities/evaluate_enumerables/string.xml deleted file mode 100644 index 18da3be..0000000 --- a/skeinforge/models/xml_models/geometry_utilities/evaluate_enumerables/string.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/geometry_utilities/evaluate_fundamentals/euclid.xml b/skeinforge/models/xml_models/geometry_utilities/evaluate_fundamentals/euclid.xml deleted file mode 100644 index a1ba2b0..0000000 --- a/skeinforge/models/xml_models/geometry_utilities/evaluate_fundamentals/euclid.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/geometry_utilities/evaluate_fundamentals/math.xml b/skeinforge/models/xml_models/geometry_utilities/evaluate_fundamentals/math.xml deleted file mode 100644 index 1540842..0000000 --- a/skeinforge/models/xml_models/geometry_utilities/evaluate_fundamentals/math.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/geometry_utilities/evaluate_fundamentals/print.xml b/skeinforge/models/xml_models/geometry_utilities/evaluate_fundamentals/print.xml deleted file mode 100644 index be2727c..0000000 --- a/skeinforge/models/xml_models/geometry_utilities/evaluate_fundamentals/print.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - hello - - - - - diff --git a/skeinforge/models/xml_models/manipulation_matrix/rotate.xml b/skeinforge/models/xml_models/manipulation_matrix/rotate.xml deleted file mode 100644 index 4a5fe62..0000000 --- a/skeinforge/models/xml_models/manipulation_matrix/rotate.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/manipulation_matrix/scale.xml b/skeinforge/models/xml_models/manipulation_matrix/scale.xml deleted file mode 100644 index 6ac9867..0000000 --- a/skeinforge/models/xml_models/manipulation_matrix/scale.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/manipulation_matrix/transform.xml b/skeinforge/models/xml_models/manipulation_matrix/transform.xml deleted file mode 100644 index e9e9a11..0000000 --- a/skeinforge/models/xml_models/manipulation_matrix/transform.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/manipulation_matrix/translate.xml b/skeinforge/models/xml_models/manipulation_matrix/translate.xml deleted file mode 100644 index f45587a..0000000 --- a/skeinforge/models/xml_models/manipulation_matrix/translate.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/manipulation_meta/array.xml b/skeinforge/models/xml_models/manipulation_meta/array.xml deleted file mode 100644 index 2a08f45..0000000 --- a/skeinforge/models/xml_models/manipulation_meta/array.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - diff --git a/skeinforge/models/xml_models/manipulation_meta/copy.xml b/skeinforge/models/xml_models/manipulation_meta/copy.xml deleted file mode 100644 index fafd795..0000000 --- a/skeinforge/models/xml_models/manipulation_meta/copy.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/manipulation_meta/disjoin.xml b/skeinforge/models/xml_models/manipulation_meta/disjoin.xml deleted file mode 100644 index 4abf001..0000000 --- a/skeinforge/models/xml_models/manipulation_meta/disjoin.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - diff --git a/skeinforge/models/xml_models/manipulation_meta/import.xml b/skeinforge/models/xml_models/manipulation_meta/import.xml deleted file mode 100644 index f7b0415..0000000 --- a/skeinforge/models/xml_models/manipulation_meta/import.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - diff --git a/skeinforge/models/xml_models/manipulation_meta/pathTest.svg b/skeinforge/models/xml_models/manipulation_meta/pathTest.svg deleted file mode 100644 index 7e4d0dd..0000000 --- a/skeinforge/models/xml_models/manipulation_meta/pathTest.svg +++ /dev/null @@ -1,490 +0,0 @@ - - - - - - - - write.xml - Slice Layers - - - - - - Layer 0, z:0.0 - - - - - Layer 1, z:5.0 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -9.0 mm - Y: -9.0 mm - Z: -1.5 mm - - - Max - X: 9.0 mm - Y: 15.0 mm - Z: 6.5 mm - - - Dimension - X: 18.0 mm - Y: 24.0 mm - Z: 8.0 mm - - - Statistics - Layer Thickness: 3.0 mm - Number of Layers: 2 - Volume: 0.33 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -9.0 mm - Y: -9.0 mm - Z: -1.5 mm - - - Max - X: 9.0 mm - Y: 15.0 mm - Z: 6.5 mm - - - Dimension - X: 18.0 mm - Y: 24.0 mm - Z: 8.0 mm - - - Statistics - Layer Thickness: 3.0 mm - Number of Layers: 2 - Volume: 0.33 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -9.0 mm - Y: -9.0 mm - Z: -1.5 mm - - - Max - X: 9.0 mm - Y: 15.0 mm - Z: 6.5 mm - - - Dimension - X: 18.0 mm - Y: 24.0 mm - Z: 8.0 mm - - - Statistics - Layer Thickness: 3.0 mm - Number of Layers: 2 - Volume: 0.33 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/manipulation_meta/write.xml b/skeinforge/models/xml_models/manipulation_meta/write.xml deleted file mode 100644 index 42bc509..0000000 --- a/skeinforge/models/xml_models/manipulation_meta/write.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/manipulation_meta/writeTest.xml b/skeinforge/models/xml_models/manipulation_meta/writeTest.xml deleted file mode 100644 index 0c1e269..0000000 --- a/skeinforge/models/xml_models/manipulation_meta/writeTest.xml +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/manipulation_meta/writeTest_2.xml b/skeinforge/models/xml_models/manipulation_meta/writeTest_2.xml deleted file mode 100644 index 0c1e269..0000000 --- a/skeinforge/models/xml_models/manipulation_meta/writeTest_2.xml +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/manipulation_paths/bevel.xml b/skeinforge/models/xml_models/manipulation_paths/bevel.xml deleted file mode 100644 index 68ce115..0000000 --- a/skeinforge/models/xml_models/manipulation_paths/bevel.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/manipulation_paths/convex.xml b/skeinforge/models/xml_models/manipulation_paths/convex.xml deleted file mode 100644 index 185885c..0000000 --- a/skeinforge/models/xml_models/manipulation_paths/convex.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/manipulation_paths/inset.xml b/skeinforge/models/xml_models/manipulation_paths/inset.xml deleted file mode 100644 index e75b16d..0000000 --- a/skeinforge/models/xml_models/manipulation_paths/inset.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/manipulation_paths/outline.xml b/skeinforge/models/xml_models/manipulation_paths/outline.xml deleted file mode 100644 index 0c73ec1..0000000 --- a/skeinforge/models/xml_models/manipulation_paths/outline.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/manipulation_paths/outset.xml b/skeinforge/models/xml_models/manipulation_paths/outset.xml deleted file mode 100644 index 6788280..0000000 --- a/skeinforge/models/xml_models/manipulation_paths/outset.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/manipulation_paths/overhang.xml b/skeinforge/models/xml_models/manipulation_paths/overhang.xml deleted file mode 100644 index 17d9782..0000000 --- a/skeinforge/models/xml_models/manipulation_paths/overhang.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/skeinforge/models/xml_models/manipulation_paths/round.xml b/skeinforge/models/xml_models/manipulation_paths/round.xml deleted file mode 100644 index b2dffd3..0000000 --- a/skeinforge/models/xml_models/manipulation_paths/round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/manipulation_paths/segment.xml b/skeinforge/models/xml_models/manipulation_paths/segment.xml deleted file mode 100644 index 8c431f9..0000000 --- a/skeinforge/models/xml_models/manipulation_paths/segment.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/skeinforge/models/xml_models/manipulation_paths/wedge.xml b/skeinforge/models/xml_models/manipulation_paths/wedge.xml deleted file mode 100644 index 577082a..0000000 --- a/skeinforge/models/xml_models/manipulation_paths/wedge.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/skeinforge/models/xml_models/manipulation_shapes/bottom.xml b/skeinforge/models/xml_models/manipulation_shapes/bottom.xml deleted file mode 100644 index 85936f2..0000000 --- a/skeinforge/models/xml_models/manipulation_shapes/bottom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/manipulation_shapes/equation.xml b/skeinforge/models/xml_models/manipulation_shapes/equation.xml deleted file mode 100644 index 7c5e763..0000000 --- a/skeinforge/models/xml_models/manipulation_shapes/equation.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/skeinforge/models/xml_models/manipulation_shapes/flip/flip_element.svg b/skeinforge/models/xml_models/manipulation_shapes/flip/flip_element.svg deleted file mode 100644 index 6c7bd7e..0000000 --- a/skeinforge/models/xml_models/manipulation_shapes/flip/flip_element.svg +++ /dev/null @@ -1,461 +0,0 @@ - - - - - - - - flip_element.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -9.5508 mm - Y: 0.0 mm - Z: 0.0 mm - - - Max - X: -0.3223 mm - Y: 9.082 mm - Z: 0.8 mm - - - Dimension - X: 9.2285 mm - Y: 9.082 mm - Z: 0.8 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 2 - Volume: 0.0475 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -9.5508 mm - Y: 0.0 mm - Z: 0.0 mm - - - Max - X: -0.3223 mm - Y: 9.082 mm - Z: 0.8 mm - - - Dimension - X: 9.2285 mm - Y: 9.082 mm - Z: 0.8 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 2 - Volume: 0.0475 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -9.5508 mm - Y: 0.0 mm - Z: 0.0 mm - - - Max - X: -0.3223 mm - Y: 9.082 mm - Z: 0.8 mm - - - Dimension - X: 9.2285 mm - Y: 9.082 mm - Z: 0.8 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 2 - Volume: 0.0475 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/manipulation_shapes/flip/flip_element.xml b/skeinforge/models/xml_models/manipulation_shapes/flip/flip_element.xml deleted file mode 100644 index 92c3d29..0000000 --- a/skeinforge/models/xml_models/manipulation_shapes/flip/flip_element.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - hi - - - diff --git a/skeinforge/models/xml_models/manipulation_shapes/flip/flip_path.svg b/skeinforge/models/xml_models/manipulation_shapes/flip/flip_path.svg deleted file mode 100644 index ea9e48d..0000000 --- a/skeinforge/models/xml_models/manipulation_shapes/flip/flip_path.svg +++ /dev/null @@ -1,460 +0,0 @@ - - - - - - - - flip_path.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -20.0 mm - Y: 0.0 mm - Z: 0.0 mm - - - Max - X: -10.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Dimension - X: 10.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 2 - Volume: 0.1 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -20.0 mm - Y: 0.0 mm - Z: 0.0 mm - - - Max - X: -10.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Dimension - X: 10.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 2 - Volume: 0.1 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -20.0 mm - Y: 0.0 mm - Z: 0.0 mm - - - Max - X: -10.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Dimension - X: 10.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 2 - Volume: 0.1 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/manipulation_shapes/flip/flip_path.xml b/skeinforge/models/xml_models/manipulation_shapes/flip/flip_path.xml deleted file mode 100644 index f733855..0000000 --- a/skeinforge/models/xml_models/manipulation_shapes/flip/flip_path.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/manipulation_shapes/flip/flip_solid.svg b/skeinforge/models/xml_models/manipulation_shapes/flip/flip_solid.svg deleted file mode 100644 index c2be263..0000000 --- a/skeinforge/models/xml_models/manipulation_shapes/flip/flip_solid.svg +++ /dev/null @@ -1,459 +0,0 @@ - - - - - - - - flip_solid.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -20.0 mm - Y: 0.0 mm - Z: 0.0 mm - - - Max - X: -10.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Dimension - X: 10.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 2 - Volume: 0.1 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -20.0 mm - Y: 0.0 mm - Z: 0.0 mm - - - Max - X: -10.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Dimension - X: 10.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 2 - Volume: 0.1 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -20.0 mm - Y: 0.0 mm - Z: 0.0 mm - - - Max - X: -10.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Dimension - X: 10.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 2 - Volume: 0.1 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/manipulation_shapes/flip/flip_solid.xml b/skeinforge/models/xml_models/manipulation_shapes/flip/flip_solid.xml deleted file mode 100644 index e3b9a25..0000000 --- a/skeinforge/models/xml_models/manipulation_shapes/flip/flip_solid.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/manipulation_shapes/mirror/mirror_element.xml b/skeinforge/models/xml_models/manipulation_shapes/mirror/mirror_element.xml deleted file mode 100644 index 73373e2..0000000 --- a/skeinforge/models/xml_models/manipulation_shapes/mirror/mirror_element.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/manipulation_shapes/mirror/mirror_path.svg b/skeinforge/models/xml_models/manipulation_shapes/mirror/mirror_path.svg deleted file mode 100644 index da2c48f..0000000 --- a/skeinforge/models/xml_models/manipulation_shapes/mirror/mirror_path.svg +++ /dev/null @@ -1,460 +0,0 @@ - - - - - - - - mirror_path.xml - Slice Layers - - - - - - Layer 0, z:0.2 - - - - - Layer 1, z:0.6 - - - - - - - - - - - - - Latitude - < - > - Longitude - < - > - Scale - 1 - < - > - - Min - X: -20.0 mm - Y: 0.0 mm - Z: 0.0 mm - - - Max - X: 20.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Dimension - X: 40.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 2 - Volume: 2.0 cm3 - - - - - - - - Y - X - 0 - - - 1 - Layer - < - > - Scale - 1 - < - > - - Min - X: -20.0 mm - Y: 0.0 mm - Z: 0.0 mm - - - Max - X: 20.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Dimension - X: 40.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 2 - Volume: 2.0 cm3 - - - - - - - Y - X - Scale - : 1 - < - > - - Min - X: -20.0 mm - Y: 0.0 mm - Z: 0.0 mm - - - Max - X: 20.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Dimension - X: 40.0 mm - Y: 30.0 mm - Z: 0.8 mm - - - Statistics - Layer Thickness: 0.4 mm - Number of Layers: 2 - Volume: 2.0 cm3 - - - [Iso View] - Iso View - [Layer View] - Layer View - [Scroll View] - Scroll View - - - diff --git a/skeinforge/models/xml_models/manipulation_shapes/mirror/mirror_path.xml b/skeinforge/models/xml_models/manipulation_shapes/mirror/mirror_path.xml deleted file mode 100644 index f41bf70..0000000 --- a/skeinforge/models/xml_models/manipulation_shapes/mirror/mirror_path.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/skeinforge/models/xml_models/manipulation_shapes/mirror/mirror_solid.xml b/skeinforge/models/xml_models/manipulation_shapes/mirror/mirror_solid.xml deleted file mode 100644 index debaef4..0000000 --- a/skeinforge/models/xml_models/manipulation_shapes/mirror/mirror_solid.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/slab.xml b/skeinforge/models/xml_models/slab.xml deleted file mode 100644 index e30dec7..0000000 --- a/skeinforge/models/xml_models/slab.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/solids/cube.xml b/skeinforge/models/xml_models/solids/cube.xml deleted file mode 100644 index 0f89ca3..0000000 --- a/skeinforge/models/xml_models/solids/cube.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/solids/cylinder.xml b/skeinforge/models/xml_models/solids/cylinder.xml deleted file mode 100644 index ca78e18..0000000 --- a/skeinforge/models/xml_models/solids/cylinder.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/solids/difference.xml b/skeinforge/models/xml_models/solids/difference.xml deleted file mode 100644 index 0731d67..0000000 --- a/skeinforge/models/xml_models/solids/difference.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - diff --git a/skeinforge/models/xml_models/solids/sphere.xml b/skeinforge/models/xml_models/solids/sphere.xml deleted file mode 100644 index 0fab81c..0000000 --- a/skeinforge/models/xml_models/solids/sphere.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/skeinforge/models/xml_models/solids/union.xml b/skeinforge/models/xml_models/solids/union.xml deleted file mode 100644 index 7ca2f79..0000000 --- a/skeinforge/models/xml_models/solids/union.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/statements/class.xml b/skeinforge/models/xml_models/statements/class.xml deleted file mode 100644 index 857720f..0000000 --- a/skeinforge/models/xml_models/statements/class.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/statements/elif.xml b/skeinforge/models/xml_models/statements/elif.xml deleted file mode 100644 index 2d20e7a..0000000 --- a/skeinforge/models/xml_models/statements/elif.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/statements/else.xml b/skeinforge/models/xml_models/statements/else.xml deleted file mode 100644 index 4075942..0000000 --- a/skeinforge/models/xml_models/statements/else.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/statements/for.xml b/skeinforge/models/xml_models/statements/for.xml deleted file mode 100644 index b379827..0000000 --- a/skeinforge/models/xml_models/statements/for.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/statements/function.xml b/skeinforge/models/xml_models/statements/function.xml deleted file mode 100644 index 2c71034..0000000 --- a/skeinforge/models/xml_models/statements/function.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/skeinforge/models/xml_models/statements/if.xml b/skeinforge/models/xml_models/statements/if.xml deleted file mode 100644 index f338a6f..0000000 --- a/skeinforge/models/xml_models/statements/if.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/statements/print.xml b/skeinforge/models/xml_models/statements/print.xml deleted file mode 100644 index 6ce4bff..0000000 --- a/skeinforge/models/xml_models/statements/print.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/skeinforge/models/xml_models/statements/return.xml b/skeinforge/models/xml_models/statements/return.xml deleted file mode 100644 index 243a0d2..0000000 --- a/skeinforge/models/xml_models/statements/return.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/skeinforge/models/xml_models/statements/statement.xml b/skeinforge/models/xml_models/statements/statement.xml deleted file mode 100644 index 413ccf3..0000000 --- a/skeinforge/models/xml_models/statements/statement.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/skeinforge/models/xml_models/statements/while.xml b/skeinforge/models/xml_models/statements/while.xml deleted file mode 100644 index 810edad..0000000 --- a/skeinforge/models/xml_models/statements/while.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/support_test_box.xml b/skeinforge/models/xml_models/support_test_box.xml deleted file mode 100644 index 600c7d1..0000000 --- a/skeinforge/models/xml_models/support_test_box.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/skeinforge/models/xml_models/tetra.xml b/skeinforge/models/xml_models/tetra.xml deleted file mode 100644 index 1c07c14..0000000 --- a/skeinforge/models/xml_models/tetra.xml +++ /dev/null @@ -1,1330 +0,0 @@ - - - - - - - - - - - - - - - - Default Texture - - - - - - - - - - - - - - - - - - - - - - - - - - Camera 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - Light 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - tetrax20 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - tetray40 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - tetraz30 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - tetrax20y40 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - tetrax20z30 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - tetray40z30 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - tetrax20y40z30 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/models/xml_models/tetrawedge.xml b/skeinforge/models/xml_models/tetrawedge.xml deleted file mode 100644 index db79680..0000000 --- a/skeinforge/models/xml_models/tetrawedge.xml +++ /dev/null @@ -1,388 +0,0 @@ - - - - - - - - - - - - - - - - Default Texture - - - - - - - - - - - - - - - - - - - - - - - - - - Camera 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - Light 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - tetrawedge - - - - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Position - - - - - - - - - - - - - - - - - - - - - - - - Weight - - Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/skeinforge/skeinforge_application/SkeinArchiver.pyw b/skeinforge/skeinforge_application/SkeinArchiver.pyw deleted file mode 100644 index 1012130..0000000 --- a/skeinforge/skeinforge_application/SkeinArchiver.pyw +++ /dev/null @@ -1,81 +0,0 @@ -#! /usr/bin/python - -# Title: SkeinArchiver.py -# Author: James Blackwell -# Date: 20-Apr-11 -# Desc: This script provides a simple GUI to save and restore Skeinforge user settings. - - -from __future__ import with_statement -import sys, os, datetime -import Tkinter, tkMessageBox, tkFileDialog -from contextlib import closing -from zipfile import ZipFile, ZIP_DEFLATED - - -AboutString = 'SkeinArchiver v0.1\nAuthor: James Blackwell\nDate: 20-Apr-11' -ArchDir = None - -def ZipDir(basedir, archivename): - """Zip everything in the specified directory and put in the specified archive""" - assert os.path.isdir(basedir) - with closing(ZipFile(archivename, "w", ZIP_DEFLATED)) as z: - for root, dirs, files in os.walk(basedir): - #NOTE: ignore empty directories - for fn in files: - absfn = os.path.join(root, fn) - zfn = absfn[len(basedir)+len(os.sep):] #XXX: relative path - z.write(absfn, zfn) - -def UnzipDir(basedir, archivename): - """Unzip everything from the specified archive to the specified directory""" - zip = ZipFile(archivename, 'r') - zip.extractall(basedir) - -def About(): - """Show the About Information""" - tkMessageBox.showinfo(title='About', message=AboutString) - -def Save(): - """Allow user to specify zip filename, then zip up everything in the archive directory""" - file='Archived Settings %s.zip' % (datetime.datetime.today().strftime('%d%b%y')) - filename = tkFileDialog.asksaveasfilename(defaultextension='zip', initialfile=file) - if filename != '': - ZipDir(ArchDir, filename) - -def Restore(): - """Let the user pick a zip file to restore to the archive directory""" - filename = tkFileDialog.askopenfilename(filetypes=[('zip files', '.zip')]) - if filename != '': - UnzipDir(ArchDir, filename) - -def SetArch(): - """Allow the user to select the archive directory, it defaults to the default Skeinforge directory""" - global ArchDir - dir = tkFileDialog.askdirectory(initialdir=ArchDir) - if dir != '': - ArchDir = dir - -def BuildMainWindow(tk): - """Build the main window of the program""" - pad = 2 - width = 9 - tk.Label(text='SkeinArchiver').grid(row=0, column=0, columnspan=2)#pack(fill=Tkinter.X) - - tk.Button(text='Save', width=width, command=Save).grid(row=1, column=0, padx=pad, pady =pad) - tk.Button(text='Restore', width=width, command=Restore).grid(row=1, column=1, padx=pad, pady =pad) - tk.Button(text='Dir to Arch', width=width, command=SetArch).grid(row=2, column=0, padx=pad, pady =pad) - tk.Button(text='About', width=width, command=About).grid(row=2, column=1, padx=pad, pady =pad) - tk.Button(text='Quit', width=width, command=sys.exit).grid(row=3, column=0, columnspan=2, padx=pad, pady =pad) - -def Main(): - global ArchDir - # Set Archive Directory to the default Skeinforge settings directory - ArchDir = os.path.expanduser('~') + '\.skeinforge' - root = Tkinter.Tk() - root.title('SkeinArchiver') - BuildMainWindow(Tkinter) - root.mainloop() - -if __name__ == '__main__': - Main() \ No newline at end of file diff --git a/skeinforge/skeinforge_application/__init__.py b/skeinforge/skeinforge_application/__init__.py deleted file mode 100644 index bdac25d..0000000 --- a/skeinforge/skeinforge_application/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 1 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/skeinforge_application/alterations/end.gmc b/skeinforge/skeinforge_application/alterations/end.gmc deleted file mode 100644 index bf7a4c8..0000000 --- a/skeinforge/skeinforge_application/alterations/end.gmc +++ /dev/null @@ -1,15 +0,0 @@ -G91 ; Make coordinates relative -G92 E0 ; reset Extruder counter -G1 E-2 F900 ;Retract extuder 2mm at 900mm/min -G1 Z2 F400 ;Move up tw mm (from current position because it is all relative now) -G1 Z2 F5000 ; Move Z another 2mm up -G90 ; Use absolute coordinates again -G1 X5 Y5 F3000.0 ;go to almost home -M84 ;disable steppers so they dont get hot during idling... - -;or you can use this one comment out -;G1 X10.0 F4000 ;home (almost) x -;G1 Y170 F4000 ; move the print to the front. -;M104 S0 ; make sure the extuder is turned off. -;M140 S0 ; make sure the bed is turned off. -;M84 ; shut down motors. diff --git a/skeinforge/skeinforge_application/alterations/example_end.gmc b/skeinforge/skeinforge_application/alterations/example_end.gmc deleted file mode 100644 index 86dc43b..0000000 --- a/skeinforge/skeinforge_application/alterations/example_end.gmc +++ /dev/null @@ -1,2 +0,0 @@ -(this is a sample gcode end file, it must be renamed end.gcode for skeinforge to recognize it) -M2 diff --git a/skeinforge/skeinforge_application/alterations/example_homing.gmc b/skeinforge/skeinforge_application/alterations/example_homing.gmc deleted file mode 100644 index a089a31..0000000 --- a/skeinforge/skeinforge_application/alterations/example_homing.gmc +++ /dev/null @@ -1,5 +0,0 @@ -(this is a sample gcode homing file, it must be renamed homing.gcode for skeinforge to recognize it) -G1 X-250.0 -G92 X0 ;set x 0 -G1 Y-250.0 -G92 Y0 ;set y 0 diff --git a/skeinforge/skeinforge_application/alterations/replace.csv b/skeinforge/skeinforge_application/alterations/replace.csv deleted file mode 100644 index 22f442e..0000000 --- a/skeinforge/skeinforge_application/alterations/replace.csv +++ /dev/null @@ -1,7 +0,0 @@ -M101 -M103 -M108 S*.* ; -M108 ; -G1 F0.0 -M113 S0.0 -M113 ; \ No newline at end of file diff --git a/skeinforge/skeinforge_application/alterations/start.gmc b/skeinforge/skeinforge_application/alterations/start.gmc deleted file mode 100644 index 312da53..0000000 --- a/skeinforge/skeinforge_application/alterations/start.gmc +++ /dev/null @@ -1,6 +0,0 @@ -G92 E0 ;reset extruder -G1 E3 F1200 ;Prime extruder 3mm -G1 E2 F1200 ;retract extruder 1mm -G92 E0 ;reset extruder -G1 Z1 F3000 ;Move Z 1mm up to avid head crashing into printbed -G92 E0 ;reset extruder \ No newline at end of file diff --git a/skeinforge/skeinforge_application/profiles/cutting.csv b/skeinforge/skeinforge_application/profiles/cutting.csv deleted file mode 100644 index ee1c1f3..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated cutting settings. -_Name Value -WindowPosition 0+400 -Profile Selection: End_Mill diff --git a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/bottom.csv b/skeinforge/skeinforge_application/profiles/cutting/End_Mill/bottom.csv deleted file mode 100644 index d57e404..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/bottom.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated bottom settings. -_Name Value -WindowPosition 700+0 -Open File for Bottom -Activate Bottom True -Additional Height over Layer Thickness (ratio): 0.5 -Altitude (mm): 0.0 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/carve.csv b/skeinforge/skeinforge_application/profiles/cutting/End_Mill/carve.csv deleted file mode 100644 index 151d244..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/carve.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated carve settings. -_Name Value -WindowPosition 700+0 -Open File for Carve -Add Layer Template to SVG True -Extra Decimal Places (float): 2.0 -Import Coarseness (ratio): 1.0 -Infill in Direction of Bridge True -Layer Thickness (mm): 0.33 -Layers From (index): 0 -Layers To (index): 912345678 -Correct Mesh True -Unproven Mesh False -Perimeter Width over Thickness (ratio): 1.33 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/chamber.csv b/skeinforge/skeinforge_application/profiles/cutting/End_Mill/chamber.csv deleted file mode 100644 index 5141fb7..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/chamber.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated chamber settings. -_Name Value -WindowPosition 700+0 -Open File for Chamber -Activate Chamber: False -Bed Temperature (Celcius): 60.0 -Chamber Temperature (Celcius): 30.0 -Holding Force (bar): 0.0 diff --git a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/chop (2).csv b/skeinforge/skeinforge_application/profiles/cutting/End_Mill/chop (2).csv deleted file mode 100644 index 40329eb..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/chop (2).csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated chop settings. -_Name Value -WindowPosition 600+0 -Open File to be Chopped -Add Extra Top Layer if Necessary True -Add Layer Template to SVG True -Extra Decimal Places (float): 2.0 -Import Coarseness (ratio): 1.0 -Layer Thickness (mm): 10.0 -Layers From (index): 0 -Layers To (index): 999999999 -Correct Mesh True -Unproven Mesh False -Perimeter Width (mm): 2.0 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/chop.csv b/skeinforge/skeinforge_application/profiles/cutting/End_Mill/chop.csv deleted file mode 100644 index ace928d..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/chop.csv +++ /dev/null @@ -1,13 +0,0 @@ -Format is tab separated chop preferences. -Name Value -Add Extra Top Layer if Necessary True -Open File to be Chopped -Import Coarseness (ratio): 1.0 -Correct Mesh True -Unproven Mesh False -Layer Thickness (mm): 0.4 -Layer Thickness over Precision (ratio): 10.0 -Layers From (index): 0 -Layers To (index): 999999999 -Perimeter Width (mm): 2.0 -windowPositionChop Preferences 600+0 diff --git a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/clip.csv b/skeinforge/skeinforge_application/profiles/cutting/End_Mill/clip.csv deleted file mode 100644 index 2ed35bb..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/clip.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated clip settings. -_Name Value -WindowPosition 700+0 -Open File for Clip -Activate Clip True -Clip Over Perimeter Width (ratio): 0.5 -Maximum Connection Distance Over Perimeter Width (ratio): 10.0 diff --git a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/dimension.csv b/skeinforge/skeinforge_application/profiles/cutting/End_Mill/dimension.csv deleted file mode 100644 index 1e488a2..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/dimension.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated dimension settings. -_Name Value -WindowPosition 700+0 -Open File for Dimension -Activate Dimension True -Absolute Extrusion Distance True -Relative Extrusion Distance False -Extruder Retraction Speed (mm/s): 25.0 -Filament Diameter (mm): 2.9 -Filament Packing Density (ratio): 1.05 -Minimum Travel for Retraction (millimeters): 4.0 -Retract When Crossing True -Retraction Distance (millimeters): 1.5 -Restart Extra Distance (millimeters): 0.0 diff --git a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/fill.csv b/skeinforge/skeinforge_application/profiles/cutting/End_Mill/fill.csv deleted file mode 100644 index f57aad2..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/fill.csv +++ /dev/null @@ -1,34 +0,0 @@ -Format is tab separated fill settings. -_Name Value -WindowPosition 700+0 -Open File for Fill -Activate Fill: True -Diaphragm Period (layers): 100 -Diaphragm Thickness (layers): 0 -Extra Shells on Alternating Solid Layer (layers): 2 -Extra Shells on Base (layers): 2 -Extra Shells on Sparse Layer (layers): 2 -Grid Circle Separation over Perimeter Width (ratio): 0.2 -Grid Extra Overlap (ratio): 0.1 -Grid Junction Separation Band Height (layers): 2 -Grid Junction Separation over Octogon Radius At End (ratio): 0.0 -Grid Junction Separation over Octogon Radius At Middle (ratio): 0.0 -Infill Begin Rotation (degrees): 45.0 -Infill Begin Rotation Repeat (layers): 1 -Infill Odd Layer Extra Rotation (degrees): 90.0 -Grid Circular False -Grid Hexagonal False -Grid Rectangular False -Line True -Infill Perimeter Overlap (ratio): 0.025 -Infill Solidity (ratio): 0.3 -Infill Width over Thickness (ratio): 1.33 -Solid Surface Thickness (layers): 1 -Lower Left True -Nearest False -Infill > Loops > Perimeter False -Infill > Perimeter > Loops False -Loops > Infill > Perimeter False -Loops > Perimeter > Infill False -Perimeter > Infill > Loops False -Perimeter > Loops > Infill True diff --git a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/lift.csv b/skeinforge/skeinforge_application/profiles/cutting/End_Mill/lift.csv deleted file mode 100644 index a2cf543..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/lift.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated lift preferences. -Name Value -Activate Lift: True -Cutting Lift over Layer Step (ratio): -0.5 -Open File to be Lifted /home/enrique/Desktop/backup/babbleold/script/reprap/pyRepRap/skeinforge_tools/craft_plugins/Screw Holder Bottom.stl -Clearance above Top (mm): 5.0 -windowPositionLift Preferences 440+53 diff --git a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/raft.csv b/skeinforge/skeinforge_application/profiles/cutting/End_Mill/raft.csv deleted file mode 100644 index 02517e0..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/raft.csv +++ /dev/null @@ -1,37 +0,0 @@ -Format is tab separated raft settings. -_Name Value -WindowPosition 700+0 -Open File for Raft -Activate Raft True -Add Raft, Elevate Nozzle, Orbit: True -Base Feed Rate Multiplier (ratio): 1.0 -Base Flow Rate Multiplier (ratio): 1.0 -Base Infill Density (ratio): 0.5 -Base Layer Thickness over Layer Thickness: 2.0 -Base Layers (integer): 0 -Base Nozzle Lift over Base Layer Thickness (ratio): 0.2 -Initial Circling: False -Infill Overhang over Extrusion Width (ratio): 0.05 -Interface Feed Rate Multiplier (ratio): 1.0 -Interface Flow Rate Multiplier (ratio): 1.0 -Interface Infill Density (ratio): 0.5 -Interface Layer Thickness over Layer Thickness: 1.0 -Interface Layers (integer): 0 -Interface Nozzle Lift over Interface Layer Thickness (ratio): 0.2 -Name of Support End File: support_end.gcode -Name of Support Start File: support_start.gcode -Object First Layer Feed Rate Infill Multiplier (ratio): 0.4 -Object First Layer Feed Rate Perimeter Multiplier (ratio): 0.4 -Object First Layer Flow Rate Infill Multiplier (ratio): 0.4 -Object First Layer Flow Rate Perimeter Multiplier (ratio): 0.4 -Operating Nozzle Lift over Layer Thickness (ratio): 0.7 -Raft Additional Margin over Length (%): 1.0 -Raft Margin (mm): 3.0 -Support Cross Hatch False -Support Flow Rate over Operating Flow Rate (ratio): 1.0 -Support Gap over Perimeter Extrusion Width (ratio): 1.0 -None False -Empty Layers Only False -Everywhere False -Exterior Only True -Support Minimum Angle (degrees): 60.0 diff --git a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/skeinforge.csv b/skeinforge/skeinforge_application/profiles/cutting/End_Mill/skeinforge.csv deleted file mode 100644 index e779a84..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/skeinforge.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated skeinforge settings. -_Name Value -WindowPosition 889+32 -Open File for Skeinforge C:/Users/Ahmet/STL/10in (fixed).stl -analyze False -craft False -help False -meta False -profile True diff --git a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/skeinforge_craft.csv b/skeinforge/skeinforge_application/profiles/cutting/End_Mill/skeinforge_craft.csv deleted file mode 100644 index ddb6f67..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/skeinforge_craft.csv +++ /dev/null @@ -1,45 +0,0 @@ -Format is tab separated skeinforge craft settings. -_Name Value -WindowPosition 600+0 -Open File for Craft -bottom False -carve False -chamber False -chop True -cleave False -clip False -coil False -comb False -cool False -dimension False -drill False -export False -feed False -fill False -fillet False -flow False -home False -hop False -inset False -jitter False -lash False -lift False -limit False -mill False -multiply False -oozebane False -outset False -preface False -raft False -scale False -skin False -skirt False -speed False -splodge False -stretch False -temperature False -tower False -unpause False -whittle False -widen False -wipe False diff --git a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/skin.csv b/skeinforge/skeinforge_application/profiles/cutting/End_Mill/skin.csv deleted file mode 100644 index b06cce0..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/skin.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated skin settings. -_Name Value -WindowPosition 700+0 -Open File for Skin -Activate Skin True -Clip Over Perimeter Width (ratio): 0.5 -Layers From (index): 1 diff --git a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/skirt.csv b/skeinforge/skeinforge_application/profiles/cutting/End_Mill/skirt.csv deleted file mode 100644 index 80cd328..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/skirt.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skirt settings. -_Name Value -WindowPosition 700+0 -Open File for Skirt -Activate Skirt: True -Convex: True -Gap over Perimeter Width (ratio): 5.0 -Layers To (index): 3 diff --git a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/speed.csv b/skeinforge/skeinforge_application/profiles/cutting/End_Mill/speed.csv deleted file mode 100644 index 160e538..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/End_Mill/speed.csv +++ /dev/null @@ -1,16 +0,0 @@ -Format is tab separated speed settings. -_Name Value -WindowPosition 700+0 -Open File for Speed -Activate Speed: True -Add Flow Rate: True -Bridge Feed Rate Multiplier (ratio): 1.0 -Bridge Flow Rate Multiplier (ratio): 0.9 -Duty Cyle at Beginning (portion): 1.0 -Duty Cyle at Ending (portion): 0.0 -Feed Rate (mm/s): 100.0 -Flow Rate Setting (float): 100.0 -Orbital Feed Rate over Operating Feed Rate (ratio): 0.5 -Perimeter Feed Rate over Operating Feed Rate (ratio): 0.64 -Perimeter Flow Rate over Operating Flow Rate (ratio): 0.64 -Travel Feed Rate (mm/s): 196.0 diff --git a/skeinforge/skeinforge_application/profiles/cutting/Laser/chop.csv b/skeinforge/skeinforge_application/profiles/cutting/Laser/chop.csv deleted file mode 100644 index b54d561..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/Laser/chop.csv +++ /dev/null @@ -1,13 +0,0 @@ -Format is tab separated chop preferences. -Name Value -Add Extra Top Layer if Necessary True -Open File to be Chopped -Import Coarseness (ratio): 1.0 -Correct Mesh True -Unproven Mesh False -Layer Thickness (mm): 0.4 -Layer Thickness over Precision (ratio): 10.0 -Layers From (index): 0 -Layers To (index): 999999999 -Perimeter Width (mm): 0.2 -windowPositionChop Preferences 600+0 diff --git a/skeinforge/skeinforge_application/profiles/cutting/Laser/lift.csv b/skeinforge/skeinforge_application/profiles/cutting/Laser/lift.csv deleted file mode 100644 index 9818ca2..0000000 --- a/skeinforge/skeinforge_application/profiles/cutting/Laser/lift.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated lift preferences. -Name Value -Activate Lift: True -Cutting Lift over Layer Step (ratio): 0.0 -Open File to be Lifted /home/enrique/Desktop/backup/babbleold/script/reprap/pyRepRap/skeinforge_tools/craft_plugins/Screw Holder Bottom.stl -Clearance above Top (mm): 5.0 -windowPositionLift Preferences 440+53 diff --git a/skeinforge/skeinforge_application/profiles/extrusion.csv b/skeinforge/skeinforge_application/profiles/extrusion.csv deleted file mode 100644 index da183d5..0000000 --- a/skeinforge/skeinforge_application/profiles/extrusion.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated extrusion settings. -_Name Value -WindowPosition 0+400 -Profile Selection: PLA 0.33 1.5 diff --git a/skeinforge/skeinforge_application/profiles/milling.csv b/skeinforge/skeinforge_application/profiles/milling.csv deleted file mode 100644 index 1068866..0000000 --- a/skeinforge/skeinforge_application/profiles/milling.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated milling settings. -_Name Value -WindowPosition 0+400 -Profile Selection: end_mill diff --git a/skeinforge/skeinforge_application/profiles/milling/End_Mill/chop.csv b/skeinforge/skeinforge_application/profiles/milling/End_Mill/chop.csv deleted file mode 100644 index ace928d..0000000 --- a/skeinforge/skeinforge_application/profiles/milling/End_Mill/chop.csv +++ /dev/null @@ -1,13 +0,0 @@ -Format is tab separated chop preferences. -Name Value -Add Extra Top Layer if Necessary True -Open File to be Chopped -Import Coarseness (ratio): 1.0 -Correct Mesh True -Unproven Mesh False -Layer Thickness (mm): 0.4 -Layer Thickness over Precision (ratio): 10.0 -Layers From (index): 0 -Layers To (index): 999999999 -Perimeter Width (mm): 2.0 -windowPositionChop Preferences 600+0 diff --git a/skeinforge/skeinforge_application/profiles/milling/End_Mill/lift.csv b/skeinforge/skeinforge_application/profiles/milling/End_Mill/lift.csv deleted file mode 100644 index a2cf543..0000000 --- a/skeinforge/skeinforge_application/profiles/milling/End_Mill/lift.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated lift preferences. -Name Value -Activate Lift: True -Cutting Lift over Layer Step (ratio): -0.5 -Open File to be Lifted /home/enrique/Desktop/backup/babbleold/script/reprap/pyRepRap/skeinforge_tools/craft_plugins/Screw Holder Bottom.stl -Clearance above Top (mm): 5.0 -windowPositionLift Preferences 440+53 diff --git a/skeinforge/skeinforge_application/profiles/milling/Laser/chop.csv b/skeinforge/skeinforge_application/profiles/milling/Laser/chop.csv deleted file mode 100644 index b54d561..0000000 --- a/skeinforge/skeinforge_application/profiles/milling/Laser/chop.csv +++ /dev/null @@ -1,13 +0,0 @@ -Format is tab separated chop preferences. -Name Value -Add Extra Top Layer if Necessary True -Open File to be Chopped -Import Coarseness (ratio): 1.0 -Correct Mesh True -Unproven Mesh False -Layer Thickness (mm): 0.4 -Layer Thickness over Precision (ratio): 10.0 -Layers From (index): 0 -Layers To (index): 999999999 -Perimeter Width (mm): 0.2 -windowPositionChop Preferences 600+0 diff --git a/skeinforge/skeinforge_application/profiles/milling/Laser/lift.csv b/skeinforge/skeinforge_application/profiles/milling/Laser/lift.csv deleted file mode 100644 index 9818ca2..0000000 --- a/skeinforge/skeinforge_application/profiles/milling/Laser/lift.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated lift preferences. -Name Value -Activate Lift: True -Cutting Lift over Layer Step (ratio): 0.0 -Open File to be Lifted /home/enrique/Desktop/backup/babbleold/script/reprap/pyRepRap/skeinforge_tools/craft_plugins/Screw Holder Bottom.stl -Clearance above Top (mm): 5.0 -windowPositionLift Preferences 440+53 diff --git a/skeinforge/skeinforge_application/profiles/skeinforge_profile.csv b/skeinforge/skeinforge_application/profiles/skeinforge_profile.csv deleted file mode 100644 index 48bb0a0..0000000 --- a/skeinforge/skeinforge_application/profiles/skeinforge_profile.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated skeinforge profile settings. -_Name Value -WindowPosition 0+200 -cutting False -extrusion True -milling False -winding False diff --git a/skeinforge/skeinforge_application/profiles/winding.csv b/skeinforge/skeinforge_application/profiles/winding.csv deleted file mode 100644 index a20384b..0000000 --- a/skeinforge/skeinforge_application/profiles/winding.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated winding settings. -_Name Value -WindowPosition 0+400 -Profile Selection: free_wire diff --git a/skeinforge/skeinforge_application/runskeinforge.sh b/skeinforge/skeinforge_application/runskeinforge.sh deleted file mode 100644 index 6c165a1..0000000 --- a/skeinforge/skeinforge_application/runskeinforge.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh - -# -# Utility script for keeping track of which preference settings a file was processed -# with, by copying the current preferences to a date-tagged directory together -# with the output files. -# -# Usage: runskeinforge.sh -# - -dir=`dirname $1` -file=`basename $1` - -for s in .gts .GTS .stl .STL; do - if [ ! `basename $file $s` = $file ]; then suffix=$s; fi -done - -if [ -n $suffix ]; then - filename=`basename $file $suffix` - newdir=$filename-`date +%m%d%H%M` - mkdir -p $newdir/skeinforge-prefs - cp $1 $newdir - cp ~/.skeinforge/*.csv $newdir/skeinforge-prefs - python skeinforge.py $newdir/$filename$suffix - echo $PWD/$newdir/${filename}_export.gcode -fi diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/cutting.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/cutting.csv deleted file mode 100644 index 3ffa660..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/cutting.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated cutting settings. -_Name Value -WindowPosition 0+400 -Profile Selection: end_mill diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion.csv deleted file mode 100644 index 7d14791..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated extrusion settings. -_Name Value -WindowPosition 0+400 -Profile Selection: PLA diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/bottom.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/bottom.csv deleted file mode 100644 index 0a24bd9..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/bottom.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated bottom settings. -_Name Value -WindowPosition 700+0 -Open File for Bottom -Activate Bottom... and dont change anything else here!!! True -Additional Height (ratio): 0.5 -Altitude (mm): 0.0 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/carve.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/carve.csv deleted file mode 100644 index 03cd070..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/carve.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated carve settings. -_Name Value -WindowPosition 700+0 -Open File for Carve -Layer Height = Extrusion Thickness (mm): 0.33 -Extrusion Width (mm): 0.5 -Print from Layer No:: 0 -Print up to Layer No: 912345678 -Infill in Direction of Bridge True -Correct Mesh True -Unproven Mesh False -SVG Viewer: webbrowser -Add Layer Template to SVG True -Extra Decimal Places (float): 2.0 -Import Coarseness (ratio): 1.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/chamber.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/chamber.csv deleted file mode 100644 index 08ccd9c..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/chamber.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated chamber settings. -_Name Value -WindowPosition 700+0 -Open File for Chamber -Activate Chamber..if you want below functions to work True -Heated PrintBed Temperature (Celcius): 60.0 -Turn print Bed Heater Off at Shut Down True -Turn Extruder Heater Off at Shut Down True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/clairvoyance.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/clairvoyance.csv deleted file mode 100644 index 8aadf4f..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/clairvoyance.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated clairvoyance settings. -_Name Value -WindowPosition 700+0 -Activate Clairvoyance False -Open File to Generate Clairvoyances for -Gcode Program: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/clip.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/clip.csv deleted file mode 100644 index c61adb8..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/clip.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated clip settings. -_Name Value -WindowPosition 700+0 -Open File for Clip -Activate Clip..to clip the extrusion that overlaps when printing perimeters True -Clip Over Perimeter Width adjuster (decrease for bigger gap): 1.0 -Threshold for connecting inner loops (ratio): 2.5 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/comb.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/comb.csv deleted file mode 100644 index 403d19b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/comb.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated comb settings. -_Name Value -WindowPosition 700+0 -Open File for Comb -Activate Comb if you cant stop the extruder stringing by retraction -it will avoid moving over loops so the strings will be there -but not visible anymore. -Comb bends the extruder travel paths around holes in the slices, to avoid stringing. -so any start up ooze will be inside the shape. True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/comment.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/comment.csv deleted file mode 100644 index c140205..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/comment.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated comment settings. -_Name Value -WindowPosition 700+0 -Activate Comment False -Open File to Write Comments for diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/cool.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/cool.csv deleted file mode 100644 index ed931a0..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/cool.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated cool settings. -_Name Value -WindowPosition 700+0 -Open File for Cool -Activate Cool.. but use with a fan! False -Use Cool if layer takes shorter than(seconds): 10.0 -Turn Fan On at Beginning True -Turn Fan Off at Ending True -Execute when Cool starts: cool_start.gmc -Execute when Cool ends: cool_end.gmc -Orbiting around Object False -Slow Down during print True -Maximum Cool (Celcius): 2.0 -Bridge Cool (Celcius): 1.0 -Minimum Orbital Radius (millimeters): 10.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/dimension.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/dimension.csv deleted file mode 100644 index e2272b6..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/dimension.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated dimension settings. -_Name Value -WindowPosition 700+0 -Open File for Dimension -Activate Volumetric Extrusion (Stepper driven Extruders) True -Filament Diameter (mm): 1.75 -Filament Packing Density (ratio) lower=more extrusion: 1.0 -Retraction Distance (millimeters): 1.0 -Restart Extra Distance (millimeters): 0.0 -Extruder Retraction Speed (mm/s): 15.0 -Force to retract when crossing over spaces True -Minimum Extrusion before Retraction (millimeters): 1.0 -Minimum Travelmove after Retraction (millimeters): 1.0 -in Absolute units (Sprinter, FiveD a.o.) True -in Relative units (Teacup a.o.) False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/export.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/export.csv deleted file mode 100644 index be5764b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/export.csv +++ /dev/null @@ -1,20 +0,0 @@ -Format is tab separated export settings. -_Name Value -WindowPosition 700+0 -Open File for Export -Activate Export True -Add _export to filename (filename_export) True -Also Send Output To: -Do Not Delete Comments False -Delete Crafting Comments False -Delete All Comments True -Do Not Change Output False -gcode_small True -File Extension (gcode): gcode -Name of Replace File: replace.csv -Save Penultimate Gcode False -Archive Used Profile As Zip False -Export Profile Values As CSV File False -Add Profile Name to Filename False -Add Description to Filename False -Add Timestamp to Filename False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/fill.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/fill.csv deleted file mode 100644 index 682b1eb..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/fill.csv +++ /dev/null @@ -1,34 +0,0 @@ -Format is tab separated fill settings. -_Name Value -WindowPosition 700+0 -Open File for Fill -Activate Fill: True -Infill Solidity (ratio): 0.35 -Extrusion Lines extra Spacing (Scaler): 1.0 -Infill Overlap over Perimeter (Scaler): 1.0 -Extra Shells on Alternating Solid Layer (layers): 1 -Extra Shells on Base (layers): 1 -Extra Shells on Sparse Layer (layers): 1 -Fully filled Layers (each top and bottom): 2 -Lower Left True -Nearest False -Infill > Loops > Perimeter False -Infill > Perimeter > Loops False -Loops > Infill > Perimeter False -Loops > Perimeter > Infill False -Perimeter > Infill > Loops False -Perimeter > Loops > Infill True -Line True -Grid Circular False -Grid Hexagonal False -Grid Rectangular False -Diaphragm at every ...th Layer: 100 -Diaphragm Thickness (layers): 0 -Grid Circle Separation over Perimeter Width (ratio): 0.2 -Grid Extra Overlap (ratio): 0.1 -Grid Junction Separation Band Height (layers): 10 -Grid Junction Separation over Octogon Radius At End (ratio): 0.0 -Grid Junction Separation over Octogon Radius At Middle (ratio): 0.0 -Infill Begin Rotation (degrees): 45.0 -Infill Begin Rotation Repeat (layers): 1 -Infill Odd Layer Extra Rotation (degrees): 90.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/home.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/home.csv deleted file mode 100644 index 430a33a..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/home.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated home settings. -_Name Value -WindowPosition 700+0 -Open File for Home -Activate Home ... Not needed True -Name of Homing File: homing.gcode diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/inset.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/inset.csv deleted file mode 100644 index 6c3d57c..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/inset.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated inset settings. -_Name Value -WindowPosition 700+0 -Open File for Inset -Bridge Width Multiplier (ratio): 1.0 -Prefer Loops False -Prefer Perimeter True -Overlap Removal(Scaler): 1.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/interpret.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/interpret.csv deleted file mode 100644 index 76cdc59..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/interpret.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated interpret settings. -_Name Value -WindowPosition 700+0 -Open File for Interpret -Activate Interpret False -Print Interpretion False -Text Program: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/jitter.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/jitter.csv deleted file mode 100644 index 781738d..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/jitter.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated jitter settings. -_Name Value -WindowPosition 700+0 -Open File for Jitter -Activate Jitter to have your perimeter and loop endpoints scattered False -Jitter Over Perimeter Width (ratio): 2.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/lash.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/lash.csv deleted file mode 100644 index 32ccb3b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/lash.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated lash settings. -_Name Value -WindowPosition 700+0 -Open File for Lash -Activate Lash if you have backlash in your axes. -But its better to fix the mechanical problem! False -X Backlash (mm): 0.0 -Y Backlash (mm): 0.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/limit.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/limit.csv deleted file mode 100644 index 9671405..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/limit.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated limit settings. -_Name Value -WindowPosition 700+0 -Open File for Limit -Activate Limit if your Firmware is unable to Limiting your Z-Speed. False -Maximum Initial Feed Rate (mm/s): 5.0 -Maximum Z Feed Rate (mm/s): 5.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/multiply.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/multiply.csv deleted file mode 100644 index 269d53f..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/multiply.csv +++ /dev/null @@ -1,10 +0,0 @@ -Format is tab separated multiply settings. -_Name Value -WindowPosition 700+0 -Open File for Multiply -Activate Multiply: True -Center X (mm): 100.0 -Center Y (mm): 100.0 -Number of Columns (integer): 1 -Number of Rows (integer): 1 -Separation over Perimeter Width (ratio): 15.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/polyfile.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/polyfile.csv deleted file mode 100644 index 6e7d9bb..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/polyfile.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated polyfile settings. -_Name Value -WindowPosition 700+0 -Execute All Unmodified Files in a Directory False -Execute File True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/preface.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/preface.csv deleted file mode 100644 index 937a406..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/preface.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated preface settings. -Home before Print False -_Name Value -WindowPosition 700+0 -Open File for Preface -Reset Extruder before Print True -Meta: -Name of End File: end.gmc -Name of Start File: start.gmc -Set Positioning to Absolute True -Set Units to Millimeters True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/raft.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/raft.csv deleted file mode 100644 index 8d4b00a..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/raft.csv +++ /dev/null @@ -1,38 +0,0 @@ -Format is tab separated raft settings. -_Name Value -WindowPosition 700+0 -Open File for Raft -Activate Raft True -Add Raft, Elevate Nozzle, Orbit: True -None True -Empty Layers Only False -Everywhere False -Exterior Only False -Add support if flatter than (degrees): 50.0 -Cross Hatch instead of Lines False -Interface/Support Lines Density (ratio): 0.25 -Interface/Support Layer Thickness over Layer Thickness: 1.0 -Support Feed Rate mm/sec: 15.0 -Support Flow Rate (scaler): 1.0 -Support Gap over Perimeter Extrusion Width (ratio): 1.0 -Raft/Support extension in (%): 5.0 -Raft/Support extension in(mm): 2.0 -Name of Support End File: support_end.gmc -Name of Support Start File: support_start.gmc -Extra Nozzle clearance over Object(ratio): 0.0 -First Layer Main Feedrate (mm/s): 35.0 -First Layer Perimeter Feedrate (mm/s): 25.0 -First Layer Flow Rate Infill(scaler): 1.0 -First Layer Flow Rate Perimeter(scaler): 1.0 -Interface Layers (integer): 0 -Interface Feed Rate Multiplier (ratio): 1.0 -Interface Flow Rate Multiplier (ratio): 1.0 -Interface Nozzle Lift over Interface Layer Thickness (ratio): 0.45 -Base Layers (integer): 0 -Base Feed Rate Multiplier (ratio): 0.5 -Base Flow Rate Multiplier (ratio): 0.5 -Base Infill Density (ratio): 0.5 -Base Layer Thickness over Layer Thickness: 2.0 -Base Nozzle Lift over Base Layer Thickness (ratio): 0.4 -Initial Circling: False -Infill Overhang over Extrusion Width (ratio): 3.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/scale.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/scale.csv deleted file mode 100644 index a479f8b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/scale.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated scale settings. -_Name Value -WindowPosition 700+0 -Open File for Scale -Activate Scale to finetune print size (try to find the fault somewhere else..): False -XY Plane Scale (ratio): 1.0 -Z Axis Scale (ratio): 1.0 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge.csv deleted file mode 100644 index 22338a4..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated skeinforge settings. -_Name Value -WindowPosition 1187+2 -Open File for Skeinforge C:/Users/Ahmet/STL/_Screw Holder Bottom.stl -analyze False -craft True -help False -meta False -profile False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_analyze.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_analyze.csv deleted file mode 100644 index 8826bcb..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_analyze.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated skeinforge analyze settings. -_Name Value -WindowPosition 600+0 -Open File for Analyze -clairvoyance False -comment False -interpret False -skeiniso True -skeinlayer False -statistic False -vectorwrite False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_craft.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_craft.csv deleted file mode 100644 index 0943077..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_craft.csv +++ /dev/null @@ -1,27 +0,0 @@ -Format is tab separated skeinforge craft settings. -_Name Value -WindowPosition 600+0 -Open File for Craft -bottom False -carve False -chamber False -clip False -comb False -cool False -dimension True -export False -fill False -inset False -jitter False -lash False -limit False -multiply False -preface False -raft False -scale False -skin False -skirt False -speed False -stretch False -temperature False -wipe False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_help.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_help.csv deleted file mode 100644 index 6447399..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinforge_help.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated skeinforge help settings. -_Name Value -WindowPosition 600+0 -Wiki Manual Primary True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeiniso.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeiniso.csv deleted file mode 100644 index a0bf075..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeiniso.csv +++ /dev/null @@ -1,41 +0,0 @@ -Format is tab separated skeiniso settings. -_Name Value -WindowPosition 700+0 -Open File for Skeiniso -Activate Skeiniso True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Axis Rulings True -Band Height (layers): 5 -Bottom Band Brightness (ratio): 0.7 -Bottom Layer Brightness (ratio): 1.0 -From the Bottom False -From the Top True -Draw Arrows False -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 912345678 -Line (index): 24 -Display Line True -View Move False -View Rotate False -Number of Fill Bottom Layers (integer): 1 -Number of Fill Top Layers (integer): 1 -Scale (pixels per millimeter): 15.0 -Screen Horizontal Inset (pixels): 100 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Viewpoint Latitude (degrees): 15.0 -Viewpoint Longitude (degrees): 210.0 -Width of Axis Negative Side (pixels): 2 -Width of Axis Positive Side (pixels): 6 -Width of Fill Bottom Thread (pixels): 2 -Width of Fill Top Thread (pixels): 2 -Width of Infill Thread (pixels): 1 -Width of Loop Thread (pixels): 2 -Width of Perimeter Inside Thread (pixels): 8 -Width of Perimeter Outside Thread (pixels): 8 -Width of Raft Thread (pixels): 1 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinlayer.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinlayer.csv deleted file mode 100644 index 5273776..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skeinlayer.csv +++ /dev/null @@ -1,23 +0,0 @@ -Format is tab separated skeinlayer settings. -_Name Value -WindowPosition 700+0 -Open File for Skeinlayer -Activate Skeinlayer True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Draw Arrows True -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 0 -Line (index): 430 -Display Line True -View Move False -Scale (pixels per millimeter): 25.0 -Screen Horizontal Inset (pixels): 100 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Show Position True -Width of Extrusion Thread (pixels): 3 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 1 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skin.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skin.csv deleted file mode 100644 index 9154030..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skin.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skin settings. -_Name Value -WindowPosition 700+0 -Open File for Skin -Activate Skin: this is experimental. -It prints the perimeters and loops only at half the layer height that is specified under carve. False -Clip Over Perimeter Width (scaler): 1.0 -Do Not Skin the first ... Layers: 3 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skirt.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skirt.csv deleted file mode 100644 index 80cd328..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/skirt.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skirt settings. -_Name Value -WindowPosition 700+0 -Open File for Skirt -Activate Skirt: True -Convex: True -Gap over Perimeter Width (ratio): 5.0 -Layers To (index): 3 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/speed.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/speed.csv deleted file mode 100644 index e2685f3..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/speed.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated speed settings. -_Name Value -WindowPosition 700+0 -Open File for Speed -Activate Speed: True -Add Flow Rate: True -Main Feed Rate (mm/s): 60.0 -Main Flow Rate (scaler): 1.0 -Feed Rate ratio for Orbiting move (ratio): 0.5 -Perimeter Feed Rate (mm/s): 30.0 -Perimeter Flow Rate (scaler): 1.0 -Bridge Feed Rate (ratio): 1.0 -Bridge Flow Rate (scaler): 1.0 -Travel Feed Rate (mm/s): 130.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/statistic.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/statistic.csv deleted file mode 100644 index 4a1f127..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/statistic.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated statistic settings. -_Name Value -WindowPosition 700+0 -Activate Statistic True -Machine Time ($/hour): 1.0 -Material ($/kg): 20.0 -Density (kg/m3): 930.0 -Extrusion Diameter over Thickness (ratio): 1.25 -Open File to Generate Statistics for -Print Statistics True -Save Statistics False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/stretch.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/stretch.csv deleted file mode 100644 index 5bc618d..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/stretch.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated stretch settings. -_Name Value -WindowPosition 700+0 -Open File for Stretch -Activate Stretch to correct for diameter shrink in small diameter holes False -Cross Limit Distance Over Perimeter Width (ratio): 5.0 -Loop Stretch Over Perimeter Width (ratio): 0.11 -Path Stretch Over Perimeter Width (ratio): 0.0 -Perimeter Inside Stretch Over Perimeter Width (ratio): 0.32 -Perimeter Outside Stretch Over Perimeter Width (ratio): 0.1 -Stretch From Distance Over Perimeter Width (ratio): 2.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/temperature.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/temperature.csv deleted file mode 100644 index ce2ef6e..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/temperature.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated temperature settings. -_Name Value -WindowPosition 700+0 -Open File for Temperature -Activate Temperature: False -Cooling Rate (Celcius/second): 3.0 -Heating Rate (Celcius/second): 3.0 -Base Temperature (Celcius): 210.0 -Interface Temperature (Celcius): 210.0 -Object First Layer Infill Temperature (Celcius): 210.0 -Object First Layer Perimeter Temperature (Celcius): 210.0 -Object Next Layers Temperature (Celcius): 210.0 -Support Layers Temperature (Celcius): 210.0 -Supported Layers Temperature (Celcius): 210.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/vectorwrite.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/vectorwrite.csv deleted file mode 100644 index e03372b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/vectorwrite.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated vectorwrite settings. -_Name Value -WindowPosition 700+0 -Activate Vectorwrite False -Open File to Write Vector Graphics for -Add Loops True -Add Paths True -Add Perimeters True -Layers From (index): 0 -Layers To (index): 912345678 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/wipe.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/wipe.csv deleted file mode 100644 index 855c684..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.3 nozzle/wipe.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated wipe settings. -_Name Value -WindowPosition 700+0 -Open File for Wipe -Activate Wipe False -Location Arrival X (mm): 0.0 -Location Arrival Y (mm): 5.0 -Location Arrival Z (mm): 0.0 -Location Departure X (mm): 5.0 -Location Departure Y (mm): 0.0 -Location Departure Z (mm): 0.0 -Location Wipe X (mm): 0.0 -Location Wipe Y (mm): 0.0 -Location Wipe Z (mm): 0.0 -Wipe Period (layers): 15 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/bottom.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/bottom.csv deleted file mode 100644 index 0a24bd9..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/bottom.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated bottom settings. -_Name Value -WindowPosition 700+0 -Open File for Bottom -Activate Bottom... and dont change anything else here!!! True -Additional Height (ratio): 0.5 -Altitude (mm): 0.0 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/carve.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/carve.csv deleted file mode 100644 index 3a65503..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/carve.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated carve settings. -_Name Value -WindowPosition 700+0 -Open File for Carve -Layer Height = Extrusion Thickness (mm): 0.4 -Extrusion Width (mm): 0.6 -Print from Layer No:: 0 -Print up to Layer No: 912345678 -Infill in Direction of Bridge True -Correct Mesh True -Unproven Mesh False -SVG Viewer: webbrowser -Add Layer Template to SVG True -Extra Decimal Places (float): 2.0 -Import Coarseness (ratio): 1.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/chamber.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/chamber.csv deleted file mode 100644 index 08ccd9c..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/chamber.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated chamber settings. -_Name Value -WindowPosition 700+0 -Open File for Chamber -Activate Chamber..if you want below functions to work True -Heated PrintBed Temperature (Celcius): 60.0 -Turn print Bed Heater Off at Shut Down True -Turn Extruder Heater Off at Shut Down True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/clairvoyance.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/clairvoyance.csv deleted file mode 100644 index 8aadf4f..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/clairvoyance.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated clairvoyance settings. -_Name Value -WindowPosition 700+0 -Activate Clairvoyance False -Open File to Generate Clairvoyances for -Gcode Program: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/clip.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/clip.csv deleted file mode 100644 index c61adb8..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/clip.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated clip settings. -_Name Value -WindowPosition 700+0 -Open File for Clip -Activate Clip..to clip the extrusion that overlaps when printing perimeters True -Clip Over Perimeter Width adjuster (decrease for bigger gap): 1.0 -Threshold for connecting inner loops (ratio): 2.5 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/comb.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/comb.csv deleted file mode 100644 index 403d19b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/comb.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated comb settings. -_Name Value -WindowPosition 700+0 -Open File for Comb -Activate Comb if you cant stop the extruder stringing by retraction -it will avoid moving over loops so the strings will be there -but not visible anymore. -Comb bends the extruder travel paths around holes in the slices, to avoid stringing. -so any start up ooze will be inside the shape. True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/comment.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/comment.csv deleted file mode 100644 index c140205..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/comment.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated comment settings. -_Name Value -WindowPosition 700+0 -Activate Comment False -Open File to Write Comments for diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/cool.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/cool.csv deleted file mode 100644 index ed931a0..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/cool.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated cool settings. -_Name Value -WindowPosition 700+0 -Open File for Cool -Activate Cool.. but use with a fan! False -Use Cool if layer takes shorter than(seconds): 10.0 -Turn Fan On at Beginning True -Turn Fan Off at Ending True -Execute when Cool starts: cool_start.gmc -Execute when Cool ends: cool_end.gmc -Orbiting around Object False -Slow Down during print True -Maximum Cool (Celcius): 2.0 -Bridge Cool (Celcius): 1.0 -Minimum Orbital Radius (millimeters): 10.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/dimension.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/dimension.csv deleted file mode 100644 index e2272b6..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/dimension.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated dimension settings. -_Name Value -WindowPosition 700+0 -Open File for Dimension -Activate Volumetric Extrusion (Stepper driven Extruders) True -Filament Diameter (mm): 1.75 -Filament Packing Density (ratio) lower=more extrusion: 1.0 -Retraction Distance (millimeters): 1.0 -Restart Extra Distance (millimeters): 0.0 -Extruder Retraction Speed (mm/s): 15.0 -Force to retract when crossing over spaces True -Minimum Extrusion before Retraction (millimeters): 1.0 -Minimum Travelmove after Retraction (millimeters): 1.0 -in Absolute units (Sprinter, FiveD a.o.) True -in Relative units (Teacup a.o.) False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/export.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/export.csv deleted file mode 100644 index be5764b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/export.csv +++ /dev/null @@ -1,20 +0,0 @@ -Format is tab separated export settings. -_Name Value -WindowPosition 700+0 -Open File for Export -Activate Export True -Add _export to filename (filename_export) True -Also Send Output To: -Do Not Delete Comments False -Delete Crafting Comments False -Delete All Comments True -Do Not Change Output False -gcode_small True -File Extension (gcode): gcode -Name of Replace File: replace.csv -Save Penultimate Gcode False -Archive Used Profile As Zip False -Export Profile Values As CSV File False -Add Profile Name to Filename False -Add Description to Filename False -Add Timestamp to Filename False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/fill.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/fill.csv deleted file mode 100644 index 682b1eb..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/fill.csv +++ /dev/null @@ -1,34 +0,0 @@ -Format is tab separated fill settings. -_Name Value -WindowPosition 700+0 -Open File for Fill -Activate Fill: True -Infill Solidity (ratio): 0.35 -Extrusion Lines extra Spacing (Scaler): 1.0 -Infill Overlap over Perimeter (Scaler): 1.0 -Extra Shells on Alternating Solid Layer (layers): 1 -Extra Shells on Base (layers): 1 -Extra Shells on Sparse Layer (layers): 1 -Fully filled Layers (each top and bottom): 2 -Lower Left True -Nearest False -Infill > Loops > Perimeter False -Infill > Perimeter > Loops False -Loops > Infill > Perimeter False -Loops > Perimeter > Infill False -Perimeter > Infill > Loops False -Perimeter > Loops > Infill True -Line True -Grid Circular False -Grid Hexagonal False -Grid Rectangular False -Diaphragm at every ...th Layer: 100 -Diaphragm Thickness (layers): 0 -Grid Circle Separation over Perimeter Width (ratio): 0.2 -Grid Extra Overlap (ratio): 0.1 -Grid Junction Separation Band Height (layers): 10 -Grid Junction Separation over Octogon Radius At End (ratio): 0.0 -Grid Junction Separation over Octogon Radius At Middle (ratio): 0.0 -Infill Begin Rotation (degrees): 45.0 -Infill Begin Rotation Repeat (layers): 1 -Infill Odd Layer Extra Rotation (degrees): 90.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/home.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/home.csv deleted file mode 100644 index 430a33a..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/home.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated home settings. -_Name Value -WindowPosition 700+0 -Open File for Home -Activate Home ... Not needed True -Name of Homing File: homing.gcode diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/inset.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/inset.csv deleted file mode 100644 index 6c3d57c..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/inset.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated inset settings. -_Name Value -WindowPosition 700+0 -Open File for Inset -Bridge Width Multiplier (ratio): 1.0 -Prefer Loops False -Prefer Perimeter True -Overlap Removal(Scaler): 1.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/interpret.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/interpret.csv deleted file mode 100644 index 76cdc59..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/interpret.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated interpret settings. -_Name Value -WindowPosition 700+0 -Open File for Interpret -Activate Interpret False -Print Interpretion False -Text Program: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/jitter.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/jitter.csv deleted file mode 100644 index 781738d..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/jitter.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated jitter settings. -_Name Value -WindowPosition 700+0 -Open File for Jitter -Activate Jitter to have your perimeter and loop endpoints scattered False -Jitter Over Perimeter Width (ratio): 2.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/lash.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/lash.csv deleted file mode 100644 index 32ccb3b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/lash.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated lash settings. -_Name Value -WindowPosition 700+0 -Open File for Lash -Activate Lash if you have backlash in your axes. -But its better to fix the mechanical problem! False -X Backlash (mm): 0.0 -Y Backlash (mm): 0.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/limit.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/limit.csv deleted file mode 100644 index 9671405..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/limit.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated limit settings. -_Name Value -WindowPosition 700+0 -Open File for Limit -Activate Limit if your Firmware is unable to Limiting your Z-Speed. False -Maximum Initial Feed Rate (mm/s): 5.0 -Maximum Z Feed Rate (mm/s): 5.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/multiply.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/multiply.csv deleted file mode 100644 index 269d53f..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/multiply.csv +++ /dev/null @@ -1,10 +0,0 @@ -Format is tab separated multiply settings. -_Name Value -WindowPosition 700+0 -Open File for Multiply -Activate Multiply: True -Center X (mm): 100.0 -Center Y (mm): 100.0 -Number of Columns (integer): 1 -Number of Rows (integer): 1 -Separation over Perimeter Width (ratio): 15.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/polyfile.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/polyfile.csv deleted file mode 100644 index 6e7d9bb..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/polyfile.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated polyfile settings. -_Name Value -WindowPosition 700+0 -Execute All Unmodified Files in a Directory False -Execute File True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/preface.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/preface.csv deleted file mode 100644 index 937a406..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/preface.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated preface settings. -Home before Print False -_Name Value -WindowPosition 700+0 -Open File for Preface -Reset Extruder before Print True -Meta: -Name of End File: end.gmc -Name of Start File: start.gmc -Set Positioning to Absolute True -Set Units to Millimeters True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/raft.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/raft.csv deleted file mode 100644 index 8d4b00a..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/raft.csv +++ /dev/null @@ -1,38 +0,0 @@ -Format is tab separated raft settings. -_Name Value -WindowPosition 700+0 -Open File for Raft -Activate Raft True -Add Raft, Elevate Nozzle, Orbit: True -None True -Empty Layers Only False -Everywhere False -Exterior Only False -Add support if flatter than (degrees): 50.0 -Cross Hatch instead of Lines False -Interface/Support Lines Density (ratio): 0.25 -Interface/Support Layer Thickness over Layer Thickness: 1.0 -Support Feed Rate mm/sec: 15.0 -Support Flow Rate (scaler): 1.0 -Support Gap over Perimeter Extrusion Width (ratio): 1.0 -Raft/Support extension in (%): 5.0 -Raft/Support extension in(mm): 2.0 -Name of Support End File: support_end.gmc -Name of Support Start File: support_start.gmc -Extra Nozzle clearance over Object(ratio): 0.0 -First Layer Main Feedrate (mm/s): 35.0 -First Layer Perimeter Feedrate (mm/s): 25.0 -First Layer Flow Rate Infill(scaler): 1.0 -First Layer Flow Rate Perimeter(scaler): 1.0 -Interface Layers (integer): 0 -Interface Feed Rate Multiplier (ratio): 1.0 -Interface Flow Rate Multiplier (ratio): 1.0 -Interface Nozzle Lift over Interface Layer Thickness (ratio): 0.45 -Base Layers (integer): 0 -Base Feed Rate Multiplier (ratio): 0.5 -Base Flow Rate Multiplier (ratio): 0.5 -Base Infill Density (ratio): 0.5 -Base Layer Thickness over Layer Thickness: 2.0 -Base Nozzle Lift over Base Layer Thickness (ratio): 0.4 -Initial Circling: False -Infill Overhang over Extrusion Width (ratio): 3.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/scale.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/scale.csv deleted file mode 100644 index a479f8b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/scale.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated scale settings. -_Name Value -WindowPosition 700+0 -Open File for Scale -Activate Scale to finetune print size (try to find the fault somewhere else..): False -XY Plane Scale (ratio): 1.0 -Z Axis Scale (ratio): 1.0 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge.csv deleted file mode 100644 index 22338a4..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated skeinforge settings. -_Name Value -WindowPosition 1187+2 -Open File for Skeinforge C:/Users/Ahmet/STL/_Screw Holder Bottom.stl -analyze False -craft True -help False -meta False -profile False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_analyze.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_analyze.csv deleted file mode 100644 index a399731..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_analyze.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated skeinforge analyze settings. -_Name Value -WindowPosition 600+0 -Open File for Analyze -clairvoyance False -comment False -interpret False -skeiniso True -skeinlayer True -statistic False -vectorwrite False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_craft.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_craft.csv deleted file mode 100644 index 0943077..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_craft.csv +++ /dev/null @@ -1,27 +0,0 @@ -Format is tab separated skeinforge craft settings. -_Name Value -WindowPosition 600+0 -Open File for Craft -bottom False -carve False -chamber False -clip False -comb False -cool False -dimension True -export False -fill False -inset False -jitter False -lash False -limit False -multiply False -preface False -raft False -scale False -skin False -skirt False -speed False -stretch False -temperature False -wipe False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_help.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_help.csv deleted file mode 100644 index 6447399..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinforge_help.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated skeinforge help settings. -_Name Value -WindowPosition 600+0 -Wiki Manual Primary True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeiniso.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeiniso.csv deleted file mode 100644 index a0bf075..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeiniso.csv +++ /dev/null @@ -1,41 +0,0 @@ -Format is tab separated skeiniso settings. -_Name Value -WindowPosition 700+0 -Open File for Skeiniso -Activate Skeiniso True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Axis Rulings True -Band Height (layers): 5 -Bottom Band Brightness (ratio): 0.7 -Bottom Layer Brightness (ratio): 1.0 -From the Bottom False -From the Top True -Draw Arrows False -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 912345678 -Line (index): 24 -Display Line True -View Move False -View Rotate False -Number of Fill Bottom Layers (integer): 1 -Number of Fill Top Layers (integer): 1 -Scale (pixels per millimeter): 15.0 -Screen Horizontal Inset (pixels): 100 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Viewpoint Latitude (degrees): 15.0 -Viewpoint Longitude (degrees): 210.0 -Width of Axis Negative Side (pixels): 2 -Width of Axis Positive Side (pixels): 6 -Width of Fill Bottom Thread (pixels): 2 -Width of Fill Top Thread (pixels): 2 -Width of Infill Thread (pixels): 1 -Width of Loop Thread (pixels): 2 -Width of Perimeter Inside Thread (pixels): 8 -Width of Perimeter Outside Thread (pixels): 8 -Width of Raft Thread (pixels): 1 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinlayer.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinlayer.csv deleted file mode 100644 index 5273776..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skeinlayer.csv +++ /dev/null @@ -1,23 +0,0 @@ -Format is tab separated skeinlayer settings. -_Name Value -WindowPosition 700+0 -Open File for Skeinlayer -Activate Skeinlayer True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Draw Arrows True -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 0 -Line (index): 430 -Display Line True -View Move False -Scale (pixels per millimeter): 25.0 -Screen Horizontal Inset (pixels): 100 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Show Position True -Width of Extrusion Thread (pixels): 3 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 1 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skin.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skin.csv deleted file mode 100644 index 9154030..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skin.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skin settings. -_Name Value -WindowPosition 700+0 -Open File for Skin -Activate Skin: this is experimental. -It prints the perimeters and loops only at half the layer height that is specified under carve. False -Clip Over Perimeter Width (scaler): 1.0 -Do Not Skin the first ... Layers: 3 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skirt.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skirt.csv deleted file mode 100644 index 80cd328..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/skirt.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skirt settings. -_Name Value -WindowPosition 700+0 -Open File for Skirt -Activate Skirt: True -Convex: True -Gap over Perimeter Width (ratio): 5.0 -Layers To (index): 3 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/speed.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/speed.csv deleted file mode 100644 index e2685f3..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/speed.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated speed settings. -_Name Value -WindowPosition 700+0 -Open File for Speed -Activate Speed: True -Add Flow Rate: True -Main Feed Rate (mm/s): 60.0 -Main Flow Rate (scaler): 1.0 -Feed Rate ratio for Orbiting move (ratio): 0.5 -Perimeter Feed Rate (mm/s): 30.0 -Perimeter Flow Rate (scaler): 1.0 -Bridge Feed Rate (ratio): 1.0 -Bridge Flow Rate (scaler): 1.0 -Travel Feed Rate (mm/s): 130.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/statistic.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/statistic.csv deleted file mode 100644 index 4a1f127..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/statistic.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated statistic settings. -_Name Value -WindowPosition 700+0 -Activate Statistic True -Machine Time ($/hour): 1.0 -Material ($/kg): 20.0 -Density (kg/m3): 930.0 -Extrusion Diameter over Thickness (ratio): 1.25 -Open File to Generate Statistics for -Print Statistics True -Save Statistics False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/stretch.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/stretch.csv deleted file mode 100644 index 5bc618d..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/stretch.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated stretch settings. -_Name Value -WindowPosition 700+0 -Open File for Stretch -Activate Stretch to correct for diameter shrink in small diameter holes False -Cross Limit Distance Over Perimeter Width (ratio): 5.0 -Loop Stretch Over Perimeter Width (ratio): 0.11 -Path Stretch Over Perimeter Width (ratio): 0.0 -Perimeter Inside Stretch Over Perimeter Width (ratio): 0.32 -Perimeter Outside Stretch Over Perimeter Width (ratio): 0.1 -Stretch From Distance Over Perimeter Width (ratio): 2.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/temperature.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/temperature.csv deleted file mode 100644 index ce2ef6e..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/temperature.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated temperature settings. -_Name Value -WindowPosition 700+0 -Open File for Temperature -Activate Temperature: False -Cooling Rate (Celcius/second): 3.0 -Heating Rate (Celcius/second): 3.0 -Base Temperature (Celcius): 210.0 -Interface Temperature (Celcius): 210.0 -Object First Layer Infill Temperature (Celcius): 210.0 -Object First Layer Perimeter Temperature (Celcius): 210.0 -Object Next Layers Temperature (Celcius): 210.0 -Support Layers Temperature (Celcius): 210.0 -Supported Layers Temperature (Celcius): 210.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/vectorwrite.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/vectorwrite.csv deleted file mode 100644 index e03372b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/vectorwrite.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated vectorwrite settings. -_Name Value -WindowPosition 700+0 -Activate Vectorwrite False -Open File to Write Vector Graphics for -Add Loops True -Add Paths True -Add Perimeters True -Layers From (index): 0 -Layers To (index): 912345678 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/wipe.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/wipe.csv deleted file mode 100644 index 2533703..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/1.7mm-0.5 nozzle/wipe.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated wipe settings. -_Name Value -WindowPosition 700+0 -Open File for Wipe -Activate Wipe False -Location Arrival X (mm): 0.0 -Location Arrival Y (mm): 5.0 -Location Arrival Z (mm): 0.0 -Location Departure X (mm): 5.0 -Location Departure Y (mm): 0.0 -Location Departure Z (mm): 0.0 -Location Wipe X (mm): 0.0 -Location Wipe Y (mm): 0.0 -Location Wipe Z (mm): 0.0 -Wipe Period (layers): 33333 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/bottom.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/bottom.csv deleted file mode 100644 index 0a24bd9..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/bottom.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated bottom settings. -_Name Value -WindowPosition 700+0 -Open File for Bottom -Activate Bottom... and dont change anything else here!!! True -Additional Height (ratio): 0.5 -Altitude (mm): 0.0 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/carve.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/carve.csv deleted file mode 100644 index 03cd070..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/carve.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated carve settings. -_Name Value -WindowPosition 700+0 -Open File for Carve -Layer Height = Extrusion Thickness (mm): 0.33 -Extrusion Width (mm): 0.5 -Print from Layer No:: 0 -Print up to Layer No: 912345678 -Infill in Direction of Bridge True -Correct Mesh True -Unproven Mesh False -SVG Viewer: webbrowser -Add Layer Template to SVG True -Extra Decimal Places (float): 2.0 -Import Coarseness (ratio): 1.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/chamber.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/chamber.csv deleted file mode 100644 index 08ccd9c..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/chamber.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated chamber settings. -_Name Value -WindowPosition 700+0 -Open File for Chamber -Activate Chamber..if you want below functions to work True -Heated PrintBed Temperature (Celcius): 60.0 -Turn print Bed Heater Off at Shut Down True -Turn Extruder Heater Off at Shut Down True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/clairvoyance.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/clairvoyance.csv deleted file mode 100644 index 8aadf4f..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/clairvoyance.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated clairvoyance settings. -_Name Value -WindowPosition 700+0 -Activate Clairvoyance False -Open File to Generate Clairvoyances for -Gcode Program: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/clip.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/clip.csv deleted file mode 100644 index c61adb8..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/clip.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated clip settings. -_Name Value -WindowPosition 700+0 -Open File for Clip -Activate Clip..to clip the extrusion that overlaps when printing perimeters True -Clip Over Perimeter Width adjuster (decrease for bigger gap): 1.0 -Threshold for connecting inner loops (ratio): 2.5 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/comb.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/comb.csv deleted file mode 100644 index 403d19b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/comb.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated comb settings. -_Name Value -WindowPosition 700+0 -Open File for Comb -Activate Comb if you cant stop the extruder stringing by retraction -it will avoid moving over loops so the strings will be there -but not visible anymore. -Comb bends the extruder travel paths around holes in the slices, to avoid stringing. -so any start up ooze will be inside the shape. True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/comment.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/comment.csv deleted file mode 100644 index c140205..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/comment.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated comment settings. -_Name Value -WindowPosition 700+0 -Activate Comment False -Open File to Write Comments for diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/cool.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/cool.csv deleted file mode 100644 index ed931a0..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/cool.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated cool settings. -_Name Value -WindowPosition 700+0 -Open File for Cool -Activate Cool.. but use with a fan! False -Use Cool if layer takes shorter than(seconds): 10.0 -Turn Fan On at Beginning True -Turn Fan Off at Ending True -Execute when Cool starts: cool_start.gmc -Execute when Cool ends: cool_end.gmc -Orbiting around Object False -Slow Down during print True -Maximum Cool (Celcius): 2.0 -Bridge Cool (Celcius): 1.0 -Minimum Orbital Radius (millimeters): 10.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/dimension.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/dimension.csv deleted file mode 100644 index 4c110d3..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/dimension.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated dimension settings. -_Name Value -WindowPosition 700+0 -Open File for Dimension -Activate Volumetric Extrusion (Stepper driven Extruders) True -Filament Diameter (mm): 2.85 -Filament Packing Density (ratio) lower=more extrusion: 1.0 -Retraction Distance (millimeters): 1.0 -Restart Extra Distance (millimeters): 0.0 -Extruder Retraction Speed (mm/s): 15.0 -Force to retract when crossing over spaces True -Minimum Extrusion before Retraction (millimeters): 1.0 -Minimum Travelmove after Retraction (millimeters): 1.0 -in Absolute units (Sprinter, FiveD a.o.) True -in Relative units (Teacup a.o.) False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/export.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/export.csv deleted file mode 100644 index be5764b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/export.csv +++ /dev/null @@ -1,20 +0,0 @@ -Format is tab separated export settings. -_Name Value -WindowPosition 700+0 -Open File for Export -Activate Export True -Add _export to filename (filename_export) True -Also Send Output To: -Do Not Delete Comments False -Delete Crafting Comments False -Delete All Comments True -Do Not Change Output False -gcode_small True -File Extension (gcode): gcode -Name of Replace File: replace.csv -Save Penultimate Gcode False -Archive Used Profile As Zip False -Export Profile Values As CSV File False -Add Profile Name to Filename False -Add Description to Filename False -Add Timestamp to Filename False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/fill.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/fill.csv deleted file mode 100644 index 682b1eb..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/fill.csv +++ /dev/null @@ -1,34 +0,0 @@ -Format is tab separated fill settings. -_Name Value -WindowPosition 700+0 -Open File for Fill -Activate Fill: True -Infill Solidity (ratio): 0.35 -Extrusion Lines extra Spacing (Scaler): 1.0 -Infill Overlap over Perimeter (Scaler): 1.0 -Extra Shells on Alternating Solid Layer (layers): 1 -Extra Shells on Base (layers): 1 -Extra Shells on Sparse Layer (layers): 1 -Fully filled Layers (each top and bottom): 2 -Lower Left True -Nearest False -Infill > Loops > Perimeter False -Infill > Perimeter > Loops False -Loops > Infill > Perimeter False -Loops > Perimeter > Infill False -Perimeter > Infill > Loops False -Perimeter > Loops > Infill True -Line True -Grid Circular False -Grid Hexagonal False -Grid Rectangular False -Diaphragm at every ...th Layer: 100 -Diaphragm Thickness (layers): 0 -Grid Circle Separation over Perimeter Width (ratio): 0.2 -Grid Extra Overlap (ratio): 0.1 -Grid Junction Separation Band Height (layers): 10 -Grid Junction Separation over Octogon Radius At End (ratio): 0.0 -Grid Junction Separation over Octogon Radius At Middle (ratio): 0.0 -Infill Begin Rotation (degrees): 45.0 -Infill Begin Rotation Repeat (layers): 1 -Infill Odd Layer Extra Rotation (degrees): 90.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/home.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/home.csv deleted file mode 100644 index 430a33a..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/home.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated home settings. -_Name Value -WindowPosition 700+0 -Open File for Home -Activate Home ... Not needed True -Name of Homing File: homing.gcode diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/inset.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/inset.csv deleted file mode 100644 index 6c3d57c..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/inset.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated inset settings. -_Name Value -WindowPosition 700+0 -Open File for Inset -Bridge Width Multiplier (ratio): 1.0 -Prefer Loops False -Prefer Perimeter True -Overlap Removal(Scaler): 1.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/interpret.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/interpret.csv deleted file mode 100644 index 76cdc59..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/interpret.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated interpret settings. -_Name Value -WindowPosition 700+0 -Open File for Interpret -Activate Interpret False -Print Interpretion False -Text Program: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/jitter.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/jitter.csv deleted file mode 100644 index 781738d..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/jitter.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated jitter settings. -_Name Value -WindowPosition 700+0 -Open File for Jitter -Activate Jitter to have your perimeter and loop endpoints scattered False -Jitter Over Perimeter Width (ratio): 2.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/lash.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/lash.csv deleted file mode 100644 index 32ccb3b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/lash.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated lash settings. -_Name Value -WindowPosition 700+0 -Open File for Lash -Activate Lash if you have backlash in your axes. -But its better to fix the mechanical problem! False -X Backlash (mm): 0.0 -Y Backlash (mm): 0.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/limit.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/limit.csv deleted file mode 100644 index 9671405..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/limit.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated limit settings. -_Name Value -WindowPosition 700+0 -Open File for Limit -Activate Limit if your Firmware is unable to Limiting your Z-Speed. False -Maximum Initial Feed Rate (mm/s): 5.0 -Maximum Z Feed Rate (mm/s): 5.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/multiply.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/multiply.csv deleted file mode 100644 index 269d53f..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/multiply.csv +++ /dev/null @@ -1,10 +0,0 @@ -Format is tab separated multiply settings. -_Name Value -WindowPosition 700+0 -Open File for Multiply -Activate Multiply: True -Center X (mm): 100.0 -Center Y (mm): 100.0 -Number of Columns (integer): 1 -Number of Rows (integer): 1 -Separation over Perimeter Width (ratio): 15.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/polyfile.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/polyfile.csv deleted file mode 100644 index 6e7d9bb..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/polyfile.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated polyfile settings. -_Name Value -WindowPosition 700+0 -Execute All Unmodified Files in a Directory False -Execute File True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/preface.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/preface.csv deleted file mode 100644 index ff7f52f..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/preface.csv +++ /dev/null @@ -1,11 +0,0 @@ -_Name Value -Format is tab separated preface settings. -Home before Print False -Meta: -Name of End File: end.gmc -Name of Start File: start.gmc -Open File for Preface -Reset Extruder before Print True -Set Positioning to Absolute True -Set Units to Millimeters True -WindowPosition 700+0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/raft.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/raft.csv deleted file mode 100644 index 8d4b00a..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/raft.csv +++ /dev/null @@ -1,38 +0,0 @@ -Format is tab separated raft settings. -_Name Value -WindowPosition 700+0 -Open File for Raft -Activate Raft True -Add Raft, Elevate Nozzle, Orbit: True -None True -Empty Layers Only False -Everywhere False -Exterior Only False -Add support if flatter than (degrees): 50.0 -Cross Hatch instead of Lines False -Interface/Support Lines Density (ratio): 0.25 -Interface/Support Layer Thickness over Layer Thickness: 1.0 -Support Feed Rate mm/sec: 15.0 -Support Flow Rate (scaler): 1.0 -Support Gap over Perimeter Extrusion Width (ratio): 1.0 -Raft/Support extension in (%): 5.0 -Raft/Support extension in(mm): 2.0 -Name of Support End File: support_end.gmc -Name of Support Start File: support_start.gmc -Extra Nozzle clearance over Object(ratio): 0.0 -First Layer Main Feedrate (mm/s): 35.0 -First Layer Perimeter Feedrate (mm/s): 25.0 -First Layer Flow Rate Infill(scaler): 1.0 -First Layer Flow Rate Perimeter(scaler): 1.0 -Interface Layers (integer): 0 -Interface Feed Rate Multiplier (ratio): 1.0 -Interface Flow Rate Multiplier (ratio): 1.0 -Interface Nozzle Lift over Interface Layer Thickness (ratio): 0.45 -Base Layers (integer): 0 -Base Feed Rate Multiplier (ratio): 0.5 -Base Flow Rate Multiplier (ratio): 0.5 -Base Infill Density (ratio): 0.5 -Base Layer Thickness over Layer Thickness: 2.0 -Base Nozzle Lift over Base Layer Thickness (ratio): 0.4 -Initial Circling: False -Infill Overhang over Extrusion Width (ratio): 3.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/scale.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/scale.csv deleted file mode 100644 index a479f8b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/scale.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated scale settings. -_Name Value -WindowPosition 700+0 -Open File for Scale -Activate Scale to finetune print size (try to find the fault somewhere else..): False -XY Plane Scale (ratio): 1.0 -Z Axis Scale (ratio): 1.0 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge.csv deleted file mode 100644 index 22338a4..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated skeinforge settings. -_Name Value -WindowPosition 1187+2 -Open File for Skeinforge C:/Users/Ahmet/STL/_Screw Holder Bottom.stl -analyze False -craft True -help False -meta False -profile False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_analyze.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_analyze.csv deleted file mode 100644 index 8826bcb..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_analyze.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated skeinforge analyze settings. -_Name Value -WindowPosition 600+0 -Open File for Analyze -clairvoyance False -comment False -interpret False -skeiniso True -skeinlayer False -statistic False -vectorwrite False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_craft.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_craft.csv deleted file mode 100644 index 0943077..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_craft.csv +++ /dev/null @@ -1,27 +0,0 @@ -Format is tab separated skeinforge craft settings. -_Name Value -WindowPosition 600+0 -Open File for Craft -bottom False -carve False -chamber False -clip False -comb False -cool False -dimension True -export False -fill False -inset False -jitter False -lash False -limit False -multiply False -preface False -raft False -scale False -skin False -skirt False -speed False -stretch False -temperature False -wipe False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_help.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_help.csv deleted file mode 100644 index 6447399..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinforge_help.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated skeinforge help settings. -_Name Value -WindowPosition 600+0 -Wiki Manual Primary True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeiniso.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeiniso.csv deleted file mode 100644 index a0bf075..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeiniso.csv +++ /dev/null @@ -1,41 +0,0 @@ -Format is tab separated skeiniso settings. -_Name Value -WindowPosition 700+0 -Open File for Skeiniso -Activate Skeiniso True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Axis Rulings True -Band Height (layers): 5 -Bottom Band Brightness (ratio): 0.7 -Bottom Layer Brightness (ratio): 1.0 -From the Bottom False -From the Top True -Draw Arrows False -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 912345678 -Line (index): 24 -Display Line True -View Move False -View Rotate False -Number of Fill Bottom Layers (integer): 1 -Number of Fill Top Layers (integer): 1 -Scale (pixels per millimeter): 15.0 -Screen Horizontal Inset (pixels): 100 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Viewpoint Latitude (degrees): 15.0 -Viewpoint Longitude (degrees): 210.0 -Width of Axis Negative Side (pixels): 2 -Width of Axis Positive Side (pixels): 6 -Width of Fill Bottom Thread (pixels): 2 -Width of Fill Top Thread (pixels): 2 -Width of Infill Thread (pixels): 1 -Width of Loop Thread (pixels): 2 -Width of Perimeter Inside Thread (pixels): 8 -Width of Perimeter Outside Thread (pixels): 8 -Width of Raft Thread (pixels): 1 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinlayer.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinlayer.csv deleted file mode 100644 index 5273776..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skeinlayer.csv +++ /dev/null @@ -1,23 +0,0 @@ -Format is tab separated skeinlayer settings. -_Name Value -WindowPosition 700+0 -Open File for Skeinlayer -Activate Skeinlayer True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Draw Arrows True -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 0 -Line (index): 430 -Display Line True -View Move False -Scale (pixels per millimeter): 25.0 -Screen Horizontal Inset (pixels): 100 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Show Position True -Width of Extrusion Thread (pixels): 3 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 1 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skin.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skin.csv deleted file mode 100644 index 9154030..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skin.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skin settings. -_Name Value -WindowPosition 700+0 -Open File for Skin -Activate Skin: this is experimental. -It prints the perimeters and loops only at half the layer height that is specified under carve. False -Clip Over Perimeter Width (scaler): 1.0 -Do Not Skin the first ... Layers: 3 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skirt.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skirt.csv deleted file mode 100644 index 80cd328..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/skirt.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skirt settings. -_Name Value -WindowPosition 700+0 -Open File for Skirt -Activate Skirt: True -Convex: True -Gap over Perimeter Width (ratio): 5.0 -Layers To (index): 3 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/speed.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/speed.csv deleted file mode 100644 index e2685f3..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/speed.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated speed settings. -_Name Value -WindowPosition 700+0 -Open File for Speed -Activate Speed: True -Add Flow Rate: True -Main Feed Rate (mm/s): 60.0 -Main Flow Rate (scaler): 1.0 -Feed Rate ratio for Orbiting move (ratio): 0.5 -Perimeter Feed Rate (mm/s): 30.0 -Perimeter Flow Rate (scaler): 1.0 -Bridge Feed Rate (ratio): 1.0 -Bridge Flow Rate (scaler): 1.0 -Travel Feed Rate (mm/s): 130.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/statistic.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/statistic.csv deleted file mode 100644 index 4a1f127..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/statistic.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated statistic settings. -_Name Value -WindowPosition 700+0 -Activate Statistic True -Machine Time ($/hour): 1.0 -Material ($/kg): 20.0 -Density (kg/m3): 930.0 -Extrusion Diameter over Thickness (ratio): 1.25 -Open File to Generate Statistics for -Print Statistics True -Save Statistics False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/stretch.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/stretch.csv deleted file mode 100644 index 5bc618d..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/stretch.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated stretch settings. -_Name Value -WindowPosition 700+0 -Open File for Stretch -Activate Stretch to correct for diameter shrink in small diameter holes False -Cross Limit Distance Over Perimeter Width (ratio): 5.0 -Loop Stretch Over Perimeter Width (ratio): 0.11 -Path Stretch Over Perimeter Width (ratio): 0.0 -Perimeter Inside Stretch Over Perimeter Width (ratio): 0.32 -Perimeter Outside Stretch Over Perimeter Width (ratio): 0.1 -Stretch From Distance Over Perimeter Width (ratio): 2.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/temperature.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/temperature.csv deleted file mode 100644 index ce2ef6e..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/temperature.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated temperature settings. -_Name Value -WindowPosition 700+0 -Open File for Temperature -Activate Temperature: False -Cooling Rate (Celcius/second): 3.0 -Heating Rate (Celcius/second): 3.0 -Base Temperature (Celcius): 210.0 -Interface Temperature (Celcius): 210.0 -Object First Layer Infill Temperature (Celcius): 210.0 -Object First Layer Perimeter Temperature (Celcius): 210.0 -Object Next Layers Temperature (Celcius): 210.0 -Support Layers Temperature (Celcius): 210.0 -Supported Layers Temperature (Celcius): 210.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/vectorwrite.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/vectorwrite.csv deleted file mode 100644 index e03372b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/vectorwrite.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated vectorwrite settings. -_Name Value -WindowPosition 700+0 -Activate Vectorwrite False -Open File to Write Vector Graphics for -Add Loops True -Add Paths True -Add Perimeters True -Layers From (index): 0 -Layers To (index): 912345678 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/wipe.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/wipe.csv deleted file mode 100644 index 2533703..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.3 nozzle/wipe.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated wipe settings. -_Name Value -WindowPosition 700+0 -Open File for Wipe -Activate Wipe False -Location Arrival X (mm): 0.0 -Location Arrival Y (mm): 5.0 -Location Arrival Z (mm): 0.0 -Location Departure X (mm): 5.0 -Location Departure Y (mm): 0.0 -Location Departure Z (mm): 0.0 -Location Wipe X (mm): 0.0 -Location Wipe Y (mm): 0.0 -Location Wipe Z (mm): 0.0 -Wipe Period (layers): 33333 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/bottom.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/bottom.csv deleted file mode 100644 index 0a24bd9..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/bottom.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated bottom settings. -_Name Value -WindowPosition 700+0 -Open File for Bottom -Activate Bottom... and dont change anything else here!!! True -Additional Height (ratio): 0.5 -Altitude (mm): 0.0 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/carve.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/carve.csv deleted file mode 100644 index 3a65503..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/carve.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated carve settings. -_Name Value -WindowPosition 700+0 -Open File for Carve -Layer Height = Extrusion Thickness (mm): 0.4 -Extrusion Width (mm): 0.6 -Print from Layer No:: 0 -Print up to Layer No: 912345678 -Infill in Direction of Bridge True -Correct Mesh True -Unproven Mesh False -SVG Viewer: webbrowser -Add Layer Template to SVG True -Extra Decimal Places (float): 2.0 -Import Coarseness (ratio): 1.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/chamber.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/chamber.csv deleted file mode 100644 index 08ccd9c..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/chamber.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated chamber settings. -_Name Value -WindowPosition 700+0 -Open File for Chamber -Activate Chamber..if you want below functions to work True -Heated PrintBed Temperature (Celcius): 60.0 -Turn print Bed Heater Off at Shut Down True -Turn Extruder Heater Off at Shut Down True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/clairvoyance.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/clairvoyance.csv deleted file mode 100644 index 8aadf4f..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/clairvoyance.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated clairvoyance settings. -_Name Value -WindowPosition 700+0 -Activate Clairvoyance False -Open File to Generate Clairvoyances for -Gcode Program: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/clip.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/clip.csv deleted file mode 100644 index c61adb8..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/clip.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated clip settings. -_Name Value -WindowPosition 700+0 -Open File for Clip -Activate Clip..to clip the extrusion that overlaps when printing perimeters True -Clip Over Perimeter Width adjuster (decrease for bigger gap): 1.0 -Threshold for connecting inner loops (ratio): 2.5 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/comb.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/comb.csv deleted file mode 100644 index 403d19b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/comb.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated comb settings. -_Name Value -WindowPosition 700+0 -Open File for Comb -Activate Comb if you cant stop the extruder stringing by retraction -it will avoid moving over loops so the strings will be there -but not visible anymore. -Comb bends the extruder travel paths around holes in the slices, to avoid stringing. -so any start up ooze will be inside the shape. True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/comment.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/comment.csv deleted file mode 100644 index c140205..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/comment.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated comment settings. -_Name Value -WindowPosition 700+0 -Activate Comment False -Open File to Write Comments for diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/cool.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/cool.csv deleted file mode 100644 index ed931a0..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/cool.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated cool settings. -_Name Value -WindowPosition 700+0 -Open File for Cool -Activate Cool.. but use with a fan! False -Use Cool if layer takes shorter than(seconds): 10.0 -Turn Fan On at Beginning True -Turn Fan Off at Ending True -Execute when Cool starts: cool_start.gmc -Execute when Cool ends: cool_end.gmc -Orbiting around Object False -Slow Down during print True -Maximum Cool (Celcius): 2.0 -Bridge Cool (Celcius): 1.0 -Minimum Orbital Radius (millimeters): 10.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/dimension.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/dimension.csv deleted file mode 100644 index 4c110d3..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/dimension.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated dimension settings. -_Name Value -WindowPosition 700+0 -Open File for Dimension -Activate Volumetric Extrusion (Stepper driven Extruders) True -Filament Diameter (mm): 2.85 -Filament Packing Density (ratio) lower=more extrusion: 1.0 -Retraction Distance (millimeters): 1.0 -Restart Extra Distance (millimeters): 0.0 -Extruder Retraction Speed (mm/s): 15.0 -Force to retract when crossing over spaces True -Minimum Extrusion before Retraction (millimeters): 1.0 -Minimum Travelmove after Retraction (millimeters): 1.0 -in Absolute units (Sprinter, FiveD a.o.) True -in Relative units (Teacup a.o.) False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/export.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/export.csv deleted file mode 100644 index be5764b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/export.csv +++ /dev/null @@ -1,20 +0,0 @@ -Format is tab separated export settings. -_Name Value -WindowPosition 700+0 -Open File for Export -Activate Export True -Add _export to filename (filename_export) True -Also Send Output To: -Do Not Delete Comments False -Delete Crafting Comments False -Delete All Comments True -Do Not Change Output False -gcode_small True -File Extension (gcode): gcode -Name of Replace File: replace.csv -Save Penultimate Gcode False -Archive Used Profile As Zip False -Export Profile Values As CSV File False -Add Profile Name to Filename False -Add Description to Filename False -Add Timestamp to Filename False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/fill.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/fill.csv deleted file mode 100644 index 682b1eb..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/fill.csv +++ /dev/null @@ -1,34 +0,0 @@ -Format is tab separated fill settings. -_Name Value -WindowPosition 700+0 -Open File for Fill -Activate Fill: True -Infill Solidity (ratio): 0.35 -Extrusion Lines extra Spacing (Scaler): 1.0 -Infill Overlap over Perimeter (Scaler): 1.0 -Extra Shells on Alternating Solid Layer (layers): 1 -Extra Shells on Base (layers): 1 -Extra Shells on Sparse Layer (layers): 1 -Fully filled Layers (each top and bottom): 2 -Lower Left True -Nearest False -Infill > Loops > Perimeter False -Infill > Perimeter > Loops False -Loops > Infill > Perimeter False -Loops > Perimeter > Infill False -Perimeter > Infill > Loops False -Perimeter > Loops > Infill True -Line True -Grid Circular False -Grid Hexagonal False -Grid Rectangular False -Diaphragm at every ...th Layer: 100 -Diaphragm Thickness (layers): 0 -Grid Circle Separation over Perimeter Width (ratio): 0.2 -Grid Extra Overlap (ratio): 0.1 -Grid Junction Separation Band Height (layers): 10 -Grid Junction Separation over Octogon Radius At End (ratio): 0.0 -Grid Junction Separation over Octogon Radius At Middle (ratio): 0.0 -Infill Begin Rotation (degrees): 45.0 -Infill Begin Rotation Repeat (layers): 1 -Infill Odd Layer Extra Rotation (degrees): 90.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/home.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/home.csv deleted file mode 100644 index 430a33a..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/home.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated home settings. -_Name Value -WindowPosition 700+0 -Open File for Home -Activate Home ... Not needed True -Name of Homing File: homing.gcode diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/inset.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/inset.csv deleted file mode 100644 index 6c3d57c..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/inset.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated inset settings. -_Name Value -WindowPosition 700+0 -Open File for Inset -Bridge Width Multiplier (ratio): 1.0 -Prefer Loops False -Prefer Perimeter True -Overlap Removal(Scaler): 1.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/interpret.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/interpret.csv deleted file mode 100644 index 76cdc59..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/interpret.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated interpret settings. -_Name Value -WindowPosition 700+0 -Open File for Interpret -Activate Interpret False -Print Interpretion False -Text Program: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/jitter.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/jitter.csv deleted file mode 100644 index 781738d..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/jitter.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated jitter settings. -_Name Value -WindowPosition 700+0 -Open File for Jitter -Activate Jitter to have your perimeter and loop endpoints scattered False -Jitter Over Perimeter Width (ratio): 2.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/lash.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/lash.csv deleted file mode 100644 index 32ccb3b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/lash.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated lash settings. -_Name Value -WindowPosition 700+0 -Open File for Lash -Activate Lash if you have backlash in your axes. -But its better to fix the mechanical problem! False -X Backlash (mm): 0.0 -Y Backlash (mm): 0.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/limit.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/limit.csv deleted file mode 100644 index 9671405..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/limit.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated limit settings. -_Name Value -WindowPosition 700+0 -Open File for Limit -Activate Limit if your Firmware is unable to Limiting your Z-Speed. False -Maximum Initial Feed Rate (mm/s): 5.0 -Maximum Z Feed Rate (mm/s): 5.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/multiply.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/multiply.csv deleted file mode 100644 index 269d53f..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/multiply.csv +++ /dev/null @@ -1,10 +0,0 @@ -Format is tab separated multiply settings. -_Name Value -WindowPosition 700+0 -Open File for Multiply -Activate Multiply: True -Center X (mm): 100.0 -Center Y (mm): 100.0 -Number of Columns (integer): 1 -Number of Rows (integer): 1 -Separation over Perimeter Width (ratio): 15.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/polyfile.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/polyfile.csv deleted file mode 100644 index 6e7d9bb..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/polyfile.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated polyfile settings. -_Name Value -WindowPosition 700+0 -Execute All Unmodified Files in a Directory False -Execute File True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/preface.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/preface.csv deleted file mode 100644 index 4c37dad..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/preface.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated preface settings. -_Name Value -WindowPosition 700+0 -Open File for Preface -Meta: -Name of End File: end.gmc -Name of Start File: start.gmc -Set Positioning to Absolute True -Set Units to Millimeters True -Home before Print False -Reset Extruder before Print True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/raft.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/raft.csv deleted file mode 100644 index 8d4b00a..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/raft.csv +++ /dev/null @@ -1,38 +0,0 @@ -Format is tab separated raft settings. -_Name Value -WindowPosition 700+0 -Open File for Raft -Activate Raft True -Add Raft, Elevate Nozzle, Orbit: True -None True -Empty Layers Only False -Everywhere False -Exterior Only False -Add support if flatter than (degrees): 50.0 -Cross Hatch instead of Lines False -Interface/Support Lines Density (ratio): 0.25 -Interface/Support Layer Thickness over Layer Thickness: 1.0 -Support Feed Rate mm/sec: 15.0 -Support Flow Rate (scaler): 1.0 -Support Gap over Perimeter Extrusion Width (ratio): 1.0 -Raft/Support extension in (%): 5.0 -Raft/Support extension in(mm): 2.0 -Name of Support End File: support_end.gmc -Name of Support Start File: support_start.gmc -Extra Nozzle clearance over Object(ratio): 0.0 -First Layer Main Feedrate (mm/s): 35.0 -First Layer Perimeter Feedrate (mm/s): 25.0 -First Layer Flow Rate Infill(scaler): 1.0 -First Layer Flow Rate Perimeter(scaler): 1.0 -Interface Layers (integer): 0 -Interface Feed Rate Multiplier (ratio): 1.0 -Interface Flow Rate Multiplier (ratio): 1.0 -Interface Nozzle Lift over Interface Layer Thickness (ratio): 0.45 -Base Layers (integer): 0 -Base Feed Rate Multiplier (ratio): 0.5 -Base Flow Rate Multiplier (ratio): 0.5 -Base Infill Density (ratio): 0.5 -Base Layer Thickness over Layer Thickness: 2.0 -Base Nozzle Lift over Base Layer Thickness (ratio): 0.4 -Initial Circling: False -Infill Overhang over Extrusion Width (ratio): 3.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/scale.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/scale.csv deleted file mode 100644 index a479f8b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/scale.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated scale settings. -_Name Value -WindowPosition 700+0 -Open File for Scale -Activate Scale to finetune print size (try to find the fault somewhere else..): False -XY Plane Scale (ratio): 1.0 -Z Axis Scale (ratio): 1.0 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge.csv deleted file mode 100644 index 22338a4..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated skeinforge settings. -_Name Value -WindowPosition 1187+2 -Open File for Skeinforge C:/Users/Ahmet/STL/_Screw Holder Bottom.stl -analyze False -craft True -help False -meta False -profile False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_analyze.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_analyze.csv deleted file mode 100644 index e9fca6c..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_analyze.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated skeinforge analyze settings. -_Name Value -WindowPosition 600+0 -Open File for Analyze -clairvoyance False -comment False -interpret False -skeiniso False -skeinlayer True -statistic False -vectorwrite False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_craft.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_craft.csv deleted file mode 100644 index 0943077..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_craft.csv +++ /dev/null @@ -1,27 +0,0 @@ -Format is tab separated skeinforge craft settings. -_Name Value -WindowPosition 600+0 -Open File for Craft -bottom False -carve False -chamber False -clip False -comb False -cool False -dimension True -export False -fill False -inset False -jitter False -lash False -limit False -multiply False -preface False -raft False -scale False -skin False -skirt False -speed False -stretch False -temperature False -wipe False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_help.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_help.csv deleted file mode 100644 index 6447399..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinforge_help.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated skeinforge help settings. -_Name Value -WindowPosition 600+0 -Wiki Manual Primary True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeiniso.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeiniso.csv deleted file mode 100644 index a0bf075..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeiniso.csv +++ /dev/null @@ -1,41 +0,0 @@ -Format is tab separated skeiniso settings. -_Name Value -WindowPosition 700+0 -Open File for Skeiniso -Activate Skeiniso True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Axis Rulings True -Band Height (layers): 5 -Bottom Band Brightness (ratio): 0.7 -Bottom Layer Brightness (ratio): 1.0 -From the Bottom False -From the Top True -Draw Arrows False -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 912345678 -Line (index): 24 -Display Line True -View Move False -View Rotate False -Number of Fill Bottom Layers (integer): 1 -Number of Fill Top Layers (integer): 1 -Scale (pixels per millimeter): 15.0 -Screen Horizontal Inset (pixels): 100 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Viewpoint Latitude (degrees): 15.0 -Viewpoint Longitude (degrees): 210.0 -Width of Axis Negative Side (pixels): 2 -Width of Axis Positive Side (pixels): 6 -Width of Fill Bottom Thread (pixels): 2 -Width of Fill Top Thread (pixels): 2 -Width of Infill Thread (pixels): 1 -Width of Loop Thread (pixels): 2 -Width of Perimeter Inside Thread (pixels): 8 -Width of Perimeter Outside Thread (pixels): 8 -Width of Raft Thread (pixels): 1 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinlayer.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinlayer.csv deleted file mode 100644 index c3101e1..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skeinlayer.csv +++ /dev/null @@ -1,23 +0,0 @@ -Format is tab separated skeinlayer settings. -_Name Value -WindowPosition 700+0 -Open File for Skeinlayer -Activate Skeinlayer True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Draw Arrows True -Go Around Extruder Off Travel False -Layer (index): 1 -Layer Extra Span (integer): 0 -Line (index): 724 -Display Line True -View Move False -Scale (pixels per millimeter): 70.0 -Screen Horizontal Inset (pixels): 102 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Show Position True -Width of Extrusion Thread (pixels): 3 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 1 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skin.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skin.csv deleted file mode 100644 index 9154030..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skin.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skin settings. -_Name Value -WindowPosition 700+0 -Open File for Skin -Activate Skin: this is experimental. -It prints the perimeters and loops only at half the layer height that is specified under carve. False -Clip Over Perimeter Width (scaler): 1.0 -Do Not Skin the first ... Layers: 3 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skirt.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skirt.csv deleted file mode 100644 index 80cd328..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/skirt.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skirt settings. -_Name Value -WindowPosition 700+0 -Open File for Skirt -Activate Skirt: True -Convex: True -Gap over Perimeter Width (ratio): 5.0 -Layers To (index): 3 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/speed.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/speed.csv deleted file mode 100644 index e2685f3..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/speed.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated speed settings. -_Name Value -WindowPosition 700+0 -Open File for Speed -Activate Speed: True -Add Flow Rate: True -Main Feed Rate (mm/s): 60.0 -Main Flow Rate (scaler): 1.0 -Feed Rate ratio for Orbiting move (ratio): 0.5 -Perimeter Feed Rate (mm/s): 30.0 -Perimeter Flow Rate (scaler): 1.0 -Bridge Feed Rate (ratio): 1.0 -Bridge Flow Rate (scaler): 1.0 -Travel Feed Rate (mm/s): 130.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/statistic.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/statistic.csv deleted file mode 100644 index 4a1f127..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/statistic.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated statistic settings. -_Name Value -WindowPosition 700+0 -Activate Statistic True -Machine Time ($/hour): 1.0 -Material ($/kg): 20.0 -Density (kg/m3): 930.0 -Extrusion Diameter over Thickness (ratio): 1.25 -Open File to Generate Statistics for -Print Statistics True -Save Statistics False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/stretch.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/stretch.csv deleted file mode 100644 index 5bc618d..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/stretch.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated stretch settings. -_Name Value -WindowPosition 700+0 -Open File for Stretch -Activate Stretch to correct for diameter shrink in small diameter holes False -Cross Limit Distance Over Perimeter Width (ratio): 5.0 -Loop Stretch Over Perimeter Width (ratio): 0.11 -Path Stretch Over Perimeter Width (ratio): 0.0 -Perimeter Inside Stretch Over Perimeter Width (ratio): 0.32 -Perimeter Outside Stretch Over Perimeter Width (ratio): 0.1 -Stretch From Distance Over Perimeter Width (ratio): 2.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/temperature.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/temperature.csv deleted file mode 100644 index ce2ef6e..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/temperature.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated temperature settings. -_Name Value -WindowPosition 700+0 -Open File for Temperature -Activate Temperature: False -Cooling Rate (Celcius/second): 3.0 -Heating Rate (Celcius/second): 3.0 -Base Temperature (Celcius): 210.0 -Interface Temperature (Celcius): 210.0 -Object First Layer Infill Temperature (Celcius): 210.0 -Object First Layer Perimeter Temperature (Celcius): 210.0 -Object Next Layers Temperature (Celcius): 210.0 -Support Layers Temperature (Celcius): 210.0 -Supported Layers Temperature (Celcius): 210.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/vectorwrite.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/vectorwrite.csv deleted file mode 100644 index e03372b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/vectorwrite.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated vectorwrite settings. -_Name Value -WindowPosition 700+0 -Activate Vectorwrite False -Open File to Write Vector Graphics for -Add Loops True -Add Paths True -Add Perimeters True -Layers From (index): 0 -Layers To (index): 912345678 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/wipe.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/wipe.csv deleted file mode 100644 index 2533703..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/3mm-0.5nozzle/wipe.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated wipe settings. -_Name Value -WindowPosition 700+0 -Open File for Wipe -Activate Wipe False -Location Arrival X (mm): 0.0 -Location Arrival Y (mm): 5.0 -Location Arrival Z (mm): 0.0 -Location Departure X (mm): 5.0 -Location Departure Y (mm): 0.0 -Location Departure Z (mm): 0.0 -Location Wipe X (mm): 0.0 -Location Wipe Y (mm): 0.0 -Location Wipe Z (mm): 0.0 -Wipe Period (layers): 33333 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/bottom.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/bottom.csv deleted file mode 100644 index 0a24bd9..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/bottom.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated bottom settings. -_Name Value -WindowPosition 700+0 -Open File for Bottom -Activate Bottom... and dont change anything else here!!! True -Additional Height (ratio): 0.5 -Altitude (mm): 0.0 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/carve.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/carve.csv deleted file mode 100644 index 3a65503..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/carve.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated carve settings. -_Name Value -WindowPosition 700+0 -Open File for Carve -Layer Height = Extrusion Thickness (mm): 0.4 -Extrusion Width (mm): 0.6 -Print from Layer No:: 0 -Print up to Layer No: 912345678 -Infill in Direction of Bridge True -Correct Mesh True -Unproven Mesh False -SVG Viewer: webbrowser -Add Layer Template to SVG True -Extra Decimal Places (float): 2.0 -Import Coarseness (ratio): 1.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/chamber.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/chamber.csv deleted file mode 100644 index 08ccd9c..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/chamber.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated chamber settings. -_Name Value -WindowPosition 700+0 -Open File for Chamber -Activate Chamber..if you want below functions to work True -Heated PrintBed Temperature (Celcius): 60.0 -Turn print Bed Heater Off at Shut Down True -Turn Extruder Heater Off at Shut Down True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/clairvoyance.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/clairvoyance.csv deleted file mode 100644 index 8aadf4f..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/clairvoyance.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated clairvoyance settings. -_Name Value -WindowPosition 700+0 -Activate Clairvoyance False -Open File to Generate Clairvoyances for -Gcode Program: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/clip.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/clip.csv deleted file mode 100644 index c61adb8..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/clip.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated clip settings. -_Name Value -WindowPosition 700+0 -Open File for Clip -Activate Clip..to clip the extrusion that overlaps when printing perimeters True -Clip Over Perimeter Width adjuster (decrease for bigger gap): 1.0 -Threshold for connecting inner loops (ratio): 2.5 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/comb.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/comb.csv deleted file mode 100644 index 403d19b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/comb.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated comb settings. -_Name Value -WindowPosition 700+0 -Open File for Comb -Activate Comb if you cant stop the extruder stringing by retraction -it will avoid moving over loops so the strings will be there -but not visible anymore. -Comb bends the extruder travel paths around holes in the slices, to avoid stringing. -so any start up ooze will be inside the shape. True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/comment.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/comment.csv deleted file mode 100644 index c140205..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/comment.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated comment settings. -_Name Value -WindowPosition 700+0 -Activate Comment False -Open File to Write Comments for diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/cool.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/cool.csv deleted file mode 100644 index ed931a0..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/cool.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated cool settings. -_Name Value -WindowPosition 700+0 -Open File for Cool -Activate Cool.. but use with a fan! False -Use Cool if layer takes shorter than(seconds): 10.0 -Turn Fan On at Beginning True -Turn Fan Off at Ending True -Execute when Cool starts: cool_start.gmc -Execute when Cool ends: cool_end.gmc -Orbiting around Object False -Slow Down during print True -Maximum Cool (Celcius): 2.0 -Bridge Cool (Celcius): 1.0 -Minimum Orbital Radius (millimeters): 10.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/dimension.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/dimension.csv deleted file mode 100644 index 4c110d3..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/dimension.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated dimension settings. -_Name Value -WindowPosition 700+0 -Open File for Dimension -Activate Volumetric Extrusion (Stepper driven Extruders) True -Filament Diameter (mm): 2.85 -Filament Packing Density (ratio) lower=more extrusion: 1.0 -Retraction Distance (millimeters): 1.0 -Restart Extra Distance (millimeters): 0.0 -Extruder Retraction Speed (mm/s): 15.0 -Force to retract when crossing over spaces True -Minimum Extrusion before Retraction (millimeters): 1.0 -Minimum Travelmove after Retraction (millimeters): 1.0 -in Absolute units (Sprinter, FiveD a.o.) True -in Relative units (Teacup a.o.) False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/export.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/export.csv deleted file mode 100644 index be5764b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/export.csv +++ /dev/null @@ -1,20 +0,0 @@ -Format is tab separated export settings. -_Name Value -WindowPosition 700+0 -Open File for Export -Activate Export True -Add _export to filename (filename_export) True -Also Send Output To: -Do Not Delete Comments False -Delete Crafting Comments False -Delete All Comments True -Do Not Change Output False -gcode_small True -File Extension (gcode): gcode -Name of Replace File: replace.csv -Save Penultimate Gcode False -Archive Used Profile As Zip False -Export Profile Values As CSV File False -Add Profile Name to Filename False -Add Description to Filename False -Add Timestamp to Filename False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/fill.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/fill.csv deleted file mode 100644 index 682b1eb..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/fill.csv +++ /dev/null @@ -1,34 +0,0 @@ -Format is tab separated fill settings. -_Name Value -WindowPosition 700+0 -Open File for Fill -Activate Fill: True -Infill Solidity (ratio): 0.35 -Extrusion Lines extra Spacing (Scaler): 1.0 -Infill Overlap over Perimeter (Scaler): 1.0 -Extra Shells on Alternating Solid Layer (layers): 1 -Extra Shells on Base (layers): 1 -Extra Shells on Sparse Layer (layers): 1 -Fully filled Layers (each top and bottom): 2 -Lower Left True -Nearest False -Infill > Loops > Perimeter False -Infill > Perimeter > Loops False -Loops > Infill > Perimeter False -Loops > Perimeter > Infill False -Perimeter > Infill > Loops False -Perimeter > Loops > Infill True -Line True -Grid Circular False -Grid Hexagonal False -Grid Rectangular False -Diaphragm at every ...th Layer: 100 -Diaphragm Thickness (layers): 0 -Grid Circle Separation over Perimeter Width (ratio): 0.2 -Grid Extra Overlap (ratio): 0.1 -Grid Junction Separation Band Height (layers): 10 -Grid Junction Separation over Octogon Radius At End (ratio): 0.0 -Grid Junction Separation over Octogon Radius At Middle (ratio): 0.0 -Infill Begin Rotation (degrees): 45.0 -Infill Begin Rotation Repeat (layers): 1 -Infill Odd Layer Extra Rotation (degrees): 90.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/home.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/home.csv deleted file mode 100644 index 430a33a..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/home.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated home settings. -_Name Value -WindowPosition 700+0 -Open File for Home -Activate Home ... Not needed True -Name of Homing File: homing.gcode diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/inset.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/inset.csv deleted file mode 100644 index 6c3d57c..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/inset.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated inset settings. -_Name Value -WindowPosition 700+0 -Open File for Inset -Bridge Width Multiplier (ratio): 1.0 -Prefer Loops False -Prefer Perimeter True -Overlap Removal(Scaler): 1.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/interpret.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/interpret.csv deleted file mode 100644 index 76cdc59..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/interpret.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated interpret settings. -_Name Value -WindowPosition 700+0 -Open File for Interpret -Activate Interpret False -Print Interpretion False -Text Program: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/jitter.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/jitter.csv deleted file mode 100644 index 781738d..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/jitter.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated jitter settings. -_Name Value -WindowPosition 700+0 -Open File for Jitter -Activate Jitter to have your perimeter and loop endpoints scattered False -Jitter Over Perimeter Width (ratio): 2.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/lash.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/lash.csv deleted file mode 100644 index 32ccb3b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/lash.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated lash settings. -_Name Value -WindowPosition 700+0 -Open File for Lash -Activate Lash if you have backlash in your axes. -But its better to fix the mechanical problem! False -X Backlash (mm): 0.0 -Y Backlash (mm): 0.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/limit.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/limit.csv deleted file mode 100644 index 9671405..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/limit.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated limit settings. -_Name Value -WindowPosition 700+0 -Open File for Limit -Activate Limit if your Firmware is unable to Limiting your Z-Speed. False -Maximum Initial Feed Rate (mm/s): 5.0 -Maximum Z Feed Rate (mm/s): 5.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/multiply.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/multiply.csv deleted file mode 100644 index 269d53f..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/multiply.csv +++ /dev/null @@ -1,10 +0,0 @@ -Format is tab separated multiply settings. -_Name Value -WindowPosition 700+0 -Open File for Multiply -Activate Multiply: True -Center X (mm): 100.0 -Center Y (mm): 100.0 -Number of Columns (integer): 1 -Number of Rows (integer): 1 -Separation over Perimeter Width (ratio): 15.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/polyfile.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/polyfile.csv deleted file mode 100644 index 6e7d9bb..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/polyfile.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated polyfile settings. -_Name Value -WindowPosition 700+0 -Execute All Unmodified Files in a Directory False -Execute File True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/preface.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/preface.csv deleted file mode 100644 index 4c37dad..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/preface.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated preface settings. -_Name Value -WindowPosition 700+0 -Open File for Preface -Meta: -Name of End File: end.gmc -Name of Start File: start.gmc -Set Positioning to Absolute True -Set Units to Millimeters True -Home before Print False -Reset Extruder before Print True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/raft.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/raft.csv deleted file mode 100644 index 9d64614..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/raft.csv +++ /dev/null @@ -1,38 +0,0 @@ -Format is tab separated raft settings. -_Name Value -WindowPosition 700+0 -Open File for Raft -Activate Raft True -Add Raft, Elevate Nozzle, Orbit: True -None False -Empty Layers Only False -Everywhere True -Exterior Only False -Add support if flatter than (degrees): 50.0 -Cross Hatch instead of Lines False -Interface/Support Lines Density (ratio): 0.25 -Interface/Support Layer Thickness over Layer Thickness: 1.0 -Support Feed Rate mm/sec: 15.0 -Support Flow Rate (scaler): 1.0 -Support Gap over Perimeter Extrusion Width (ratio): 1.0 -Raft/Support extension in (%): 5.0 -Raft/Support extension in(mm): 2.0 -Name of Support End File: support_end.gmc -Name of Support Start File: support_start.gmc -Extra Nozzle clearance over Object(ratio): 0.0 -First Layer Main Feedrate (mm/s): 35.0 -First Layer Perimeter Feedrate (mm/s): 25.0 -First Layer Flow Rate Infill(scaler): 1.0 -First Layer Flow Rate Perimeter(scaler): 1.0 -Interface Layers (integer): 0 -Interface Feed Rate Multiplier (ratio): 1.0 -Interface Flow Rate Multiplier (ratio): 1.0 -Interface Nozzle Lift over Interface Layer Thickness (ratio): 0.45 -Base Layers (integer): 0 -Base Feed Rate Multiplier (ratio): 0.5 -Base Flow Rate Multiplier (ratio): 0.5 -Base Infill Density (ratio): 0.5 -Base Layer Thickness over Layer Thickness: 2.0 -Base Nozzle Lift over Base Layer Thickness (ratio): 0.4 -Initial Circling: False -Infill Overhang over Extrusion Width (ratio): 3.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/scale.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/scale.csv deleted file mode 100644 index a479f8b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/scale.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated scale settings. -_Name Value -WindowPosition 700+0 -Open File for Scale -Activate Scale to finetune print size (try to find the fault somewhere else..): False -XY Plane Scale (ratio): 1.0 -Z Axis Scale (ratio): 1.0 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeinforge.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeinforge.csv deleted file mode 100644 index 5b6f636..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeinforge.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated skeinforge settings. -_Name Value -WindowPosition 1187+2 -Open File for Skeinforge C:/Users/Ahmet/STL/Calibration/ohtest.STL -analyze False -craft True -help False -meta False -profile False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeinforge_analyze.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeinforge_analyze.csv deleted file mode 100644 index 8826bcb..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeinforge_analyze.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated skeinforge analyze settings. -_Name Value -WindowPosition 600+0 -Open File for Analyze -clairvoyance False -comment False -interpret False -skeiniso True -skeinlayer False -statistic False -vectorwrite False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeinforge_craft.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeinforge_craft.csv deleted file mode 100644 index f70ac71..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeinforge_craft.csv +++ /dev/null @@ -1,27 +0,0 @@ -Format is tab separated skeinforge craft settings. -_Name Value -WindowPosition 600+0 -Open File for Craft -bottom False -carve False -chamber False -clip False -comb False -cool False -dimension False -export False -fill False -inset False -jitter False -lash False -limit False -multiply False -preface False -raft True -scale False -skin False -skirt False -speed False -stretch False -temperature False -wipe False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeinforge_help.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeinforge_help.csv deleted file mode 100644 index 6447399..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeinforge_help.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated skeinforge help settings. -_Name Value -WindowPosition 600+0 -Wiki Manual Primary True diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeiniso.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeiniso.csv deleted file mode 100644 index dce1290..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeiniso.csv +++ /dev/null @@ -1,41 +0,0 @@ -Format is tab separated skeiniso settings. -_Name Value -WindowPosition 700+0 -Open File for Skeiniso -Activate Skeiniso True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Axis Rulings True -Band Height (layers): 5 -Bottom Band Brightness (ratio): 0.7 -Bottom Layer Brightness (ratio): 1.0 -From the Bottom False -From the Top True -Draw Arrows False -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 912345678 -Line (index): 7 -Display Line True -View Move False -View Rotate False -Number of Fill Bottom Layers (integer): 1 -Number of Fill Top Layers (integer): 1 -Scale (pixels per millimeter): 15.0 -Screen Horizontal Inset (pixels): 100 -Screen Vertical Inset (pixels): 220 -Show Gcode True -Viewpoint Latitude (degrees): 15.0 -Viewpoint Longitude (degrees): 210.0 -Width of Axis Negative Side (pixels): 2 -Width of Axis Positive Side (pixels): 6 -Width of Fill Bottom Thread (pixels): 2 -Width of Fill Top Thread (pixels): 2 -Width of Infill Thread (pixels): 1 -Width of Loop Thread (pixels): 2 -Width of Perimeter Inside Thread (pixels): 8 -Width of Perimeter Outside Thread (pixels): 8 -Width of Raft Thread (pixels): 1 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeinlayer.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeinlayer.csv deleted file mode 100644 index ae7700f..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skeinlayer.csv +++ /dev/null @@ -1,23 +0,0 @@ -Format is tab separated skeinlayer settings. -_Name Value -WindowPosition 700+0 -Open File for Skeinlayer -Activate Skeinlayer True -Frame List -Animation Line Quickening (ratio): 1.0 -Animation Slide Show Rate (layers/second): 2.0 -Draw Arrows True -Go Around Extruder Off Travel False -Layer (index): 0 -Layer Extra Span (integer): 0 -Line (index): 120 -Display Line True -View Move False -Scale (pixels per millimeter): 25.0 -Screen Horizontal Inset (pixels): 983 -Screen Vertical Inset (pixels): 292 -Show Gcode True -Show Position True -Width of Extrusion Thread (pixels): 3 -Width of Selection Thread (pixels): 6 -Width of Travel Thread (pixels): 1 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skin.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skin.csv deleted file mode 100644 index 9154030..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skin.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skin settings. -_Name Value -WindowPosition 700+0 -Open File for Skin -Activate Skin: this is experimental. -It prints the perimeters and loops only at half the layer height that is specified under carve. False -Clip Over Perimeter Width (scaler): 1.0 -Do Not Skin the first ... Layers: 3 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skirt.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skirt.csv deleted file mode 100644 index 80cd328..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/skirt.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skirt settings. -_Name Value -WindowPosition 700+0 -Open File for Skirt -Activate Skirt: True -Convex: True -Gap over Perimeter Width (ratio): 5.0 -Layers To (index): 3 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/speed.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/speed.csv deleted file mode 100644 index e2685f3..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/speed.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated speed settings. -_Name Value -WindowPosition 700+0 -Open File for Speed -Activate Speed: True -Add Flow Rate: True -Main Feed Rate (mm/s): 60.0 -Main Flow Rate (scaler): 1.0 -Feed Rate ratio for Orbiting move (ratio): 0.5 -Perimeter Feed Rate (mm/s): 30.0 -Perimeter Flow Rate (scaler): 1.0 -Bridge Feed Rate (ratio): 1.0 -Bridge Flow Rate (scaler): 1.0 -Travel Feed Rate (mm/s): 130.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/statistic.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/statistic.csv deleted file mode 100644 index 4a1f127..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/statistic.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated statistic settings. -_Name Value -WindowPosition 700+0 -Activate Statistic True -Machine Time ($/hour): 1.0 -Material ($/kg): 20.0 -Density (kg/m3): 930.0 -Extrusion Diameter over Thickness (ratio): 1.25 -Open File to Generate Statistics for -Print Statistics True -Save Statistics False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/stretch.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/stretch.csv deleted file mode 100644 index 5bc618d..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/stretch.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated stretch settings. -_Name Value -WindowPosition 700+0 -Open File for Stretch -Activate Stretch to correct for diameter shrink in small diameter holes False -Cross Limit Distance Over Perimeter Width (ratio): 5.0 -Loop Stretch Over Perimeter Width (ratio): 0.11 -Path Stretch Over Perimeter Width (ratio): 0.0 -Perimeter Inside Stretch Over Perimeter Width (ratio): 0.32 -Perimeter Outside Stretch Over Perimeter Width (ratio): 0.1 -Stretch From Distance Over Perimeter Width (ratio): 2.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/temperature.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/temperature.csv deleted file mode 100644 index ce2ef6e..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/temperature.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated temperature settings. -_Name Value -WindowPosition 700+0 -Open File for Temperature -Activate Temperature: False -Cooling Rate (Celcius/second): 3.0 -Heating Rate (Celcius/second): 3.0 -Base Temperature (Celcius): 210.0 -Interface Temperature (Celcius): 210.0 -Object First Layer Infill Temperature (Celcius): 210.0 -Object First Layer Perimeter Temperature (Celcius): 210.0 -Object Next Layers Temperature (Celcius): 210.0 -Support Layers Temperature (Celcius): 210.0 -Supported Layers Temperature (Celcius): 210.0 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/vectorwrite.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/vectorwrite.csv deleted file mode 100644 index e03372b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/vectorwrite.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated vectorwrite settings. -_Name Value -WindowPosition 700+0 -Activate Vectorwrite False -Open File to Write Vector Graphics for -Add Loops True -Add Paths True -Add Perimeters True -Layers From (index): 0 -Layers To (index): 912345678 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/wipe.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/wipe.csv deleted file mode 100644 index 2533703..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/extrusion/PLA/wipe.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated wipe settings. -_Name Value -WindowPosition 700+0 -Open File for Wipe -Activate Wipe False -Location Arrival X (mm): 0.0 -Location Arrival Y (mm): 5.0 -Location Arrival Z (mm): 0.0 -Location Departure X (mm): 5.0 -Location Departure Y (mm): 0.0 -Location Departure Z (mm): 0.0 -Location Wipe X (mm): 0.0 -Location Wipe Y (mm): 0.0 -Location Wipe Z (mm): 0.0 -Wipe Period (layers): 33333 diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/milling.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/milling.csv deleted file mode 100644 index 1068866..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/milling.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated milling settings. -_Name Value -WindowPosition 0+400 -Profile Selection: end_mill diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/skeinforge_profile.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/skeinforge_profile.csv deleted file mode 100644 index 48bb0a0..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/skeinforge_profile.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated skeinforge profile settings. -_Name Value -WindowPosition 0+200 -cutting False -extrusion True -milling False -winding False diff --git a/skeinforge/skeinforge_application/sfact_profiles/profiles/winding.csv b/skeinforge/skeinforge_application/sfact_profiles/profiles/winding.csv deleted file mode 100644 index a20384b..0000000 --- a/skeinforge/skeinforge_application/sfact_profiles/profiles/winding.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated winding settings. -_Name Value -WindowPosition 0+400 -Profile Selection: free_wire diff --git a/skeinforge/skeinforge_application/show_skeinforge.sh b/skeinforge/skeinforge_application/show_skeinforge.sh deleted file mode 100644 index 0548ca1..0000000 --- a/skeinforge/skeinforge_application/show_skeinforge.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/python -# -# Script to show the skeinforge dialog. -# -# Usage: set the executable property to true if it isn't already. Then double click the file. -# -import skeinforge -skeinforge.main() diff --git a/skeinforge/skeinforge_application/skeinforge.py b/skeinforge/skeinforge_application/skeinforge.py deleted file mode 100644 index 67a8462..0000000 --- a/skeinforge/skeinforge_application/skeinforge.py +++ /dev/null @@ -1,617 +0,0 @@ -#!/usr/bin/python -""" -This page is in the table of contents. -==Overview== -===Introduction=== -Skeinforge is a GPL tool chain to forge a gcode skein for a model. - -The tool chain starts with carve, which carves the model into layers, then the layers are modified by other tools in turn like fill, comb, tower, raft, stretch, hop, wipe, fillet & export. Each tool automatically gets the gcode from the previous tool. So if you want a carved & filled gcode, call the fill tool and it will call carve, then it will fill and output the gcode. If you want to use all the tools, call export and it will call in turn all the other tools down the chain to produce the gcode file. - -If you do not want a tool after preface to modify the output, deselect the Activate checkbox for that tool. When the Activate checkbox is off, the tool will just hand off the gcode to the next tool without modifying it. - -The skeinforge module provides a single place to call up all the setting dialogs. When the 'Skeinforge' button is clicked, skeinforge calls export, since that is the end of the chain. - -The plugin buttons which are commonly used are bolded and the ones which are rarely used have normal font weight. - -There are also tools which handle settings for the chain, like polyfile. - -The analyze tool calls plugins in the analyze_plugins folder, which will analyze the gcode in some way when it is generated if their Activate checkbox is selected. - -The interpret tool accesses and displays the import plugins. - -The default settings are similar to those on Nophead's machine. A setting which is often different is the 'Layer Thickness' in carve. - -===Command Line Interface=== -To bring up the skeinforge dialog without a file name, type: -python skeinforge_application/skeinforge.py - -Slicing a file from skeinforge_utilities/skeinforge_craft.py, for example: -python skeinforge_application/skeinforge_utilities/skeinforge_craft.py test.stl - -will slice the file and exit. This is the correct option for programs which use skeinforge to only generate a gcode file. - -Slicing a file from skeinforge.py, for example: -python skeinforge_application/skeinforge.py test.stl - -will slice the file and bring up the skeinforge window and the analyze windows and then skeinforge will wait for user input. - -Slicing a file from skeinforge_plugins/craft.py, for example: -python skeinforge_application/skeinforge_plugins/craft.py test.stl - -will slice the file and bring up the analyze windows only and then skeinforge will wait for user input. - -===Contribute=== -You can contribute by helping develop the manual at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge - -There is also a forum thread about how to contribute to skeinforge development at: -http://dev.forums.reprap.org/read.php?12,27562 - -I will only reply to emails from contributors or to complete bug reports. - -===Documentation=== -There is a manual at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge - -There is also documentation is in the documentation folder, in the doc strings for each module and it can be called from the '?' button or the menu or by clicking F1 in each setting dialog. - -A list of other tutorials is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge#Tutorials - -Skeinforge tagged pages on thingiverse can be searched for at: -http://www.thingiverse.com/search?cx=015525747728168968820%3Arqnsgx1xxcw&cof=FORID%3A9&ie=UTF-8&q=skeinforge&sa=Search&siteurl=www.thingiverse.com%2F#944 - -===Fabrication=== -To fabricate a model with gcode and the Arduino you can use the send.py in the fabricate folder. The documentation for it is in the folder as send.html and at: -http://reprap.org/bin/view/Main/ArduinoSend - -Another way is to use an EMC2 or similar computer controlled milling machine, as described in the "ECM2 based repstrap" forum thread at: -http://forums.reprap.org/read.php?1,12143 - -using the M-Apps package, which is at: -http://forums.reprap.org/file.php?1,file=772 - -Another way is to use Zach's ReplicatorG at: -http://replicat.org/ - -There is also an older Processing script at: -http://reprap.svn.sourceforge.net/viewvc/reprap/trunk/users/hoeken/arduino/GCode_Host/ - -Yet another way is to use the reprap host, written in Java, to load and print gcode: -http://dev.www.reprap.org/bin/view/Main/DriverSoftware#Load_GCode - -For jogging, the Metalab group wrote their own exerciser, also in Processing: -http://reprap.svn.sourceforge.net/viewvc/reprap/trunk/users/metalab/processing/GCode_Exerciser/ - -The Metalab group has descriptions of skeinforge in action and their adventures are described at: -http://reprap.soup.io/ - -There is a board about printing issues at: -http://www.bitsfrombytes.com/fora/user/index.php?board=5.0 - -You can buy the Rapman (an improved Darwin) from Bits from Bytes at: -http://www.bitsfrombytes.com/ - -You can buy the Makerbot from Makerbot Industries at: -http://www.makerbot.com/ - -===File Formats=== -An explanation of the gcodes is at: -http://reprap.org/bin/view/Main/Arduino_GCode_Interpreter - -and at: -http://reprap.org/bin/view/Main/MCodeReference - -A gode example is at: -http://forums.reprap.org/file.php?12,file=565 - -The settings are saved as tab separated .csv files in the .skeinforge folder in your home directory. The settings can be set in the tool dialogs. The .csv files can also be edited with a text editor or a spreadsheet program set to separate tabs. - -The Scalable Vector Graphics file produced by vectorwrite can be opened by an SVG viewer or an SVG capable browser like Mozilla: -http://www.mozilla.com/firefox/ - -A good triangle surface format is the GNU Triangulated Surface format, which is supported by Mesh Viewer and described at: -http://gts.sourceforge.net/reference/gts-surfaces.html#GTS-SURFACE-WRITE - -You can export GTS files from Art of Illusion with the Export GNU Triangulated Surface.bsh script in the Art of Illusion Scripts folder. - -STL is an inferior triangle surface format, described at: -http://en.wikipedia.org/wiki/STL_(file_format) - -If you're using an STL file and you can't even carve it, try converting it to a GNU Triangulated Surface file in Art of Illusion. If it still doesn't carve, then follow the advice in the troubleshooting section. - -===Getting Skeinforge=== -The latest version is at: -http://members.axion.net/~enrique/reprap_python_beanshell.zip - -a sometimes out of date version is in the last reprap_python_beanshell.zip attachment in the last post of the Fabmetheus blog at: -http://fabmetheus.blogspot.com/ - -another sometimes out of date version is at: -https://reprap.svn.sourceforge.net/svnroot/reprap/trunk/reprap/miscellaneous/python-beanshell-scripts/ - -===Getting Started=== -For skeinforge to run, install python 2.x on your machine, which is available from: -http://www.python.org/download/ - -To use the settings dialog you'll also need Tkinter, which probably came with the python installation. If it did not, look for it at: -http://www.tcl.tk/software/tcltk/ - -If you want python and Tkinter together on MacOS, you can try: -http://www.astro.washington.edu/users/rowen/ROPackage/Overview.html - -If you want python and Tkinter together on all platforms and don't mind filling out forms, you can try the ActivePython package from Active State at: -http://www.activestate.com/Products/activepython/feature_list.mhtml - -The computation intensive python modules will use psyco if it is available and run about twice as fast. Psyco is described at: -http://psyco.sourceforge.net/index.html - -The psyco download page is: -http://psyco.sourceforge.net/download.html - -Skeinforge imports Stereolithography (.stl) files or GNU Triangulated Surface (.gts) files. If importing an STL file directly doesn't work, an indirect way to import an STL file is by turning it into a GTS file is by using the Export GNU Triangulated Surface script at: -http://members.axion.net/~enrique/Export%20GNU%20Triangulated%20Surface.bsh - -The Export GNU Triangulated Surface script is also in the Art of Illusion folder, which is in the same folder as skeinforge.py. To bring the script into Art of Illusion, drop it into the folder ArtOfIllusion/Scripts/Tools/. Then import the STL file using the STL import plugin in the import submenu of the Art of Illusion file menu. Then from the Scripts submenu in the Tools menu, choose 'Export GNU Triangulated Surface' and select the imported STL shape. Click the 'Export Selected' checkbox and click OK. Once you've created the GTS file, you can turn it into gcode by typing in a shell in the same folder as skeinforge: -> python skeinforge.py - -When the skeinforge dialog pops up, click 'Skeinforge', choose the file which you exported in 'Export GNU Triangulated Surface' and the gcode file will be saved with the suffix '_export.gcode'. - -Or you can turn files into gcode by adding the file name, for example: -> python skeinforge.py Screw Holder Bottom.stl - -===License=== -GNU Affero General Public License -http://www.gnu.org/licenses/agpl.html - -===Motto=== -I may be slow, but I get there in the end. - -===Troubleshooting=== -If there's a bug, try downloading the very latest version because skeinforge is often updated without an announcement. The very latest version is at: -http://members.axion.net/~enrique/reprap_python_beanshell.zip - -If there is still a bug, then first prepare the following files: - -1. stl file -2. pictures explaining the problem -3. your settings (pack the whole .skeinforge directory with all your settings) -4. alterations folder, if you have any active alterations files - -Then zip all the files. - -Second, write a description of the error, send the description and the archive to the developer, enrique ( perez_enrique AT yahoo.com.removethispart ). After a bug fix is released, test the new version and report the results to enrique, whether the fix was successful or not. - -If the dialog window is too big for the screen, on most Linux window managers you can move a window by holding down the Alt key and then drag the window with the left mouse button to get to the off screen widgets. - -If you can't use the graphical interface, you can change the settings for skeinforge by using a text editor or spreadsheet to change the settings in the profiles folder in the .skeinforge folder in your home directory. - -Comments and suggestions are welcome, however, I won't reply unless you are a contributor. Likewise, I will only answer your questions if you contribute to skeinforge in some way. Some ways of contributing to skeinforge are in the contributions thread at: -http://dev.forums.reprap.org/read.php?12,27562 - -You could also contribute articles to demozendium on any topic: -http://fabmetheus.crsndoo.com/wiki/index.php/Main_Page - -If you contribute in a significant way to another open source project, I will consider that also. - -When I answered everyone's questions, eventually I received more questions than I had time to answer, so now I only answer questions from contributors. - -I reserve the right to make any correspondence public. Do not send me any correspondence marked confidential. If you do I will delete it. - - -==Examples== -The following examples forge the STL file Screw Holder.stl. The examples are run in a terminal in the folder which contains Screw Holder.gts and skeinforge.py. - -> python skeinforge.py -This brings up the dialog, after clicking 'Skeinforge', the following is printed: -The exported file is saved as Screw Holder_export.gcode - -> python skeinforge.py Screw Holder.stl -The exported file is saved as Screw Holder_export.gcode - -To run only fill for example, type in the craft_plugins folder which fill is in: -> python fill.py - -""" - -from __future__ import absolute_import -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import settings -from optparse import OptionParser -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -# double circle top infill in skin -# weird missing line on second layer of interfaceRaft -# circle is average radius in circle, cylinder, drill, extrude -# infuse _extrusion -# base xmlelement off xmlatom -# cutting ahmet -# smooth http://hydraraptor.blogspot.com/2010/12/frequency-limit.html _extrusion -# think about changing getOverlapRatio(loop, pointDictionary) < 0.2 to 0.51 -# change topOverBottom in linearbearingexample to pegAngle -# add links download manual svg_writer, add left right arrow keys to layer -# change thickness to height in gear xml -# documentation Retract When Crossing -# document announce convex, http://www.thingiverse.com/thing:7652 -# document clairvoyance, announcement -# maybe in svgReader if loop intersection with previous union else add -# think about http://code.google.com/p/skeinarchiver/ and/or undo -# -# unimportant -# minor outline problem when an end path goes through a path, like in the letter A -# view profile 1 mm thickness -# -# raftPerimeter outset by maximum thickness -# When opening a file for craft I wondered if there is an option to set the file type to .stl as it currently defaults to .xml -# scrollbar/width problem when starting with narrow view like help/meta/profile -# check inset loop for intersection with rotatedLoopLayer.loops -# maybe make vectorwrite prominent, not skeiniso, probably not because it doesn't work on Mac -# move more __file__ -# close, getPillarByLoopLists, addConcave, polymorph original graph section, loop, add step object, add continuous object -# hollow top -# chamber: heated bed off at a layer http://blog.makerbot.com/2011/03/17/if-you-cant-stand-the-heat/ -# packingDensity or density in grid - probably just density -# derivations for shapes -# think about rectangular getVector3RemoveByPre.. -# links in layerTemplate -# del previous, add begin & end if far get actual path -# linearbearingexample 15 x 1 x 2, linearbearingcage -# add date time 11.01.02|12:08 -# polling -# connectionfrom, to, connect, xaxis -# lathe, transform normal in getRemaining, getConnection -# getConnection of some kind like getConnectionVertexes, getConnection -# xml_creation -# voronoi average location intersection looped inset intercircles -# 'fileName, text, repository' commandLineInterface -# delete: text = text.replace(('\nName %sValue\n' % globalSpreadsheetSeparator), ('\n_Name %sValue\n' % globalSpreadsheetSeparator)) -# -# -# multiply to table + boundary bedBound bedWidth bedHeight bedFile.csv -# getNormal, getIsFlat? -# info statistics, procedures, xml if any -# test solid arguments -# combine xmlelement with csvelement using example.csv & geometry.csv, csv _format, _column, _row, _text -# pixel, voxel, surfaxel/boxel, lattice, mesh -# probably not replace getOverlapRatio with getOverlap if getOverlapRatio is never small, always 0.0 -# mesh. for cube, then cyliner, then sphere after lathe -# dimension extrude diameter, density -# thermistor lookup table -# add overview link to crnsdoo index and svg page -# stretch add back addAlong -# import, write, copy examples -# maybe remove default warnings from scale, rotate, translate, transform -# easy helix -# write tool; maybe write one deep -# -# -# tube -# rotor -# coin -# demozendium privacy policy, maybe thumbnail logo -# pymethe -# test translate -# full lathe -# pyramid -# round extrusion ?, fillet -# make html statistics, move statistics to folder -# manipulate solid, maybe manipulate around elements -# boolean loop corner outset -# mechaslab advanced drainage, shingles -# dovetail -# maybe not getNewObject, getNew, addToBoolean -# work out close and radius -# maybe try to get rid of comment if possible -# maybe have add function as well as append for list and string -# maybe move and give geometryOutput to cube, cylinder, sphere -# -# comb -> maybe add back running jump look at outside loops only for jump, find closest points, find slightly away inside points, link -# global simplify pathBetween -# comb documentation -# -# maybe move widen before bottom -# maybe add 1 to max layer input to iso in layer_template.svg -# maybe save all generated_files option -# table to dictionary -# check for last existing then remove unneeded fill code (getLastExistingFillLoops) from euclidean -# remove cool set at end of layer -# add fan on when hot in chamber -# maybe measuring rod -# getLayerThickness from xml -# maybe center for xy plane -# remove comments from clip, bend -# winding into coiling, coil into wind & weave -# later, precision -# documentation -# http://wiki.makerbot.com/configuring-skeinforge -# -# -# remove index from CircleIntersection remove ahead or behind from CircleIntersection _speed -# cache surroundingCarves _speed -# probably not speed up CircleIntersection by performing isWithinCircles before creation _speed -# pixelSet instead of pixelTable for arounds _speed -# -# -# add hook _extrusion -# integral thin width _extrusion -# layer color, for multilayer start http://reprap.org/pub/Main/MultipleMaterialsFiles/legend.xml _extrusion -# maybe double height shells option _extrusion -# maybe raft triple layer base, middle interface with hot loop or ties -# somehow, add pattern to outside, http://blog.makerbot.com/2010/09/03/lampshades/ -# implement acceleration & collinear removal in penultimate viewers _extrusion -# -# rename skeinforge_profile.addListsToCraftTypeRepository to skeinforge_profile.addToCraftTypeRepository after apron -# basic tool -# arch, ceiling -# meta setting, rename setting _setting -# add polish, has perimeter, has cut first layer (False) -# probably not set addedLocation in distanceFeedRate after arc move -# maybe horizontal bridging and/or check to see if the ends are standing on anything -# thin self? check when removing intersecting paths in inset -# maybe later remove isPerimeterPathInSurroundLoops, once there are no weird fill bugs, also change getHorizontalSegmentListsFromLoopLists -# save all analyze viewers of the same name except itself, update help menu self.wikiManualPrimary.setUpdateFunction -# check alterations folder first, if there is something copy it to the home directory, if not check the home directory -# set temperature in temperature -# add links to demozendium in help -# maybe add hop only if long option -# -# -# -# help primary menu item refresh -# add plugin help menu, add craft below menu -# give option of saving when switching profiles -# xml & svg more forgiving, svg make defaults for layerThickness -# option of surrounding lines in display -# maybe add connecting line in display line -# maybe check inset loops to see if they are smaller, but this would be slow -# maybe status bar -# maybe measurement ruler mouse tool -# search rss from blogs, add search links for common materials, combine created on or progress bar with searchable help -# boundaries, center radius z bottom top, alterations file, circular or rectangular, polygon, put cool minimum radius orbits within boundaries, bound.. -# move & rotate model -# possible jitter bug http://cpwebste.blogspot.com/2010/04/hydras-first-print.html -# trial, meta in a grid settings -# maybe interpret svg_convex_mesh -#laminate tool head -#maybe use 5x5 radius search in circle node -#maybe add layer updates in behold, skeinlayer and maybe others -#lathe winding, extrusion and cutting; synonym for rotation or turning, loop angle -# maybe split into source code and documentation sections -# transform plugins, start with sarrus http://www.thingiverse.com/thing:1425 -# maybe make setting backups -# maybe settings in gcode or saved versions -# move skeinforge_utilities to fabmetheus_utilities -# maybe lathe cutting -# maybe lathe extrusion -# maybe lathe millng -# maybe lathe winding & weaving -# -# -# -# pick and place -# search items, search links, choice entry field -# svg triangle mesh, svg polygon mesh -# simulate -#transform -# juricator -# probably not run along sparse infill to avoid stops -#custom inclined plane, inclined plane from model, screw, fillet travel as well maybe -# probably not stretch single isLoop -#maybe much afterwards make congajure multistep view -#maybe stripe although model colors alone can handle it -#stretch fiber around shape, maybe modify winding for asymmetric shapes -#multiple heads around edge -#maybe add rarely used tool option -#angle shape for overhang extrusions -#maybe m111? countdown -#first time tool tip -#individual tool tip to place in text -# maybe try to simplify raft layer start -# maybe make temp directory -# maybe carve aoi xml testing and check xml gcode -# maybe cross hatch support polishing??? -# maybe print svg view from current layer or zero layer in single view -# maybe check if tower is picking the nearest island -# maybe combine skein classes in fillet -# maybe isometric svg option - -#Manual -#10,990 -#11,1776,786 -#12,3304,1528 -#1,4960,1656 -#2, 7077,2117 -#3, 9598,2521 -#4 12014,2305 -#5 14319,2536 -#6 16855,3226 -#7 20081, 2189 -#8 22270, 2625 -#9 24895, 2967, 98 -#10 27862, 3433, 110 -#11 31295, 3327 -#12 34622 -#85 jan7, 86jan11, 87 jan13, 88 jan15, 91 jan21, 92 jan23, 95 jan30, 98 feb6 -#make one piece electromagnet spool -#stepper rotor with ceramic disk magnet in middle, electromagnet with long thin spool line? -#stepper motor -#make plastic coated thread in vat with pulley -#tensile stuart platform -#kayak -#gear vacuum pump -#gear turbine -#heat engine -#solar power -#sailboat -#yacht -#house -#condo with reflected gardens in between buildings -#medical equipment -#cell counter, etc.. -#pipe clamp lathe -# square tube driller & cutter - -# archihedrongagglevoteindexium -# outline images -# look from top of intersection circle plane to look for next, add a node; tree out until all are stepped on then connect, when more than three intersections are close -# when loading a file, we should have a preview of the part and orientation in space -# second (and most important in my opinion) would be the ability to rotate the part on X/Y/Z axis to chose it's orientation -# third, a routine to detect the largest face and orient the part accordingly. Mat http://reprap.kumy.net/ -# concept, three perpendicular slices to get display spheres -# extend lines around short segment after cross hatched boolean -# concept, donation, postponement, rotate ad network, cached search options -# concept, local ad server, every time the program runs it changes the iamge which all the documentation points to from a pool of ads -# concept, join cross slices, go from vertex to two orthogonal edges, then from edges to each other, if not to a common point, then simplify polygons by removing points which do not change the area much -# concept, each node is fourfold, use sorted intersectionindexes to find close, connect each double sided edge, don't overlap more than two triangles on an edge -# concept, diamond cross section loops -# concept, in file, store polygon mesh and centers -# concept, display spheres or polygons would have original triangle for work plane -# .. then again no point with slices -# concept, filled slices, about 2 mm thick -# concept, rgb color triangle switch to get inside color, color golden ratio on 5:11 slope with a modulo 3 face -# concept, interlaced bricks at corners ( length proportional to corner angle ) -# concept, new links to archi, import links to archi and adds skeinforge tool menu item, back on skeinforge named execute tool is added -# concept, trnsnt -# concept, indexium expand condense remove, single text, pymetheus -# concept, inscribed key silencer -# concept, spreadsheet to python and/or javascript -# concept, range voting for posters, informative, complainer, funny, insightful, rude, spammer, literacy, troll? -# concept, intermittent cloud with multiple hash functions - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = """ -Adrian Bowyer -Brendan Erwin -Greenarrow -Ian England -John Gilmore -Jonwise -Kyle Corbitt -Michael Duffin -Marius Kintel -Nophead -PJR -Reece.Arnott -Wade -Xsainnz -Zach Hoeken - -Organizations: -Art of Illusion """ -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addToProfileMenu(profileSelection, profileType, repository): - """Add a profile menu.""" - pluginFileNames = skeinforge_profile.getPluginFileNames() - craftTypeName = skeinforge_profile.getCraftTypeName() - pluginModule = skeinforge_profile.getCraftTypePluginModule() - profilePluginSettings = settings.getReadRepository(pluginModule.getNewRepository()) - for pluginFileName in pluginFileNames: - skeinforge_profile.ProfileTypeMenuRadio().getFromMenuButtonDisplay(profileType, pluginFileName, repository, craftTypeName == pluginFileName) - for profileName in profilePluginSettings.profileList.value: - skeinforge_profile.ProfileSelectionMenuRadio().getFromMenuButtonDisplay(profileSelection, profileName, repository, profileName == profilePluginSettings.profileListbox.value) - -def getNewRepository(): - """Get new repository.""" - return SkeinforgeRepository() - -def getPluginFileNames(): - """Get skeinforge plugin fileNames.""" - return archive.getPluginFileNamesFromDirectoryPath(archive.getSkeinforgePluginsPath()) - -def getRadioPluginsAddPluginGroupFrame(directoryPath, importantFileNames, names, repository): - """Get the radio plugins and add the plugin frame.""" - repository.pluginGroupFrame = settings.PluginGroupFrame() - radioPlugins = [] - for name in names: - radioPlugin = settings.RadioPlugin().getFromRadio(name in importantFileNames, repository.pluginGroupFrame.latentStringVar, name, repository, name == importantFileNames[0]) - radioPlugin.updateFunction = repository.pluginGroupFrame.update - radioPlugins.append( radioPlugin ) - defaultRadioButton = settings.getSelectedRadioPlugin(importantFileNames + [radioPlugins[0].name], radioPlugins) - repository.pluginGroupFrame.getFromPath(defaultRadioButton, directoryPath, repository) - return radioPlugins - -def writeOutput(fileName): - """Craft a file, display dialog.""" - repository = getNewRepository() - repository.fileNameInput.value = fileName - repository.execute() - settings.startMainLoopFromConstructor(repository) - - -class SkeinforgeRepository: - """A class to handle the skeinforge settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge.html', self) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Skeinforge', self, '') - self.profileType = settings.MenuButtonDisplay().getFromName('Profile Type: ', self ) - self.profileSelection = settings.MenuButtonDisplay().getFromName('Profile Selection: ', self) - addToProfileMenu( self.profileSelection, self.profileType, self ) - settings.LabelDisplay().getFromName('Search:', self ) - reprapSearch = settings.HelpPage().getFromNameAfterHTTP('members.axion.net/~enrique/search_reprap.html', 'Reprap', self) - skeinforgeSearch = settings.HelpPage().getFromNameAfterHTTP('members.axion.net/~enrique/search_skeinforge.html', 'Skeinforge', self ) - skeinforgeSearch.column += 2 - webSearch = settings.HelpPage().getFromNameAfterHTTP('members.axion.net/~enrique/search_web.html', 'Web', self) - webSearch.column += 4 - versionText = archive.getFileText( archive.getVersionFileName() ) - self.version = settings.LabelDisplay().getFromName('Version: ' + versionText, self) - settings.LabelDisplay().getFromName('', self) - importantFileNames = ['craft', 'profile'] - getRadioPluginsAddPluginGroupFrame(archive.getSkeinforgePluginsPath(), importantFileNames, getPluginFileNames(), self) - self.executeTitle = 'Skeinforge' - self.repositoryDialog = None - - def execute(self): - """Skeinforge button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - skeinforge_craft.writeOutput(fileName) - - def save(self): - """Profile has been saved and profile menu should be updated.""" - self.profileType.removeMenus() - self.profileSelection.removeMenus() - addToProfileMenu(self.profileSelection, self.profileType, self) - self.profileType.addRadiosToDialog(self.repositoryDialog) - self.profileSelection.addRadiosToDialog(self.repositoryDialog) - - -def main(): - """Display the skeinforge dialog.""" - parser = OptionParser() - parser.add_option( - '-p', '--prefdir', help='set path to preference directory', action='store', type='string', dest='preferencesDirectory') - parser.add_option( - '-s', '--start', help='set start file to use', action='store', type='string', dest='startFile') - parser.add_option( - '-e', '--end', help='set end file to use', action='store', type='string', dest='endFile') - parser.add_option( - '-o', '--option', help='set an individual option in the format "module:preference=value"', - action='append', type='string', dest='preferences') - (options, args) = parser.parse_args() - if options.preferencesDirectory: - archive.globalTemporarySettingsPath = options.preferencesDirectory - if options.preferences: - for prefSpec in options.preferences: - (moduleName, prefSpec) = prefSpec.split(':', 1) - (prefName, valueName) = prefSpec.split('=', 1) - settings.addPreferenceOverride(moduleName, prefName, valueName) - sys.argv = [sys.argv[0]] + args - if len( args ) > 0: - writeOutput( ' '.join(args) ) - else: - settings.startMainLoopFromConstructor(getNewRepository()) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/__init__.py b/skeinforge/skeinforge_application/skeinforge_plugins/__init__.py deleted file mode 100644 index 2dc8ddc..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 2 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze.py deleted file mode 100644 index 2fbf8ef..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -This page is in the table of contents. -Analyze is a script to access the plugins which analyze a gcode file. - -The plugin buttons which are commonly used are bolded and the ones which are rarely used have normal font weight. - -==Gcodes== -An explanation of the gcodes is at: -http://reprap.org/bin/view/Main/Arduino_GCode_Interpreter - -and at: -http://reprap.org/bin/view/Main/MCodeReference - -A gode example is at: -http://forums.reprap.org/file.php?12,file=565 - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_analyze -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addToMenu(master, menu, repository, window): - """Add a tool plugin menu.""" - pluginsDirectoryPath = skeinforge_analyze.getPluginsDirectoryPath() - settings.addPluginsParentToMenu(pluginsDirectoryPath, menu, __file__, skeinforge_analyze.getPluginFileNames()) - -def getNewRepository(): - """Get new repository.""" - return skeinforge_analyze.AnalyzeRepository() - -def writeOutput(fileName): - """Analyze a gcode file.""" - repository = getNewRepository() - repository.fileNameInput.value = fileName - repository.execute() - settings.startMainLoopFromConstructor(repository) - - -def main(): - """Display the analyze dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor(getNewRepository()) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/__init__.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/__init__.py deleted file mode 100644 index 1121e8a..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/__init__.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/__init__.py deleted file mode 100644 index 58ec332..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 4 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/display_line.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/display_line.py deleted file mode 100644 index 2f27d56..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/display_line.py +++ /dev/null @@ -1,124 +0,0 @@ -""" -This page is in the table of contents. -Display line is a mouse tool to select and display information about the line. - -When a line is clicked, the line will be selected and information about the line will be displayed. If a gcode line is clicked, the information will be file line count of the line clicked, counting from one, and the line itself. - -When the display line tool is chosen and the canvas has the focus, display line will listen to the arrow keys. Clicking in the canvas gives the canvas the focus, and when the canvas has the focus a thick black border is drawn around the canvas. When the right arrow key is pressed, display line will increase the line index of the layer by one, and change the selection accordingly. If the line index of the layer goes over the index of the last line, the layer index will be increased by one and the new line index will be zero. When the left arrow key is pressed, the index will be decreased. If the line index goes below the index of the first line, the layer index will be decreased by one and the new line index will be at the last line. The up arrow key increases the layer index by one and the down arow key decreases the line index. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from skeinforge_application.skeinforge_plugins.analyze_plugins.analyze_utilities.mouse_tool_base import MouseToolBase -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewMouseTool(): - """Get a new mouse tool.""" - return DisplayLine() - - -class DisplayLine( MouseToolBase ): - """Display the line when it is clicked.""" - def button1( self, event, shift = False ): - """Print line text and connection line.""" - self.destroyEverythingGetFocus() - x = self.canvas.canvasx(event.x) - y = self.canvas.canvasy(event.y) - tags = self.getTagsGivenXY(x, y) - if tags == '': - return - if tags.startswith('colored_line_index:'): - splitLine = tags.split() - coloredLineIndex = int(splitLine[1]) - self.repository.line.value = coloredLineIndex - tags = self.getSelectedColoredLine().displayString - self.drawLineText( complex( float(x), float(y) ), tags ) - - def destroyEverything(self): - """Destroy items.""" - self.canvas.delete('mouse_item') - self.canvas.delete('selection_line') - - def drawLineText( self, location, tags ): - """Draw the line text.""" - self.window.getDrawnLineText( location, 'mouse_item', tags ) - - def drawSelectedColoredLineText(self): - """Draw the selected line and text.""" - selectedColoredLine = self.getSelectedColoredLine() - if len( self.canvas.find_withtag('selection_line') ) < 1 or selectedColoredLine is None: - return - tags = selectedColoredLine.displayString - lineCoordinates = self.canvas.coords( self.canvas.find_withtag('selection_line')[-1] ) - begin = complex( lineCoordinates[0], lineCoordinates[1] ) - end = complex( lineCoordinates[2], lineCoordinates[3] ) - segment = end - begin - segmentLength = abs(segment) - if segmentLength <= 0.0: - return - towardEnd = 0.75 * segment - segmentClockwise = 20.0 * complex( segment.imag, - segment.real ) / segmentLength - location = begin + towardEnd + segmentClockwise - self.drawLineText( location, tags ) - - def getSelectedColoredLine(self): - """Draw the selected line, add it to the items and return the colored line.""" - self.window.cancelTimerResetButtons() - coloredLines = self.window.getColoredLines() - self.repository.line.value = max(0, self.repository.line.value) - if len(coloredLines) < 1: - return None - self.repository.line.value = min(len(coloredLines) - 1, self.repository.line.value) - self.window.setLineButtonsState() - coloredLine = coloredLines[self.repository.line.value] - lineCoordinates = self.canvas.coords(self.window.getDrawnSelectedColoredLine(coloredLine)) - end = complex(lineCoordinates[2], lineCoordinates[3]) - radiusComplex = complex(16.0, 16.0) - upperLeft = end - radiusComplex - lowerRight = end + radiusComplex - self.canvas.create_oval (int(upperLeft.real), int(upperLeft.imag), int(lowerRight.real), int(lowerRight.imag), tags = 'mouse_item') - return coloredLine - - def isSelectionTool(self): - """Return if this mouse tool is a selection tool.""" - return True - - def keyPressDown(self, event): - """The down arrow was pressed.""" - self.destroyEverything() - self.window.setLayerIndex( self.repository.layer.value - 1 ) - - def keyPressLeft(self, event): - """The left arrow was pressed.""" - self.destroyEverything() - self.repository.line.value -= 1 - if self.window.isLineBelowZeroSetLayer(): - return - self.drawSelectedColoredLineText() - - def keyPressRight(self, event): - """The right arrow was pressed.""" - self.destroyEverything() - self.repository.line.value += 1 - if self.window.isLineBeyondListSetLayer(): - return - self.drawSelectedColoredLineText() - - def keyPressUp(self, event): - """The up arrow was pressed.""" - self.destroyEverything() - self.window.setLayerIndex( self.repository.layer.value + 1 ) - - def update(self): - """Update the mouse tool.""" - self.destroyEverything() - self.drawSelectedColoredLineText() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/mouse_tool_base.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/mouse_tool_base.py deleted file mode 100644 index c567b70..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/mouse_tool_base.py +++ /dev/null @@ -1,85 +0,0 @@ -""" -Display line is a mouse tool to display the line index of the line clicked, counting from one, and the line itself. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -class MouseToolBase: - """The mouse tool base class, which does nothing.""" - def button1(self, event): - """The left button was clicked, function.""" - pass - - def buttonRelease1(self, event): - """The left button was released, function.""" - pass - - def destroyEverything(self): - """Destroy items.""" - self.canvas.delete('mouse_item') - - def destroyEverythingGetFocus(self): - """Destroy items and get the focus for the canvas.""" - self.destroyEverything() - self.canvas.focus_set() - - def getReset( self, window ): - """Reset the mouse tool to default.""" - self.setWindowItems( window ) - self.destroyEverything() - return self - - def getTagsGivenXY( self, x, y ): - """Get the tag for the x and y.""" - tags = self.canvas.itemcget( self.canvas.find_closest(x, y), 'tags') - currentEnd = ' current' - if tags.find( currentEnd ) != - 1: - return tags[ : - len( currentEnd ) ] - return tags - - def isSelectionTool(self): - """Return if this mouse tool is a selection tool.""" - return False - - def keyPressDown(self, event): - """The down arrow was pressed.""" - pass - - def keyPressLeft(self, event): - """The left arrow was pressed.""" - pass - - def keyPressReturn(self, event): - """The return key was pressed.""" - pass - - def keyPressRight(self, event): - """The right arrow was pressed.""" - pass - - def keyPressUp(self, event): - """The up arrow was pressed.""" - pass - - def motion( self, event, shift = False ): - """The mouse moved, function.""" - pass - - def setWindowItems( self, window ): - """Set the canvas and items.""" - self.canvas = window.canvas - self.repository = window.repository - self.window = window - - def update(self): - """Update the mouse tool.""" - pass diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/tableau.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/tableau.py deleted file mode 100644 index 466c9d4..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/tableau.py +++ /dev/null @@ -1,773 +0,0 @@ -""" -Tableau has a couple of base classes for analyze viewers. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_plugins.analyze_plugins.analyze_utilities import zoom_in -from skeinforge_application.skeinforge_plugins.analyze_plugins.analyze_utilities import zoom_out -import math -import os - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getGeometricDifference( first, second ): - """Get the geometric difference of the two numbers.""" - return max( first, second ) / min( first, second ) - -def getGridHorizontalFrame(gridPosition): - """Get the grid horizontal object with a frame from the grid position.""" - gridHorizontal = settings.GridHorizontal( 0, 0 ) - gridHorizontal.master = settings.Tkinter.Frame( gridPosition.master, borderwidth = 1, padx = 3, relief = 'raised') - gridHorizontal.master.grid( row = gridPosition.row, column = gridPosition.column, sticky = settings.Tkinter.E ) - return gridHorizontal - -def getIsLayerStart(firstWord, skein, splitLine): - """Determine if the line is the start of a layer.""" - if skein.isThereALayerStartWord: - return firstWord == '(' - if firstWord != 'G1' and firstWord != 'G2' and firstWord != 'G3': - return False - location = gcodec.getLocationFromSplitLine(skein.oldLocation, splitLine) - if location.z - skein.oldZ > 0.1: - skein.oldZ = location.z - return True - return False - -def getLengthMinusOneMinimumOne( elementList ): - """Get the length of the length minus one, minimum one.""" - return max( 1, len( elementList ) - 1 ) - -def getScrollbarCanvasPortion( scrollbar ): - """Get the canvas portion of the scrollbar.""" - scrollbarBeginEnd = scrollbar.get() - return scrollbarBeginEnd[1] - scrollbarBeginEnd[0] - -def setStateNormalDisabled( active, widget ): - """Set the state of the widget to normal if active and disabled if inactive.""" - if active: - widget.config( state = settings.Tkinter.NORMAL ) - else: - widget.config( state = settings.Tkinter.DISABLED ) - - -class ColoredLine: - """A colored index line.""" - def __init__( self, begin, colorName, displayString, end, tagString ): - """Set the color name and corners.""" - self.begin = begin - self.colorName = colorName - self.displayString = displayString - self.end = end - self.tagString = tagString - - def __repr__(self): - """Get the string representation of this colored index line.""" - return '%s, %s, %s, %s' % ( self.colorName, self.begin, self.end, self.tagString ) - - -class ExportCanvasDialog: - """A class to display the export canvas repository dialog.""" - def addPluginToMenu( self, canvas, fileName, menu, name, suffix ): - """Add the display command to the menu.""" - self.canvas = canvas - self.fileName = fileName - self.name = name - self.suffix = suffix - menu.add_command( label = settings.getEachWordCapitalized( self.name ), command = self.display ) - - def display(self): - """Display the export canvas repository dialog.""" - for repositoryDialog in settings.globalRepositoryDialogListTable: - if repositoryDialog.repository.lowerName == self.name: - repositoryDialog.setCanvasFileNameSuffix( self.canvas, self.skein.fileName, self.suffix ) - settings.liftRepositoryDialogs( settings.globalRepositoryDialogListTable[ repositoryDialog ] ) - return - exportCanvasPluginsFolderPath = archive.getAbsoluteFolderPath( os.path.dirname(__file__), 'export_canvas_plugins') - pluginModule = archive.getModuleWithDirectoryPath( exportCanvasPluginsFolderPath, self.name ) - if pluginModule is None: - return None - pluginRepository = pluginModule.getNewRepository() - pluginRepository.setCanvasFileNameSuffix( self.canvas, self.fileName, self.suffix ) - settings.getDisplayedDialogFromConstructor( pluginRepository ) - - -class TableauRepository: - """The viewer base repository class.""" - def addAnimation(self): - """Add the animation settings.""" - self.frameList = settings.FrameList().getFromValue('Frame List', self, [] ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Animation -', self ) - self.animationLineQuickening = settings.FloatSpinUpdate().getFromValue( 0.5, 'Animation Line Quickening (ratio):', self, 4.5, 1.0 ) - self.animationSlideShowRate = settings.FloatSpinUpdate().getFromValue( 1.0, 'Animation Slide Show Rate (layers/second):', self, 5.0, 2.0 ) - settings.LabelSeparator().getFromRepository(self) - - def addScaleScreenSlide(self): - """Add the scale, screen and slide show settings.""" - self.scale = settings.FloatSpinNotOnMenu().getFromValue( 10.0, 'Scale (pixels per millimeter):', self, 50.0, 15.0 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Screen Inset -', self ) - self.screenHorizontalInset = settings.IntSpin().getFromValue( 80, 'Screen Horizontal Inset (pixels):', self, 1000, 100 ) - self.screenVerticalInset = settings.IntSpin().getFromValue( 120, 'Screen Vertical Inset (pixels):', self, 1000, 220 ) - settings.LabelSeparator().getFromRepository(self) - self.showGcode = settings.BooleanSetting().getFromValue('Show Gcode', self, True ) - - def setToDisplaySave(self, event=None): - """Set the setting values to the display, save the new values.""" - for menuEntity in self.menuEntities: - if menuEntity in self.preferences: - menuEntity.setToDisplay() - settings.writeSettings(self) - - -class TableauWindow: - def activateMouseModeTool(self): - """Activate the mouse mode tool.""" - self.repository.setToDisplaySave() - self.canvas.focus_set() - self.createMouseModeTool() - self.mouseTool.update() - - def addCanvasMenuRootScrollSkein(self, repository, skein, suffix, title): - """Add the canvas, menu bar, scroll bar, skein panes, tableau repository, root and skein.""" - self.imagesDirectoryPath = archive.getFabmetheusUtilitiesPath('images') - self.movementTextID = None - self.mouseInstantButtons = [] - self.photoImages = {} - self.repository = repository - self.root = settings.Tkinter.Tk() - self.gridPosition = settings.GridVertical(0, 1) - self.gridPosition.master = self.root - self.highlightThickness = 3 - self.root.title(os.path.basename(skein.fileName) + ' - ' + title) - self.rulingExtent = 24 - self.rulingTargetSeparation = 150.0 - self.screenSize = skein.screenSize - self.skein = skein - self.skeinPanes = skein.skeinPanes - self.suffix = suffix - self.timerID = None - repository.animationSlideShowRate.value = max(repository.animationSlideShowRate.value, 0.01) - repository.animationSlideShowRate.value = min(repository.animationSlideShowRate.value, 85.0) - repository.drawArrows.setUpdateFunction(self.setWindowToDisplaySaveUpdate) - repository.goAroundExtruderOffTravel.setUpdateFunction(self.setWindowToDisplaySavePhoenixUpdate) - repository.layerExtraSpan.setUpdateFunction(self.setWindowToDisplaySaveUpdate) - repository.showGcode.setUpdateFunction(self.setWindowToDisplaySaveUpdate) - repository.widthOfSelectionThread.setUpdateFunction(self.setWindowToDisplaySaveUpdate) - repository.widthOfTravelThread.setUpdateFunction(self.setWindowToDisplaySaveUpdate) - repository.window = self - for menuRadio in repository.mouseMode.menuRadios: - fileName = menuRadio.name.lower() - fileName = fileName.replace(' ', '_') + '.ppm' - menuRadio.mouseButton = self.getPhotoButtonGridIncrement(menuRadio.invoke, fileName, self.gridPosition) - self.gridPosition = settings.GridHorizontal(2, 99) - self.gridPosition.master = self.root - self.gcodeStringVar = settings.Tkinter.StringVar(self.root) - self.gcodeLabel = settings.Tkinter.Label(self.root, anchor = settings.Tkinter.W, textvariable = self.gcodeStringVar) - self.gcodeLabel.grid(row = 0, column = 5, columnspan = 93, sticky = settings.Tkinter.W) - from fabmetheus_utilities.hidden_scrollbar import HiddenScrollbar - self.xScrollbar = HiddenScrollbar(self.root, orient = settings.Tkinter.HORIZONTAL) - self.xScrollbar.grid(row = 98, column = 2, columnspan = 96, sticky = settings.Tkinter.E + settings.Tkinter.W) - self.yScrollbar = HiddenScrollbar(self.root) - self.yScrollbar.grid(row = 2, rowspan = 96, column = 99, sticky = settings.Tkinter.N + settings.Tkinter.S) - self.canvasHeight = self.root.winfo_screenheight() - repository.screenVerticalInset.value - self.canvasWidth = self.root.winfo_screenwidth() - repository.screenHorizontalInset.value - scrollRegionBoundingBox = (0, 0, int(skein.screenSize.real), int(skein.screenSize.imag)) - self.canvas = settings.Tkinter.Canvas(self.root, highlightthickness = self.highlightThickness, width = self.canvasWidth, height = self.canvasHeight, scrollregion = scrollRegionBoundingBox) - self.canvas.grid(row = 2, rowspan = 96, column = 2, columnspan = 96, sticky = settings.Tkinter.E + settings.Tkinter.W + settings.Tkinter.N + settings.Tkinter.S) - self.fileHelpMenuBar = settings.FileHelpMenuBar(self.root) - self.exportMenu = settings.Tkinter.Menu(self.fileHelpMenuBar.fileMenu, tearoff = 0) - self.fileHelpMenuBar.fileMenu.add_cascade(label = 'Export', menu = self.exportMenu, underline = 0) - exportCanvasPluginsFolderPath = archive.getAbsoluteFolderPath(os.path.dirname(__file__), 'export_canvas_plugins') - exportCanvasPluginFileNames = archive.getPluginFileNamesFromDirectoryPath(exportCanvasPluginsFolderPath) - for exportCanvasPluginFileName in exportCanvasPluginFileNames: - ExportCanvasDialog().addPluginToMenu(self.canvas, skein.fileName, self.exportMenu, exportCanvasPluginFileName, suffix) - self.fileHelpMenuBar.fileMenu.add_separator() - self.fileHelpMenuBar.completeMenu(self.close, repository, self.save, self) - - def addLayer( self, gridPosition ): - """Add the layer frame items.""" - self.diveButton = self.getPhotoButtonGridIncrement( self.dive, 'dive.ppm', gridPosition ) - self.soarButton = self.getPhotoButtonGridIncrement( self.soar, 'soar.ppm', gridPosition ) - gridPosition.increment() - settings.Tkinter.Label( gridPosition.master, text = 'Layer:').grid( row = gridPosition.row, column = gridPosition.column, sticky = settings.Tkinter.W ) - gridPosition.increment() - self.limitIndex() - self.layerEntry = settings.Tkinter.Spinbox( gridPosition.master, command = self.layerEntryReturnPressed, from_ = 0, increment = 1, to = getLengthMinusOneMinimumOne( self.skeinPanes ) ) - self.layerEntry.bind('', self.layerEntryReturnPressed ) - self.layerEntry.grid( row = gridPosition.row, column = gridPosition.column, sticky = settings.Tkinter.W ) - - def addLine( self, gridPosition ): - """Add the line frame items.""" - self.lineDiveButton = self.getPhotoButtonGridIncrement( self.lineDive, 'dive.ppm', gridPosition ) - self.lineSoarButton = self.getPhotoButtonGridIncrement( self.lineSoar, 'soar.ppm', gridPosition ) - gridPosition.increment() - settings.Tkinter.Label( gridPosition.master, text = 'Line:').grid( row = gridPosition.row, column = gridPosition.column, sticky = settings.Tkinter.W ) - gridPosition.increment() - self.lineEntry = settings.Tkinter.Spinbox( gridPosition.master, command = self.lineEntryReturnPressed, from_ = 0, increment = 1, to = getLengthMinusOneMinimumOne( self.getColoredLines() ) ) - self.lineEntry.bind('', self.lineEntryReturnPressed ) - self.lineEntry.grid( row = gridPosition.row, column = gridPosition.column, sticky = settings.Tkinter.W ) - - def addMouseInstantTool( self, fileName, gridPosition, mouseInstantTool ): - """Add the mouse instant tool and derived photo button.""" - mouseInstantTool.getReset(self) - photoButton = self.getPhotoButtonGridIncrement( mouseInstantTool.click, fileName, gridPosition ) - mouseInstantTool.mouseButton = photoButton - self.mouseInstantButtons.append( photoButton ) - - def addMouseToolsBind(self): - """Add the mouse tool and bind button one clicked, button one released and motion.""" - self.xScrollbar.config( command = self.relayXview ) - self.yScrollbar.config( command = self.relayYview ) - self.canvas['xscrollcommand'] = self.xScrollbar.set - self.canvas['yscrollcommand'] = self.yScrollbar.set - settings.CloseListener( self, self.destroyAllDialogWindows ).listenToWidget( self.canvas ) - self.canvasScreenCenter = 0.5 * complex( float( self.canvasWidth ) / float( self.screenSize.real ), float( self.canvasHeight ) / float( self.screenSize.imag ) ) - self.addPhotoImage('stop.ppm', self.gridPosition ) - self.gridPosition.increment() - self.addLayer( getGridHorizontalFrame( self.gridPosition ) ) - self.gridPosition.increment() - self.addLine( getGridHorizontalFrame( self.gridPosition ) ) - self.gridPosition.increment() - self.addScale( getGridHorizontalFrame( self.gridPosition ) ) - self.gridPosition = settings.GridVertical( self.gridPosition.columnStart + 1, self.gridPosition.row ) - self.gridPosition.master = self.root - for name in self.repository.frameList.value: - entity = self.getEntityFromName( name ) - if entity is not None: - self.gridPosition.incrementGivenNumberOfColumns(3) - entity.addToDialog( getGridHorizontalFrame( self.gridPosition ) ) - for menuRadio in self.repository.mouseMode.menuRadios: - menuRadio.mouseTool = menuRadio.getNewMouseToolFunction().getReset(self) - self.mouseTool = menuRadio.mouseTool - self.createMouseModeTool() - self.canvas.bind('', self.button1) - self.canvas.bind('', self.buttonRelease1) - self.canvas.bind('', self.setInsetToCanvas) - self.canvas.bind('', self.keyPressDown) - self.canvas.bind('', self.keyPressLeft) - self.canvas.bind('', self.keyPressRight) - self.canvas.bind('', self.keyPressUp) - self.canvas.bind('', self.motion) - self.canvas.bind('', self.keyPressReturn) - self.canvas.bind('', self.shiftButtonRelease1) - self.canvas.bind('', self.shiftMotion) - self.layerEntry.bind('', self.cancelTimer) - self.root.grid_columnconfigure(44, weight = 1) - self.root.grid_rowconfigure(44, weight = 1) - self.resetPeriodicButtonsText() - self.repository.animationLineQuickening.setUpdateFunction( self.repository.setToDisplaySave ) - self.repository.animationSlideShowRate.setUpdateFunction( self.repository.setToDisplaySave ) - self.repository.screenHorizontalInset.setUpdateFunction( self.redisplayWindowUpdate ) - self.repository.screenVerticalInset.setUpdateFunction( self.redisplayWindowUpdate ) - rankZeroSeperation = self.getRulingSeparationWidthPixels( 0 ) - zoom = self.rulingTargetSeparation / rankZeroSeperation - self.rank = euclidean.getRank( zoom ) - rankTop = self.rank + 1 - seperationBottom = self.getRulingSeparationWidthPixels( self.rank ) - seperationTop = self.getRulingSeparationWidthPixels( rankTop ) - bottomDifference = getGeometricDifference( self.rulingTargetSeparation, seperationBottom ) - topDifference = getGeometricDifference( self.rulingTargetSeparation, seperationTop ) - if topDifference < bottomDifference: - self.rank = rankTop - self.rulingSeparationWidthMillimeters = euclidean.getIncrementFromRank( self.rank ) - self.canvas.focus_set() - - def addPhotoImage( self, fileName, gridPosition ): - """Get a PhotoImage button, grid the button and increment the grid position.""" - photoImage = None - try: - photoImage = settings.Tkinter.PhotoImage( file = os.path.join( self.imagesDirectoryPath, fileName ), master = gridPosition.master ) - except: - print('Image %s was not found in the images directory, so a text button will be substituted.' % fileName ) - untilDotFileName = archive.getUntilDot(fileName) - self.photoImages[ untilDotFileName ] = photoImage - return untilDotFileName - - def addScale( self, gridPosition ): - """Add the line frame items.""" - self.addMouseInstantTool('zoom_out.ppm', gridPosition, zoom_out.getNewMouseTool() ) - self.addMouseInstantTool('zoom_in.ppm', gridPosition, zoom_in.getNewMouseTool() ) - gridPosition.increment() - settings.Tkinter.Label( gridPosition.master, text = 'Scale:').grid( row = gridPosition.row, column = gridPosition.column, sticky = settings.Tkinter.W ) - gridPosition.increment() - self.scaleEntry = settings.Tkinter.Spinbox( gridPosition.master, command = self.scaleEntryReturnPressed, from_ = 10.0, increment = 5.0, to = 100.0 ) - self.scaleEntry.bind('', self.scaleEntryReturnPressed ) - self.scaleEntry.grid( row = gridPosition.row, column = gridPosition.column, sticky = settings.Tkinter.W ) - - def addSettingsMenuSetWindowGeometry( self, center ): - """Add the settings menu, center the scroll region, update, and set the window geometry.""" - self.settingsMenu = settings.Tkinter.Menu( self.fileHelpMenuBar.menuBar, tearoff = 0 ) - self.fileHelpMenuBar.addMenuToMenuBar( 'Settings', self.settingsMenu ) - settings.addMenuEntitiesToMenuFrameable( self.settingsMenu, self.repository.menuEntities ) - self.relayXview( settings.Tkinter.MOVETO, center.real - self.canvasScreenCenter.real ) - self.relayYview( settings.Tkinter.MOVETO, center.imag - self.canvasScreenCenter.imag ) - self.root.withdraw() - self.root.update_idletasks() - movedGeometryString = '%sx%s+%s' % ( self.root.winfo_reqwidth(), self.root.winfo_reqheight(), '0+0') - self.root.geometry( movedGeometryString ) - - def button1(self, event): - """The button was clicked.""" - self.mouseTool.button1(event) - - def buttonRelease1(self, event): - """The button was released.""" - self.mouseTool.buttonRelease1(event) - - def cancel(self, event=None): - """Set all entities to their saved state.""" - settings.cancelRepository(self.repository) - - def cancelTimer(self, event=None): - """Cancel the timer and set it to none.""" - if self.timerID is not None: - self.canvas.after_cancel(self.timerID) - self.timerID = None - - def cancelTimerResetButtons(self): - """Cancel the timer and set it to none.""" - self.cancelTimer() - self.resetPeriodicButtonsText() - - def close(self, event=None): - """The dialog was closed.""" - try: - self.root.after( 1, self.root.destroy ) # to get around 'Font Helvetica -12 still in cache.' segmentation bug, instead of simply calling self.root.destroy() - except: - pass - - def createMouseModeTool(self): - """Create the mouse mode tool.""" - self.destroyMouseToolRaiseMouseButtons() - for menuRadio in self.repository.mouseMode.menuRadios: - if menuRadio.value: - self.mouseTool = menuRadio.mouseTool - menuRadio.mouseButton['relief'] = settings.Tkinter.SUNKEN - - def destroyAllDialogWindows(self): - """Destroy all the dialog windows.""" - settings.writeSettings(self.repository) - return - for menuEntity in self.repository.menuEntities: - lowerName = menuEntity.name.lower() - if lowerName in settings.globalRepositoryDialogListTable: - globalRepositoryDialogValues = settings.globalRepositoryDialogListTable[ lowerName ] - for globalRepositoryDialogValue in globalRepositoryDialogValues: - settings.quitWindow( globalRepositoryDialogValue.root ) - - def destroyMouseToolRaiseMouseButtons(self): - """Destroy the mouse tool and raise the mouse buttons.""" - self.mouseTool.destroyEverything() - for menuRadio in self.repository.mouseMode.menuRadios: - menuRadio.mouseButton['relief'] = settings.Tkinter.RAISED - for mouseInstantButton in self.mouseInstantButtons: - mouseInstantButton['relief'] = settings.Tkinter.RAISED - - def dive(self): - """Dive, go down periodically.""" - oldDiveButtonText = self.diveButton['text'] - self.cancelTimerResetButtons() - if oldDiveButtonText == 'stop': - return - self.diveCycle() - - def diveCycle(self): - """Start the dive cycle.""" - self.setLayerIndex(self.repository.layer.value - 1) - if self.repository.layer.value < 1: - self.resetPeriodicButtonsText() - return - self.setButtonImageText( self.diveButton, 'stop') - self.timerID = self.canvas.after( self.getSlideShowDelay(), self.diveCycle ) - - def getAnimationLineDelay( self, coloredLine ): - """Get the animation line delay in milliseconds.""" -# maybe later, add animation along line -# nextLayerIndex = self.repository.layer.value -# nextLineIndex = self.repository.line.value + 1 -# coloredLinesLength = len( self.getColoredLines() ) -# self.skein.feedRateMinute -# if nextLineIndex >= coloredLinesLength: -# if nextLayerIndex + 1 < len( self.skeinPanes ): -# nextLayerIndex += 1 -# nextLineIndex = 0 -# else: -# nextLineIndex = self.repository.line.value - splitLine = gcodec.getSplitLineBeforeBracketSemicolon( coloredLine.displayString ) - self.skein.feedRateMinute = gcodec.getFeedRateMinute( self.skein.feedRateMinute, splitLine ) - feedRateSecond = self.skein.feedRateMinute / 60.0 - coloredLineLength = abs( coloredLine.end - coloredLine.begin ) / self.repository.scale.value - duration = coloredLineLength / feedRateSecond - animationLineDelay = int( round( 1000.0 * duration / self.repository.animationLineQuickening.value ) ) - return max( animationLineDelay, 1 ) - - def getDrawnLineText( self, location, tags, text ): - """Get the line text drawn on the canvas.""" - anchorTowardCenter = settings.Tkinter.N - if location.imag > float( self.canvasHeight ) * 0.1: - anchorTowardCenter = settings.Tkinter.S - if location.real > float( self.canvasWidth ) * 0.7: - anchorTowardCenter += settings.Tkinter.E - else: - anchorTowardCenter += settings.Tkinter.W - return self.canvas.create_text( int( location.real ), int( location.imag ), anchor = anchorTowardCenter, tags = tags, text = text ) - - def getEntityFromName(self, name): - """Get the entity of the given name.""" - for entity in self.repository.displayEntities: - if entity.name == name: - return entity - return None - - def getPhotoButtonGridIncrement( self, commandFunction, fileName, gridPosition ): - """Get a PhotoImage button, grid the button and increment the grid position.""" - gridPosition.increment() - untilDotFileName = self.addPhotoImage( fileName, gridPosition ) - photoImage = self.photoImages[ untilDotFileName ] - photoButton = settings.Tkinter.Button( gridPosition.master, activebackground = 'black', activeforeground = 'white', command = commandFunction, text = untilDotFileName ) - if photoImage is not None: - photoButton['image'] = photoImage - photoButton.grid( row = gridPosition.row, column = gridPosition.column, sticky = settings.Tkinter.W ) - return photoButton - - def getRoundedRulingText( self, extraDecimalPlaces, number ): - """Get the rounded ruling text.""" - rulingText = euclidean.getRoundedToPlacesString( extraDecimalPlaces - math.floor( math.log10( self.rulingSeparationWidthMillimeters ) ), number ) - if self.rulingSeparationWidthMillimeters < .99: - return rulingText - if rulingText[ - len('.0') : ] == '.0': - return rulingText[ : - len('.0') ] - return rulingText - - def getRulingSeparationWidthPixels( self, rank ): - """Get the separation width in pixels.""" - return euclidean.getIncrementFromRank( rank ) * self.skein.scale - - def getScrollPaneCenter(self): - """Get the center of the scroll pane.""" - return self.getScrollPaneFraction() + self.canvasScreenCenter - - def getScrollPaneFraction(self): - """Get the scroll pane top left.""" - return complex( self.xScrollbar.get()[0], self.yScrollbar.get()[0] ) - - def getSlideShowDelay(self): - """Get the slide show delay in milliseconds.""" - slideShowDelay = int( round( 1000.0 / self.repository.animationSlideShowRate.value ) ) - return max( slideShowDelay, 1 ) - - def getUpdateSkeinPanes(self): - """Get the update skein panes.""" - layerPlusExtraSpan = self.repository.layer.value + self.repository.layerExtraSpan.value - layersFrom = max( 0, min( self.repository.layer.value, layerPlusExtraSpan ) ) - layersTo = min( len( self.skeinPanes ), max( self.repository.layer.value, layerPlusExtraSpan ) + 1 ) - return self.skeinPanes[ layersFrom : layersTo ] - - def isLineBelowZeroSetLayer(self): - """Determine if the line index is below zero, and if so set the layer index.""" - if self.repository.line.value >= 0: - return False - self.repository.line.value = 0 - if self.repository.layer.value > 0: - self.setLayerIndex( self.repository.layer.value - 1 ) - return True - return False - - def isLineBeyondListSetLayer(self): - """Determine if the line index is beyond the end of the list, and if so set the layer index.""" - coloredLinesLength = len( self.getColoredLines() ) - if self.repository.line.value < coloredLinesLength: - return False - self.repository.line.value = coloredLinesLength - 1 - if self.repository.layer.value < len( self.skeinPanes ) - 1: - self.setLayerIndex( self.repository.layer.value + 1 ) - return True - return False - - def keyPressDown(self, event): - """The down arrow was pressed.""" - self.mouseTool.keyPressDown(event) - - def keyPressLeft(self, event): - """The left arrow was pressed.""" - self.mouseTool.keyPressLeft(event) - - def keyPressReturn(self, event): - """The return key was pressed.""" - self.mouseTool.keyPressReturn(event) - - def keyPressRight(self, event): - """The right arrow was pressed.""" - self.mouseTool.keyPressRight(event) - - def keyPressUp(self, event): - """The up arrow was pressed.""" - self.mouseTool.keyPressUp(event) - - def layerEntryReturnPressed(self, event=None): - """The layer index entry return was pressed.""" - self.setLayerIndex( int( self.layerEntry.get() ) ) - - def limitIndex(self): - """Limit the index so it is not below zero or above the top.""" - self.repository.layer.value = max( 0, self.repository.layer.value ) - self.repository.layer.value = min( len( self.skeinPanes ) - 1, self.repository.layer.value ) - - def limitIndexSetArrowMouseDeleteCanvas(self): - """Limit the index, set the arrow type, and delete all the canvas items.""" - self.limitIndex() - self.arrowType = None - if self.repository.drawArrows.value: - self.arrowType = 'last' - self.canvas.delete( settings.Tkinter.ALL ) - - def lineEntryReturnPressed(self, event=None): - """The line index entry return was pressed.""" - self.repository.line.value = int( self.lineEntry.get() ) - if self.isLineBelowZeroSetLayer(): - return - if self.isLineBeyondListSetLayer(): - return - self.cancelTimerResetButtons() - self.updateMouseToolIfSelection() - self.setLineButtonsState() - - def lineDive(self): - """Line dive, go down periodically.""" - oldLineDiveButtonText = self.lineDiveButton['text'] - self.cancelTimerResetButtons() - if oldLineDiveButtonText == 'stop': - return - self.lineDiveCycle() - - def lineDiveCycle(self): - """Start the line dive cycle.""" - self.cancelTimer() - self.repository.line.value -= 1 - if self.repository.line.value < 0: - self.repository.line.value = 0 - if self.repository.layer.value == 0: - self.resetPeriodicButtonsText() - self.setLineButtonsState() - return - self.setLayerIndex( self.repository.layer.value - 1 ) - else: - self.updateMouseToolIfSelection() - self.setLineButtonsState() - self.setButtonImageText( self.lineDiveButton, 'stop') - coloredLine = self.getColoredLines()[ self.repository.line.value ] - self.timerID = self.canvas.after( self.getAnimationLineDelay( coloredLine ), self.lineDiveCycle ) - - def lineSoar(self): - """Line soar, go up periodically.""" - oldLineSoarButtonText = self.lineSoarButton['text'] - self.cancelTimerResetButtons() - if oldLineSoarButtonText == 'stop': - return - self.lineSoarCycle() - - def lineSoarCycle(self): - """Start the line soar cycle.""" - self.cancelTimer() - self.repository.line.value += 1 - coloredLinesLength = len( self.getColoredLines() ) - if self.repository.line.value >= coloredLinesLength: - self.repository.line.value = coloredLinesLength - 1 - if self.repository.layer.value > len( self.skeinPanes ) - 2: - self.resetPeriodicButtonsText() - self.setLineButtonsState() - return - self.setLayerIndex( self.repository.layer.value + 1 ) - else: - self.updateMouseToolIfSelection() - self.setLineButtonsState() - self.setButtonImageText( self.lineSoarButton, 'stop') - coloredLine = self.getColoredLines()[ self.repository.line.value ] - self.timerID = self.canvas.after( self.getAnimationLineDelay( coloredLine ), self.lineSoarCycle ) - - def motion(self, event): - """The mouse moved.""" - self.mouseTool.motion(event) - - def phoenixUpdate(self): - """Update the skein, and deiconify a new window and destroy the old.""" - self.updateNewDestroyOld( self.getScrollPaneCenter() ) - - def relayXview( self, *args ): - """Relay xview changes.""" - self.canvas.xview( *args ) - - def relayYview( self, *args ): - """Relay yview changes.""" - self.canvas.yview( *args ) - - def resetPeriodicButtonsText(self): - """Reset the text of the periodic buttons.""" - self.setButtonImageText( self.diveButton, 'dive') - self.setButtonImageText( self.soarButton, 'soar') - self.setButtonImageText( self.lineDiveButton, 'dive') - self.setButtonImageText( self.lineSoarButton, 'soar') - - def redisplayWindowUpdate(self, event=None): - """Deiconify a new window and destroy the old.""" - self.repository.setToDisplaySave() - self.getCopy().updateDeiconify( self.getScrollPaneCenter() ) - self.root.after( 1, self.root.destroy ) # to get around 'Font Helvetica -12 still in cache.' segmentation bug, instead of simply calling self.root.destroy() - - def save(self): - """Set the setting values to the display, save the new values.""" - for menuEntity in self.repository.menuEntities: - if menuEntity in self.repository.preferences: - menuEntity.setToDisplay() - settings.writeSettings(self.repository) - - def scaleEntryReturnPressed(self, event=None): - """The scale entry return was pressed.""" - self.repository.scale.value = float( self.scaleEntry.get() ) - self.phoenixUpdate() - - def setButtonImageText( self, button, text ): - """Set the text of the e periodic buttons.""" - photoImage = self.photoImages[ text ] - if photoImage is not None: - button['image'] = photoImage - button['text'] = text - - def setDisplayLayerIndex(self): - """Set the display of the layer index entry field and buttons.""" - coloredLines = self.getColoredLines() - isAboveFloor = self.repository.layer.value > 0 - isBelowCeiling = self.repository.layer.value < len( self.skeinPanes ) - 1 - setStateNormalDisabled( isAboveFloor, self.diveButton ) - setStateNormalDisabled( isBelowCeiling, self.soarButton ) - self.setLineButtonsState() - settings.setEntryText( self.layerEntry, self.repository.layer.value ) - settings.setEntryText( self.lineEntry, self.repository.line.value ) - settings.setEntryText( self.scaleEntry, self.repository.scale.value ) - self.mouseTool.update() - - def setInsetToCanvas(self, event=None): - """Set the repository insets to the canvas.""" - if self.root.state() != 'normal': - return - excessExtent = self.highlightThickness + self.highlightThickness - screenHorizontalInset = self.repository.screenHorizontalInset - screenVerticalInset = self.repository.screenVerticalInset - oldHorizontalValue = screenHorizontalInset.value - oldVerticalValue = screenVerticalInset.value - screenHorizontalInset.value = self.root.winfo_screenwidth() - self.canvas.winfo_width() + excessExtent - if not self.yScrollbar.visible: - screenHorizontalInset.value += self.yScrollbar.winfo_reqwidth() - screenHorizontalInset.setStateToValue() - screenVerticalInset.value = self.root.winfo_screenheight() - self.canvas.winfo_height() + excessExtent - if not self.xScrollbar.visible: - screenVerticalInset.value += self.xScrollbar.winfo_reqheight() - screenVerticalInset.setStateToValue() - if oldHorizontalValue != screenHorizontalInset.value or oldVerticalValue != screenVerticalInset.value: - self.repository.setToDisplaySave() - - def setLayerIndex( self, layerIndex ): - """Set the layer index.""" - self.cancelTimerResetButtons() - oldLayerIndex = self.repository.layer.value - self.repository.layer.value = layerIndex - self.limitIndex() - coloredLines = self.getColoredLines() - if self.repository.layer.value < oldLayerIndex: - self.repository.line.value = len( coloredLines ) - 1 - self.lineEntry['to'] = getLengthMinusOneMinimumOne( coloredLines ) - if self.repository.layer.value > oldLayerIndex: - self.repository.line.value = 0 - self.lineEntry['to'] = getLengthMinusOneMinimumOne( coloredLines ) - self.update() - - def setLineButtonsState(self): - """Set the state of the line buttons.""" - coloredLines = self.getColoredLines() - if len(coloredLines) < 1: - print('Warning, there are no coloredLines in setLineButtonsState in tableau for the layer:') - print(self.repository.layer.value) - return - isAboveFloor = self.repository.layer.value > 0 - isBelowCeiling = self.repository.layer.value < len( self.skeinPanes ) - 1 - setStateNormalDisabled( isAboveFloor or self.repository.line.value > 0, self.lineDiveButton ) - setStateNormalDisabled( isBelowCeiling or self.repository.line.value < len( coloredLines ) - 1, self.lineSoarButton ) - self.repository.line.value = max(self.repository.line.value, 0) - self.repository.line.value = min(self.repository.line.value, len(coloredLines) - 1) - gcodeString = '' - if self.repository.showGcode.value: - gcodeString = 'Gcode: ' + coloredLines[self.repository.line.value].displayString - self.gcodeStringVar.set(gcodeString) - self.canvas.delete('selection_line') - self.getDrawnSelectedColoredLine(coloredLines[self.repository.line.value]) - settings.setEntryText(self.lineEntry, self.repository.line.value) - - def setWindowNewMouseTool( self, getNewMouseToolFunction, mouseTool ): - """Set the getNewMouseTool function and the update function.""" - mouseTool.getNewMouseToolFunction = getNewMouseToolFunction - mouseTool.setUpdateFunction( self.activateMouseModeTool ) - - def setWindowToDisplaySavePhoenixUpdate(self, event=None): - """Set the setting values to the display, save the new values, then call the update function.""" - self.repository.setToDisplaySave() - self.phoenixUpdate() - - def setWindowToDisplaySaveUpdate(self, event=None): - """Set the setting values to the display, save the new values, then call the update function.""" - self.repository.setToDisplaySave() - self.update() - - def shiftButtonRelease1(self, event): - """The button was released while the shift key was pressed.""" - self.mouseTool.buttonRelease1( event, True ) - - def shiftMotion(self, event): - """The mouse moved.""" - self.mouseTool.motion( event, True ) - - def soar(self): - """Soar, go up periodically.""" - oldSoarButtonText = self.soarButton['text'] - self.cancelTimerResetButtons() - if oldSoarButtonText == 'stop': - return - self.soarCycle() - - def soarCycle(self): - """Start the soar cycle.""" - self.setLayerIndex(self.repository.layer.value + 1) - if self.repository.layer.value > len( self.skeinPanes ) - 2: - self.resetPeriodicButtonsText() - return - self.setButtonImageText( self.soarButton, 'stop') - self.timerID = self.canvas.after( self.getSlideShowDelay(), self.soarCycle ) - - def updateDeiconify( self, center = complex( 0.5, 0.5 ) ): - """Update and deiconify the window.""" - self.addSettingsMenuSetWindowGeometry( center ) - self.update() - self.root.deiconify() - - def updateMouseToolIfSelection(self): - """Update the mouse tool if it is a selection tool.""" - if self.mouseTool is None: - return - if self.mouseTool.isSelectionTool(): - self.mouseTool.update() - - def updateNewDestroyOld( self, scrollPaneCenter ): - """Update and deiconify a window and destroy the old.""" - self.getCopyWithNewSkein().updateDeiconify( scrollPaneCenter ) - self.root.after(1, self.root.destroy) # to get around 'Font Helvetica -12 still in cache.' segmentation bug, instead of simply calling self.root.destroy() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/view_move.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/view_move.py deleted file mode 100644 index 48d3821..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/view_move.py +++ /dev/null @@ -1,83 +0,0 @@ -""" -This page is in the table of contents. -Viewpoint move is a mouse tool to move the viewpoint in the xy plane. - -When the mouse is clicked and dragged on the canvas, viewpoint move will drag the scroll pane accordingly. If the shift key is also pressed, the scroll pane will be moved only in the x or y direction, whichever is largest. - -When the viewpoint move tool is chosen and the canvas has the focus, viewpoint move will listen to the arrow keys. Clicking in the canvas gives the canvas the focus, and when the canvas has the focus a thick black border is drawn around the canvas. When the right arrow key is pressed, viewpoint move will move the scroll pane to the right by a pixel. When the left arrow key is pressed, the scroll pane will be moved a pixel to the left. The up arrow key moves the scroll pane a pixel up and the down arow key moves the scroll pane a pixel down. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from skeinforge_application.skeinforge_plugins.analyze_plugins.analyze_utilities.mouse_tool_base import MouseToolBase -from fabmetheus_utilities import settings - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewMouseTool(): - """Get a new mouse tool.""" - return ViewpointMove() - - -class ViewpointMove( MouseToolBase ): - """Display the line when it is clicked.""" - def button1( self, event, shift = False ): - """Print line text and connection line.""" - self.destroyEverythingGetFocus() - self.buttonOnePressedScreenCoordinate = complex( event.x, event.y ) - self.scrollPaneFraction = self.window.getScrollPaneFraction() - - def buttonRelease1( self, event, shift = False ): - """The left button was released, function.""" - self.destroyEverything() - - def destroyEverything(self): - """Destroy items.""" - self.buttonOnePressedScreenCoordinate = None - - def keyPressDown(self, event): - """The down arrow was pressed.""" - self.setScrollPaneMove( complex( 0.0, 1.0 ) ) - - def keyPressLeft(self, event): - """The left arrow was pressed.""" - self.setScrollPaneMove( complex( - 1.0, 0.0 ) ) - - def keyPressRight(self, event): - """The right arrow was pressed.""" - self.setScrollPaneMove( complex( 1.0, 0.0 ) ) - - def keyPressUp(self, event): - """The up arrow was pressed.""" - self.setScrollPaneMove( complex(0.0, -1.0) ) - - def motion( self, event, shift = False ): - """The mouse moved, function.""" - if self.buttonOnePressedScreenCoordinate is None: - return - motionCoordinate = complex( event.x, event.y ) - relativeMotion = motionCoordinate - self.buttonOnePressedScreenCoordinate - if shift: - if abs( relativeMotion.real ) > abs( relativeMotion.imag ): - relativeMotion = complex( relativeMotion.real, 0.0 ) - else: - relativeMotion = complex( 0.0, relativeMotion.imag ) - self.relativeMove( relativeMotion ) - - def relativeMove( self, relativeMotion ): - """Move the view given the relative motion.""" - relativeScreenMotion = complex( relativeMotion.real / float( self.window.screenSize.real ), relativeMotion.imag / float( self.window.screenSize.imag ) ) - moveTo = self.scrollPaneFraction - relativeScreenMotion - self.window.relayXview( settings.Tkinter.MOVETO, moveTo.real ) - self.window.relayYview( settings.Tkinter.MOVETO, moveTo.imag ) - - def setScrollPaneMove( self, relativeMotion ): - """The up arrow was pressed.""" - self.scrollPaneFraction = self.window.getScrollPaneFraction() - self.relativeMove( relativeMotion ) diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/view_rotate.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/view_rotate.py deleted file mode 100644 index 18eed41..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/view_rotate.py +++ /dev/null @@ -1,201 +0,0 @@ -""" -This page is in the table of contents. -Viewpoint rotate is a mouse tool to rotate the viewpoint around the origin. - -When the mouse is clicked, dragged and released on the canvas, viewpoint rotate will rotate the longitude by the amount the mouse is dragged around the origin. If the mouse is moved towards the origin, the latitude will be increased, so the viewpoint will be closer to the top. If the mouse is moved away from the origin, the latitude will be decreased. If the shift key is also pressed, only the latitude or longitude will be changed, whichever is being changed the most. - -When the viewpoint rotate tool is chosen and the canvas has the focus, viewpoint rotate will listen to the arrow keys. Clicking in the canvas gives the canvas the focus, and when the canvas has the focus a thick black border is drawn around the canvas. When the right arrow key is pressed, viewpoint rotate will increase the preview longitude by one degree. When the left arrow key is pressed, the preview longitude will be decreased. The up arrow key increase the preview latitude by one degree and the down arow decreases the preview latitude. Pressing the key implements the preview. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from skeinforge_application.skeinforge_plugins.analyze_plugins.analyze_utilities.mouse_tool_base import MouseToolBase -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import settings -import math - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getBoundedLatitude( latitude ): - """Get the bounded latitude.later get rounded""" - return round( min( 179.9, max( 0.1, latitude ) ), 1 ) - -def getNewMouseTool(): - """Get a new mouse tool.""" - return ViewpointRotate() - - -class LatitudeLongitude: - """A latitude and longitude.""" - def __init__( self, buttonOnePressedCanvasCoordinate, newCoordinate, skeinWindow, shift ): - """Set the latitude and longitude.""" - buttonOnePressedCentered = skeinWindow.getCenteredScreened( buttonOnePressedCanvasCoordinate ) - buttonOnePressedRadius = abs( buttonOnePressedCentered ) - buttonOnePressedComplexMirror = complex( buttonOnePressedCentered.real, - buttonOnePressedCentered.imag ) - buttonOneReleasedCentered = skeinWindow.getCenteredScreened( newCoordinate ) - buttonOneReleasedRadius = abs( buttonOneReleasedCentered ) - pressedReleasedRotationComplex = buttonOneReleasedCentered * buttonOnePressedComplexMirror - self.deltaLatitude = math.degrees( buttonOneReleasedRadius - buttonOnePressedRadius ) - self.originalDeltaLongitude = math.degrees( math.atan2( pressedReleasedRotationComplex.imag, pressedReleasedRotationComplex.real ) ) - self.deltaLongitude = self.originalDeltaLongitude - if skeinWindow.repository.viewpointLatitude.value > 90.0: - self.deltaLongitude = - self.deltaLongitude - if shift: - if abs( self.deltaLatitude ) > abs( self.deltaLongitude ): - self.deltaLongitude = 0.0 - else: - self.deltaLatitude = 0.0 - self.latitude = getBoundedLatitude( skeinWindow.repository.viewpointLatitude.value + self.deltaLatitude ) - self.longitude = round( ( skeinWindow.repository.viewpointLongitude.value + self.deltaLongitude ) % 360.0, 1 ) - - -class ViewpointRotate( MouseToolBase ): - """Display the line when it is clicked.""" - def button1( self, event, shift = False ): - """Print line text and connection line.""" - self.destroyEverything() - x = self.canvas.canvasx(event.x) - y = self.canvas.canvasy(event.y) - self.buttonOnePressedCanvasCoordinate = complex(x, y) - - def buttonRelease1( self, event, shift = False ): - """The left button was released, function.""" - if self.buttonOnePressedCanvasCoordinate is None: - return - x = self.canvas.canvasx(event.x) - y = self.canvas.canvasy(event.y) - buttonOneReleasedCanvasCoordinate = complex(x, y) - self.moveViewpointGivenCoordinates( buttonOneReleasedCanvasCoordinate, shift, self.buttonOnePressedCanvasCoordinate ) - - def destroyEverything(self): - """Destroy items.""" - self.buttonOnePressedCanvasCoordinate = None - self.keyStartCanvasCoordinate = None - self.relativeLatitude = 0.0 - self.relativeLongitude = 0.5 * math.pi - self.canvas.delete('mouse_item') - - def getMoveCoordinate(self): - """Get the movement coordinate from the class relative latitude and longitude.""" - motionRadius = ( 0.75 + self.relativeLatitude ) * self.window.getCanvasRadius() - return self.window.getScreenComplex( motionRadius * euclidean.getWiddershinsUnitPolar( self.relativeLongitude ) ) - - def keyPressDown(self, event): - """The down arrow was pressed.""" - self.keyPressStart() - self.relativeLatitude -= math.radians(1.0) - self.keyPressMotion() - - def keyPressLeft(self, event): - """The left arrow was pressed.""" - self.keyPressStart() - self.relativeLongitude += math.radians(1.0) - self.keyPressMotion() - - def keyPressMotion(self): - """Move the motion viewpoint for the class key press coordinates.""" - self.motionGivenCoordinates( self.getMoveCoordinate(), False, self.keyStartCanvasCoordinate ) - - def keyPressReturn(self, event): - """The return key was pressed.""" - if self.keyStartCanvasCoordinate is None: - return - self.moveViewpointGivenCoordinates( self.getMoveCoordinate(), False, self.keyStartCanvasCoordinate ) - - def keyPressRight(self, event): - """The right arrow was pressed.""" - self.keyPressStart() - self.relativeLongitude -= math.radians(1.0) - self.keyPressMotion() - - def keyPressStart(self): - """If necessary, destroy everything and calculate the keyStartCanvasCoordinate.""" - if self.keyStartCanvasCoordinate is None: - self.destroyEverything() - self.keyStartCanvasCoordinate = self.window.getScreenComplex( complex( 0.0, 0.75 * self.window.getCanvasRadius() ) ) - - def keyPressUp(self, event): - """The up arrow was pressed.""" - self.keyPressStart() - self.relativeLatitude += math.radians(1.0) - self.keyPressMotion() - - def motion( self, event, shift = False ): - """Move the motion viewpoint if the mouse was moved.""" - if self.buttonOnePressedCanvasCoordinate is None: - return - x = self.canvas.canvasx(event.x) - y = self.canvas.canvasy(event.y) - motionCoordinate = complex(x, y) - self.motionGivenCoordinates( motionCoordinate, shift, self.buttonOnePressedCanvasCoordinate ) - - def motionGivenCoordinates( self, motionCoordinate, shift, startCoordinate ): - """Move the motion viewpoint given the motion coordinates.""" - latitudeLongitude = LatitudeLongitude( startCoordinate, motionCoordinate, self.window, shift ) - viewVectors = euclidean.ProjectiveSpace().getByLatitudeLongitude( latitudeLongitude.latitude, latitudeLongitude.longitude ) - motionCentered = self.window.getCentered( motionCoordinate ) - motionCenteredNormalized = motionCentered / abs( motionCentered ) - buttonOnePressedCentered = self.window.getCentered( startCoordinate ) - buttonOnePressedAngle = math.degrees( math.atan2( buttonOnePressedCentered.imag, buttonOnePressedCentered.real ) ) - buttonOnePressedLength = abs( buttonOnePressedCentered ) - buttonOnePressedCorner = complex( buttonOnePressedLength, buttonOnePressedLength ) - buttonOnePressedCornerBottomLeft = self.window.getScreenComplex( - buttonOnePressedCorner ) - buttonOnePressedCornerUpperRight = self.window.getScreenComplex( buttonOnePressedCorner ) - motionPressedStart = buttonOnePressedLength * motionCenteredNormalized - motionPressedScreen = self.window.getScreenComplex( motionPressedStart ) - motionColorName = '#4B0082' - motionWidth = 9 - self.canvas.delete('mouse_item') - if abs( latitudeLongitude.deltaLongitude ) > 0.0: - self.canvas.create_arc( - buttonOnePressedCornerBottomLeft.real, - buttonOnePressedCornerBottomLeft.imag, - buttonOnePressedCornerUpperRight.real, - buttonOnePressedCornerUpperRight.imag, - extent = latitudeLongitude.originalDeltaLongitude, - start = buttonOnePressedAngle, - outline = motionColorName, - outlinestipple = self.window.motionStippleName, - style = settings.Tkinter.ARC, - tags = 'mouse_item', - width = motionWidth ) - if abs( latitudeLongitude.deltaLatitude ) > 0.0: - self.canvas.create_line( - motionPressedScreen.real, - motionPressedScreen.imag, - motionCoordinate.real, - motionCoordinate.imag, - fill = motionColorName, - arrow = 'last', - arrowshape = self.window.arrowshape, - stipple = self.window.motionStippleName, - tags = 'mouse_item', - width = motionWidth ) - self.window.getDrawnLineText( motionCoordinate, 'mouse_item', 'Latitude: %s, Longitude: %s' % ( round( latitudeLongitude.latitude ), round( latitudeLongitude.longitude ) ) ) - if self.repository.widthOfAxisPositiveSide.value > 0: - self.window.getDrawnColoredLineMotion( self.window.positiveAxisLineX, viewVectors, self.repository.widthOfAxisPositiveSide.value ) - self.window.getDrawnColoredLineMotion( self.window.positiveAxisLineY, viewVectors, self.repository.widthOfAxisPositiveSide.value ) - self.window.getDrawnColoredLineMotion( self.window.positiveAxisLineZ, viewVectors, self.repository.widthOfAxisPositiveSide.value ) - - def moveViewpointGivenCoordinates( self, moveCoordinate, shift, startCoordinate ): - """Move the viewpoint given the move coordinates.""" - if abs( startCoordinate - moveCoordinate ) < 3: - startCoordinate = None - self.canvas.delete('mouse_item') - return - latitudeLongitude = LatitudeLongitude( startCoordinate, moveCoordinate, self.window, shift ) - self.repository.viewpointLatitude.value = latitudeLongitude.latitude - self.repository.viewpointLatitude.setStateToValue() - self.repository.viewpointLongitude.value = latitudeLongitude.longitude - self.repository.viewpointLongitude.setStateToValue() - startCoordinate = None - settings.writeSettings(self.repository) - self.window.update() - self.destroyEverything() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/zoom_in.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/zoom_in.py deleted file mode 100644 index b46dd3d..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/zoom_in.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -This page is in the table of contents. -Zoom in is a mouse tool to zoom in the display at the point where the mouse was clicked, increasing the scale by a factor of two. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from skeinforge_application.skeinforge_plugins.analyze_plugins.analyze_utilities.mouse_tool_base import MouseToolBase -from fabmetheus_utilities import settings - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewMouseTool(): - """Get a new mouse tool.""" - return ZoomIn() - - -class ZoomIn( MouseToolBase ): - """The zoom in mouse tool.""" - def button1( self, event, shift = False ): - """Print line text and connection line.""" - scaleSetting = self.window.repository.scale - scaleSetting.value *= self.getMultiplier() - delta = complex( float(event.x) / float( self.window.screenSize.real ), float(event.y) / float( self.window.screenSize.imag ) ) - self.window.canvasScreenCenter - delta *= 1.0 - 1.0 / self.getMultiplier() - scrollPaneCenter = self.window.getScrollPaneCenter() + delta - self.window.updateNewDestroyOld( scrollPaneCenter ) - - def click(self, event=None): - """Set the window mouse tool to this.""" - self.window.destroyMouseToolRaiseMouseButtons() - self.window.mouseTool = self - self.mouseButton['relief'] = settings.Tkinter.SUNKEN - - def getReset( self, window ): - """Reset the mouse tool to default.""" - self.setWindowItems( window ) - self.mouseButton = None - return self - - def getMultiplier(self): - """Get the scale multiplier.""" - return 2.0 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/zoom_out.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/zoom_out.py deleted file mode 100644 index a3f3902..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/analyze_utilities/zoom_out.py +++ /dev/null @@ -1,29 +0,0 @@ -""" -This page is in the table of contents. -Zoom out is a mouse tool to zoom out the display at the point where the mouse was clicked, decreasing the scale by a factor of two. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from skeinforge_application.skeinforge_plugins.analyze_plugins.analyze_utilities import zoom_in -from fabmetheus_utilities import settings - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewMouseTool(): - """Get a new mouse tool.""" - return ZoomOut() - - -class ZoomOut( zoom_in.ZoomIn ): - """The zoom out mouse tool.""" - def getMultiplier(self): - """Get the scale multiplier.""" - return 0.5 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/clairvoyance.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/clairvoyance.py deleted file mode 100644 index 4cbad4a..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/clairvoyance.py +++ /dev/null @@ -1,123 +0,0 @@ -""" -This page is in the table of contents. -Clairvoyance is a script to open the gcode file with an outside program. - -The clairvoyance manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Clairvoyance - -==Operation== -The default 'Activate Clairvoyance' checkbox is on. When it is on, the functions described below will work when called from the skeinforge toolchain, when it is off, the functions will not be called from the toolchain. The functions will still be called, whether or not the 'Activate Clairvoyance' checkbox is on, when clairvoyance is run directly. - -==Settings== -===Gcode Program=== -Default is webbrowser. - -If the 'Gcode Program' is set to webbrowser, the gcode file will be sent to the default browser to be opened. If the 'Gcode Program' is set to a program name, the gcode file will be sent to that program to be opened. A good gcode viewer is Pleasant3D, at: -http://www.pleasantsoftware.com/developer/pleasant3d/index.shtml - -==Examples== -Below are examples of clairvoyance being used. These examples are run in a terminal in the folder which contains Screw Holder_penultimate.gcode and clairvoyance.py. - -> python clairvoyance.py -This brings up the clairvoyance dialog. - -> python clairvoyance.py Screw Holder_penultimate.gcode -The file is opened by an outside program - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import cStringIO -import math -import subprocess -import sys -import traceback - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewRepository(): - """Get new repository.""" - return ClairvoyanceRepository() - -def getWindowAnalyzeFile(fileName, repository=None): - """Open penultimate file with outside program.""" - print('') - if repository is None: - repository = settings.getReadRepository(ClairvoyanceRepository()) - gcodeProgram = repository.gcodeProgram.value - if gcodeProgram == '': - print('Warning, nothing will be done in getWindowAnalyzeFile in clairvoyance because the Gcode Program field is empty.') - print('') - return - if gcodeProgram == 'webbrowser': - print('Clairvoyance will use a web browser to open the file:') - print(archive.getSummarizedFileName(fileName)) - settings.openWebPage(fileName) - return - try: - subprocess.Popen([gcodeProgram, fileName]) - print('Clairvoyance has opened the file:') - print(archive.getSummarizedFileName(fileName)) - print('with the gcode program:') - print(gcodeProgram) - except: - print('Warning, getWindowAnalyzeFile in clairvoyance could not open the file:') - print(fileName) - print('with the gcode program:') - print(gcodeProgram) - print('Error traceback is the following:') - traceback.print_exc(file=sys.stdout) - print('') - return - -def writeOutput(fileName, fileNamePenultimate, fileNameSuffix, filePenultimateWritten, gcodeText=''): - """Open penultimate file with outside program given text.""" - repository = settings.getReadRepository(ClairvoyanceRepository()) - if repository.activateClairvoyance.value: - if not filePenultimateWritten: - archive.writeFileText(fileNamePenultimate, gcodeText) - getWindowAnalyzeFile(fileNamePenultimate, repository) - - -class ClairvoyanceRepository: - """A class to handle the clairvoyance settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.analyze_plugins.clairvoyance.html', self) - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Clairvoyance') - self.activateClairvoyance = settings.BooleanSetting().getFromValue('Activate Clairvoyance', self, False) - settings.LabelSeparator().getFromRepository(self) - self.fileNameInput = settings.FileNameInput().getFromFileName([('Gcode text files', '*.gcode')], 'Open File to Generate Clairvoyances for', self, '') - self.gcodeProgram = settings.StringSetting().getFromValue('Gcode Program:', self, 'webbrowser') - self.executeTitle = 'Clairvoyance' - - def execute(self): - """Write button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrGcodeDirectory( self.fileNameInput.value, self.fileNameInput.wasCancelled, ['_comment'] ) - for fileName in fileNames: - getWindowAnalyzeFile(fileName) - - -def main(): - """Display the clairvoyance dialog.""" - if len(sys.argv) > 1: - getWindowAnalyzeFile(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/comment.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/comment.py deleted file mode 100644 index 82dacbc..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/comment.py +++ /dev/null @@ -1,170 +0,0 @@ -""" -This page is in the table of contents. -Comment is a script to comment a gcode file. - -The comment manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Comment - -==Operation== -The default 'Activate Comment' checkbox is on. When it is on, the functions described below will work when called from the skeinforge toolchain, when it is off, the functions will not be called from the toolchain. The functions will still be called, whether or not the 'Activate Comment' checkbox is on, when comment is run directly. - -==Gcodes== -An explanation of the gcodes is at: -http://reprap.org/bin/view/Main/Arduino_GCode_Interpreter - -and at: -http://reprap.org/bin/view/Main/MCodeReference - -A gode example is at: -http://forums.reprap.org/file.php?12,file=565 - -==Examples== -Below are examples of comment being used. These examples are run in a terminal in the folder which contains Screw_Holder_penultimate.gcode and comment.py. - -> python comment.py -This brings up the comment dialog. - -> python comment.py Screw Holder_penultimate.gcode -The comment file is saved as Screw_Holder_penultimate_comment.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import cStringIO -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewRepository(): - """Get new repository.""" - return CommentRepository() - -def getWindowAnalyzeFile(fileName): - """Comment a gcode file.""" - gcodeText = archive.getFileText(fileName) - return getWindowAnalyzeFileGivenText(fileName, gcodeText) - -def getWindowAnalyzeFileGivenText(fileName, gcodeText): - """Write a commented gcode file for a gcode file.""" - skein = CommentSkein() - skein.parseGcode(gcodeText) - archive.writeFileMessageEnd('_comment.gcode', fileName, skein.output.getvalue(), 'The commented file is saved as ') - -def writeOutput(fileName, fileNamePenultimate, fileNameSuffix, filePenultimateWritten, gcodeText=''): - """Write a commented gcode file for a skeinforge gcode file, if 'Write Commented File for Skeinforge Chain' is selected.""" - repository = settings.getReadRepository( CommentRepository() ) - if gcodeText == '': - gcodeText = archive.getFileText( fileNameSuffix ) - if repository.activateComment.value: - getWindowAnalyzeFileGivenText( fileNameSuffix, gcodeText ) - - -class CommentRepository: - """A class to handle the comment settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.analyze_plugins.comment.html', self) - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Comment') - self.activateComment = settings.BooleanSetting().getFromValue('Activate Comment', self, False ) - self.fileNameInput = settings.FileNameInput().getFromFileName( [ ('Gcode text files', '*.gcode') ], 'Open File to Write Comments for', self, '') - self.executeTitle = 'Write Comments' - - def execute(self): - """Write button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrGcodeDirectory( self.fileNameInput.value, self.fileNameInput.wasCancelled, ['_comment'] ) - for fileName in fileNames: - getWindowAnalyzeFile(fileName) - - -class CommentSkein: - """A class to comment a gcode skein.""" - def __init__(self): - self.oldLocation = None - self.output = cStringIO.StringIO() - - def addComment( self, comment ): - """Add a gcode comment and a newline to the output.""" - self.output.write( "( " + comment + " )\n" ) - - def linearMove( self, splitLine ): - """Comment a linear move.""" - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - self.addComment( "Linear move to " + str( location ) + "." ); - self.oldLocation = location - - def parseGcode( self, gcodeText ): - """Parse gcode text and store the commented gcode.""" - lines = archive.getTextLines(gcodeText) - for line in lines: - self.parseLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the commented gcode.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - self.linearMove(splitLine) - elif firstWord == 'G2': - self.setHelicalMoveEndpoint(splitLine) - self.addComment( "Helical clockwise move to " + str( self.oldLocation ) + "." ) - elif firstWord == 'G3': - self.setHelicalMoveEndpoint(splitLine) - self.addComment( "Helical counterclockwise move to " + str( self.oldLocation ) + "." ) - elif firstWord == 'G21': - self.addComment( "Set units to mm." ) - elif firstWord == 'G28': - self.addComment( "Start at home." ) - elif firstWord == 'G90': - self.addComment( "Set positioning to absolute." ) - elif firstWord == 'M101': - self.addComment( "Extruder on, forward." ); - elif firstWord == 'M102': - self.addComment( "Extruder on, reverse." ); - elif firstWord == 'M103': - self.addComment( "Extruder off." ) - elif firstWord == 'M104': - self.addComment( "Set temperature to " + str( gcodec.getDoubleAfterFirstLetter(splitLine[1]) ) + " C." ) - elif firstWord == 'M105': - self.addComment( "Custom code for temperature reading." ) - elif firstWord == 'M106': - self.addComment( "Turn fan on." ) - elif firstWord == 'M107': - self.addComment( "Turn fan off." ) - elif firstWord == 'M108': - self.addComment( "Set extruder speed to " + str( gcodec.getDoubleAfterFirstLetter(splitLine[1]) ) + "." ) - self.output.write(line + '\n') - - def setHelicalMoveEndpoint( self, splitLine ): - """Get the endpoint of a helical move.""" - if self.oldLocation is None: - print( "A helical move is relative and therefore must not be the first move of a gcode file." ) - return - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - location += self.oldLocation - self.oldLocation = location - - -def main(): - """Display the comment dialog.""" - if len(sys.argv) > 1: - getWindowAnalyzeFile(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() - diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/export_canvas_plugins/__init__.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/export_canvas_plugins/__init__.py deleted file mode 100644 index 58ec332..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/export_canvas_plugins/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 4 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/export_canvas_plugins/postscript.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/export_canvas_plugins/postscript.py deleted file mode 100644 index 102d2a8..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/export_canvas_plugins/postscript.py +++ /dev/null @@ -1,95 +0,0 @@ -""" -This page is in the table of contents. -Postscript is an export canvas plugin to export the canvas to a postscript file. - -When the export menu item in the file menu in an analyze viewer tool, like skeinlayer or skeiniso is clicked, the postscript dialog will be displayed. When the 'Export to Postscript' button on that dialog is clicked, the canvas will be exported as a postscript file. If the 'Postscript Program' is set to a program name, the postscript file will be sent to that program to be opened. The default is gimp, the Gnu Image Manipulation Program (Gimp), which is open source, can open postscript and save in a variety of formats. It is available at: -http://www.gimp.org/ - -If furthermore the 'File Extension' is set to a file extension, the postscript file will be sent to the program, along with the file extension for the converted output. The default is blank because some systems do not have an image conversion program; if you have or will install an image conversion program, a common 'File Extension' is png. A good open source conversion program is Image Magick, which is available at: -http://www.imagemagick.org/script/index.php - -An export canvas plugin is a script in the export_canvas_plugins folder which has the function getNewRepository, and which has a repository class with the functions setCanvasFileNameSuffix to set variables and execute to save the file. It is meant to be run from an analyze viewer tool, like skeinlayer or skeiniso. To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name. - -""" - - -from __future__ import absolute_import -import __init__ -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import cStringIO -import os -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewRepository(): - """Get new repository.""" - return PostscriptRepository() - - -class PostscriptRepository: - """A class to handle the export settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository( - 'skeinforge_application.skeinforge_plugins.analyze_plugins.export_canvas_plugins.postscript.html', self) - self.fileExtension = settings.StringSetting().getFromValue('File Extension:', self, '') - self.postscriptProgram = settings.StringSetting().getFromValue('Postscript Program:', self, 'gimp') - - def execute(self): - """Convert to postscript button has been clicked.""" - "Export the canvas as a postscript file." - postscriptFileName = archive.getFilePathWithUnderscoredBasename( self.fileName, self.suffix ) - boundingBox = self.canvas.bbox( settings.Tkinter.ALL ) # tuple (w, n, e, s) - boxW = boundingBox[0] - boxN = boundingBox[1] - boxWidth = boundingBox[2] - boxW - boxHeight = boundingBox[3] - boxN - print('Exported postscript file saved as ' + postscriptFileName ) - self.canvas.postscript( file = postscriptFileName, height = boxHeight, width = boxWidth, pageheight = boxHeight, pagewidth = boxWidth, x = boxW, y = boxN ) - fileExtension = self.fileExtension.value - postscriptProgram = self.postscriptProgram.value - if postscriptProgram == '': - return - postscriptFilePath = '"' + os.path.normpath( postscriptFileName ) + '"' # " to send in file name with spaces - shellCommand = postscriptProgram + ' ' + postscriptFilePath - print('') - if fileExtension == '': - print('Sending the shell command:') - print(shellCommand) - commandResult = os.system(shellCommand) - if commandResult != 0: - print('It may be that the system could not find the %s program.' % postscriptProgram ) - print('If so, try installing the %s program or look for another one, like the Gnu Image Manipulation Program (Gimp) which can be found at:' % postscriptProgram ) - print('http://www.gimp.org/') - return - convertedFileName = archive.getFilePathWithUnderscoredBasename( postscriptFilePath, '.' + fileExtension + '"') - shellCommand += ' ' + convertedFileName - print('Sending the shell command:') - print(shellCommand) - commandResult = os.system(shellCommand) - if commandResult != 0: - print('The %s program could not convert the postscript to the %s file format.' % ( postscriptProgram, fileExtension ) ) - print('Try installing the %s program or look for another one, like Image Magick which can be found at:' % postscriptProgram ) - print('http://www.imagemagick.org/script/index.php') - - def setCanvasFileNameSuffix( self, canvas, fileName, suffix ): - """Set the canvas and initialize the execute title.""" - self.canvas = canvas - self.executeTitle = 'Export to Postscript' - self.fileName = fileName - self.suffix = suffix + '.ps' - - -def main(): - """Display the file or directory dialog.""" - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/export_canvas_plugins/scalable_vector_graphics.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/export_canvas_plugins/scalable_vector_graphics.py deleted file mode 100644 index e9477f2..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/export_canvas_plugins/scalable_vector_graphics.py +++ /dev/null @@ -1,137 +0,0 @@ -""" -This page is in the table of contents. -Scalable vector graphics is an export canvas plugin to export the canvas to a scalable vector graphics (.svg) file. - -When the export menu item in the file menu in an analyze viewer tool, like skeinlayer or skeiniso is clicked, the postscript dialog will be displayed. When the 'Export to Scalable Vector Graphics' button on that dialog is clicked, the canvas will be exported as a scalable vector graphics file. If the 'Scalable Vector Graphics Program' is set to the default 'webbrowser', the scalable vector graphics file will be sent to the default browser to be opened. If the 'Scalable Vector Graphics Program' is set to a program name, the scalable vector graphics file will be sent to that program to be opened. - -If furthermore the 'File Extension' is set to a file extension, the scalable vector graphics file will be sent to the program, along with the file extension for the converted output. The default is blank because some systems do not have an image conversion program; if you have or will install an image conversion program, a common 'File Extension' is png. A good open source conversion program is Image Magick, which is available at: -http://www.imagemagick.org/script/index.php - -An export canvas plugin is a script in the export_canvas_plugins folder which has the function getNewRepository, and which has a repository class with the functions setCanvasFileNameSuffix to set variables and execute to save the file. It is meant to be run from an analyze viewer tool, like skeinlayer or skeiniso. To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import cStringIO -import os -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewRepository(): - """Get new repository.""" - return ScalableVectorGraphicsRepository() - -def parseLineReplace( firstWordTable, line, output ): - """Parse the line and replace it if the first word of the line is in the first word table.""" - firstWord = gcodec.getFirstWordFromLine(line) - if firstWord in firstWordTable: - line = firstWordTable[ firstWord ] - gcodec.addLineAndNewlineIfNecessary( line, output ) - - -class ScalableVectorGraphicsRepository: - """A class to handle the export settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository( - 'skeinforge_application.skeinforge_plugins.analyze_plugins.export_canvas_plugins.scalable_vector_graphics.html', self) - self.fileExtension = settings.StringSetting().getFromValue('File Extension:', self, '') - self.svgViewer = settings.StringSetting().getFromValue('SVG Viewer:', self, 'webbrowser') - - def addCanvasLineToOutput( self, canvasLinesOutput, objectIDNumber ): - """Add the canvas line to the output.""" - coordinates = self.canvas.coords( objectIDNumber ) - xBegin = coordinates[0] - self.boxW - xEnd = coordinates[2] - self.boxW - yBegin = coordinates[1] - self.boxN - yEnd = coordinates[3] - self.boxN - west = self.boxW - color = self.canvas.itemcget( objectIDNumber, 'fill') - width = self.canvas.itemcget( objectIDNumber, 'width') - line = '\n' % ( xBegin, yBegin, xEnd, yEnd, color, width ) - canvasLinesOutput.write(line + '\n') - - def execute(self): - """Export the canvas as an svg file.""" - svgFileName = archive.getFilePathWithUnderscoredBasename( self.fileName, self.suffix ) - boundingBox = self.canvas.bbox( settings.Tkinter.ALL ) # tuple (w, n, e, s) - self.boxW = boundingBox[0] - self.boxN = boundingBox[1] - boxWidth = boundingBox[2] - self.boxW - boxHeight = boundingBox[3] - self.boxN - print('Exported svg file saved as ' + svgFileName ) - svgTemplateText = archive.getFileText(archive.getTemplatesPath('canvas_template.svg')) - output = cStringIO.StringIO() - lines = archive.getTextLines( svgTemplateText ) - firstWordTable = {} - firstWordTable['height="999px"'] = ' height="%spx"' % int( round( boxHeight ) ) - firstWordTable[''] = self.getCanvasLinesOutput() - firstWordTable['replaceLineWithTitle'] = archive.getSummarizedFileName( self.fileName ) - firstWordTable['width="999px"'] = ' width="%spx"' % int( round( boxWidth ) ) - for line in lines: - parseLineReplace( firstWordTable, line, output ) - archive.writeFileText( svgFileName, output.getvalue() ) - fileExtension = self.fileExtension.value - svgViewer = self.svgViewer.value - if svgViewer == '': - return - if svgViewer == 'webbrowser': - settings.openWebPage( svgFileName ) - return - svgFilePath = '"' + os.path.normpath( svgFileName ) + '"' # " to send in file name with spaces - shellCommand = svgViewer + ' ' + svgFilePath - print('') - if fileExtension == '': - print('Sending the shell command:') - print(shellCommand) - commandResult = os.system(shellCommand) - if commandResult != 0: - print('It may be that the system could not find the %s program.' % svgViewer ) - print('If so, try installing the %s program or look for another svg viewer, like Netscape which can be found at:' % svgViewer ) - print('http://www.netscape.org/') - return - convertedFileName = archive.getFilePathWithUnderscoredBasename( svgFilePath, '.' + fileExtension + '"') - shellCommand += ' ' + convertedFileName - print('Sending the shell command:') - print(shellCommand) - commandResult = os.system(shellCommand) - if commandResult != 0: - print('The %s program could not convert the svg to the %s file format.' % ( svgViewer, fileExtension ) ) - print('Try installing the %s program or look for another one, like Image Magick which can be found at:' % svgViewer ) - print('http://www.imagemagick.org/script/index.php') - - def getCanvasLinesOutput(self): - """Add the canvas line to the output.""" - canvasLinesOutput = cStringIO.StringIO() - objectIDNumbers = self.canvas.find_all() - for objectIDNumber in objectIDNumbers: - if self.canvas.type( objectIDNumber ) == 'line': - self.addCanvasLineToOutput( canvasLinesOutput, objectIDNumber ) - return canvasLinesOutput.getvalue() - - def setCanvasFileNameSuffix( self, canvas, fileName, suffix ): - """Set the canvas and initialize the execute title.""" - self.canvas = canvas - self.executeTitle = 'Convert to Scalable Vector Graphics' - self.fileName = fileName - self.suffix = suffix + '.svg' - - -def main(): - """Display the file or directory dialog.""" - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/interpret.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/interpret.py deleted file mode 100644 index cf6657c..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/interpret.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -This page is in the table of contents. -Interpret is a script to interpret a file, turning it into xml. - -==Operation== -The default 'Activate Interpret' checkbox is off. When it is on, the functions described below will work when called from the skeinforge toolchain, when it is off, the functions will not be called from the tool chain. The functions will still be called, whether or not the 'Activate Interpret' checkbox is on, when interpret is run directly. - -==Settings== -===Print Interpretion=== -Default is off. - -When selected, the xml text will be printed to the console. - -===Text Program=== -Default is webbrowser. - -If the 'Text Program' is set the default 'webbrowser', the XML file will be sent to the default browser to be opened. If the 'Text Program' is set to a program name, the XML file will be sent to that program to be opened. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import settings -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewRepository(): - """Get new repository.""" - return fabmetheus_interpret.InterpretRepository() - -def writeOutput(fileName, fileNamePenultimate, fileNameSuffix, filePenultimateWritten, gcodeText=''): - """Write file interpretation, if activate interpret is selected.""" - repository = settings.getReadRepository( getNewRepository() ) - if repository.activateInterpret.value: - fabmetheus_interpret.getWindowAnalyzeFile(fileName) - - -def main(): - """Display the interpret dialog.""" - if len(sys.argv) > 1: - fabmetheus_interpret.getWindowAnalyzeFile(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/skeiniso.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/skeiniso.py deleted file mode 100644 index 54adf3b..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/skeiniso.py +++ /dev/null @@ -1,886 +0,0 @@ -""" -This page is in the table of contents. -Skeiniso is an analysis script to display a gcode file in an isometric view. - -The skeiniso manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Skeiniso - -==Operation== -The default 'Activate Skeiniso' checkbox is on. When it is on, the functions described below will work when called from the skeinforge toolchain, when it is off, the functions will not be called from the toolchain. The functions will still be called, whether or not the 'Activate Skeiniso' checkbox is on, when skeiniso is run directly. - -Skeiniso requires skeinforge comments in the gcode file to distinguish the loops and perimeters. If the comments are deleted, all threads will be displayed as generic threads. To get the penultimate file of the tool chain, just before export deletes the comments, select 'Save Penultimate Gcode' in export, and open the gcode file with the suffix '_penultimate.gcode' with skeiniso. - -The viewer is simple, the viewpoint can only be moved in a sphere around the center of the model by changing the viewpoint latitude and longitude. Different regions of the model can be hidden by setting the width of the thread to zero. The alternating bands act as contour bands and their brightness and width can be changed. - -==Settings== -===Animation=== -====Animation Line Quickening==== -Default is one. - -The quickness of the tool animation over the quickness of the actual tool. - -====Animation Slide Show Rate==== -Default is two layers per second. - -The rate, in layers per second, at which the layer changes when the soar or dive button is pressed.. - -===Axis Rulings=== -Default is on. - -When selected, rulings will be drawn on the axis lines. - -===Banding=== -====Band Height==== -Default is five layers. - -Defines the height of the band in layers, a pair of bands is twice that height. - -====Bottom Band Brightness==== -Default is 0.7. - -Defines the ratio of the brightness of the bottom band over the brightness of the top band. The higher it is the brighter the bottom band will be. - -====Bottom Layer Brightness==== -Default is one. - -Defines the ratio of the brightness of the bottom layer over the brightness of the top layer. With a low bottom layer brightness ratio the bottom of the model will be darker than the top of the model, as if it was being illuminated by a light just above the top. - -====Bright Band Start==== -Default choice is 'From the Top'. - -The button group that determines where the bright band starts from. - -=====From the Bottom===== -When selected, the bright bands will start from the bottom. - -=====From the Top===== -When selected, the bright bands will start from the top. - -===Draw Arrows=== -Default is on. - -When selected, arrows will be drawn at the end of each line segment. - -===Export Menu=== -When the submenu in the export menu item in the file menu is clicked, an export canvas dialog will be displayed, which can export the canvas to a file. - -===Go Around Extruder Off Travel=== -Default is off. - -When selected, the display will include the travel when the extruder is off, which means it will include the nozzle wipe path if any. - -===Layers=== -====Layer==== -Default is zero. - -On the display window, the Up button increases the 'Layer' by one, and the Down button decreases the layer by one. When the layer displayed in the layer spin box is changed then is hit, the layer shown will be set to the spin box, to a mimimum of zero and to a maximum of the highest index layer.The Soar button increases the layer at the 'Animation Slide Show Rate', and the Dive (double left arrow button beside the layer field) button decreases the layer at the slide show rate. - -====Layer Extra Span==== -Default is a huge number. - -The viewer will draw the layers in the range including the 'Layer' index and the 'Layer' index plus the 'Layer Extra Span'. If the 'Layer Extra Span' is negative, the layers viewed will start at the 'Layer' index, plus the 'Layer Extra Span', and go up to and include the 'Layer' index. If the 'Layer Extra Span' is zero, only the 'Layer' index layer will be displayed. If the 'Layer Extra Span' is positive, the layers viewed will start at the 'Layer' index, and go up to and include the 'Layer' index plus the 'Layer Extra Span'. - -===Line=== -Default is zero. - -The index of the selected line on the layer that is highlighted when the 'Display Line' mouse tool is chosen. The line spin box up button increases the 'Line' by one. If the line index of the layer goes over the index of the last line, the layer index will be increased by one and the new line index will be zero. The down button decreases the line index by one. If the line index goes below the index of the first line, the layer index will be decreased by one and the new line index will be at the last line. When the line displayed in the line field is changed then is hit, the line shown will be set to the line field, to a mimimum of zero and to a maximum of the highest index line. The Soar button increases the line at the speed at which the extruder would move, times the 'Animation Line Quickening' ratio, and the Dive (double left arrow button beside the line field) button decreases the line at the animation line quickening ratio. - -===Mouse Mode=== -Default is 'Display Line'. - -The mouse tool can be changed from the 'Mouse Mode' menu button or picture button. The mouse tools listen to the arrow keys when the canvas has the focus. Clicking in the canvas gives the canvas the focus, and when the canvas has the focus a thick black border is drawn around the canvas. - -====Display Line==== -The 'Display Line' tool will display the highlight the selected line, and display the file line count, counting from one, and the gcode line itself. When the 'Display Line' tool is active, clicking the canvas will select the nearest line to the mouse click. - -====Viewpoint Move==== -The 'Viewpoint Move' tool will move the viewpoint in the xy plane when the mouse is clicked and dragged on the canvas. - -====Viewpoint Rotate==== -The 'Viewpoint Rotate' tool will rotate the viewpoint around the origin, when the mouse is clicked and dragged on the canvas, or the arrow keys have been used and is pressed. The viewpoint can also be moved by dragging the mouse. The viewpoint latitude will be increased when the mouse is dragged from the center towards the edge. The viewpoint longitude will be changed by the amount around the center the mouse is dragged. This is not very intuitive, but I don't know how to do this the intuitive way and I have other stuff to develop. If the shift key is pressed; if the latitude is changed more than the longitude, only the latitude will be changed, if the longitude is changed more only the longitude will be changed. - -===Number of Fill Layers=== -====Number of Fill Bottom Layers==== -Default is one. - -The "Number of Fill Bottom Layers" is the number of layers at the bottom which will be colored olive. - -===Number of Fill Top Layers=== -Default is one. - -The "Number of Fill Top Layers" is the number of layers at the top which will be colored blue. - -===Scale=== -Default is ten. - -The scale setting is the scale of the image in pixels per millimeter, the higher the number, the greater the size of the display. - -The zoom in mouse tool will zoom in the display at the point where the mouse was clicked, increasing the scale by a factor of two. The zoom out tool will zoom out the display at the point where the mouse was clicked, decreasing the scale by a factor of two. - -===Screen Inset=== -====Screen Horizontal Inset==== -Default is one hundred. - -The "Screen Horizontal Inset" determines how much the canvas will be inset in the horizontal direction from the edge of screen, the higher the number the more it will be inset and the smaller it will be. - -====Screen Vertical Inset==== -Default is two hundred and twenty. - -The "Screen Vertical Inset" determines how much the canvas will be inset in the vertical direction from the edge of screen, the higher the number the more it will be inset and the smaller it will be.. - -===Viewpoint=== -====Viewpoint Latitude==== -Default is fifteen degrees. - -The "Viewpoint Latitude" is the latitude of the viewpoint, a latitude of zero is the top pole giving a top view, a latitude of ninety gives a side view and a latitude of 180 gives a bottom view. - -====Viewpoint Longitude==== -Default is 210 degrees. - -The "Viewpoint Longitude" is the longitude of the viewpoint. - -===Width=== -The width of each type of thread and of each axis can be changed. If the width is set to zero, the thread will not be visible. - -====Width of Axis Negative Side==== -Default is two. - -Defines the width of the negative side of the axis. - -====Width of Axis Positive Side==== -Default is six. - -Defines the width of the positive side of the axis. - -====Width of Infill Thread==== -Default is one. - -The "Width of Infill Thread" sets the width of the green extrusion threads, those threads which are not loops and not part of the raft. - -====Width of Fill Bottom Thread==== -Default is two. - -The "Width of Fill Bottom Thread" sets the width of the olive extrusion threads at the bottom of the model. - -====Width of Fill Top Thread==== -Default is two. - -The "Width of Fill Top Thread" sets the width of the blue extrusion threads at the top of the model. - -====Width of Loop Thread==== -Default is three. - -The "Width of Loop Thread" sets the width of the yellow loop threads, which are not perimeters. - -====Width of Perimeter Inside Thread==== -Default is eight. - -The "Width of Perimeter Inside Thread" sets the width of the orange inside perimeter threads. - -====Width of Perimeter Outside Thread==== -Default is eight. - -The "Width of Perimeter Outside Thread" sets the width of the red outside perimeter threads. - -====Width of Raft Thread==== -Default is one. - -The "Width of Raft Thread" sets the width of the brown raft threads. - -====Width of Selection Thread==== -Default is six. - -The "Width of Selection Thread" sets the width of the selected line. - -====Width of Travel Thread==== -Default is zero. - -The "Width of Travel Thread" sets the width of the grey extruder off travel threads. - -==Icons== -The dive, soar and zoom icons are from Mark James' soarSilk icon set 1.3 at: -http://www.famfamfam.com/lab/icons/silk/ - -==Gcodes== -An explanation of the gcodes is at: -http://reprap.org/bin/view/Main/Arduino_GCode_Interpreter - -and at: -http://reprap.org/bin/view/Main/MCodeReference - -A gode example is at: -http://forums.reprap.org/file.php?12,file=565 - -==Examples== -Below are examples of skeiniso being used. These examples are run in a terminal in the folder which contains Screw Holder_penultimate.gcode and skeiniso.py. - -> python skeiniso.py -This brings up the skeiniso dialog. - -> python skeiniso.py Screw Holder_penultimate.gcode -This brings up the skeiniso viewer to view the gcode file. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_plugins.analyze_plugins.analyze_utilities import display_line -from skeinforge_application.skeinforge_plugins.analyze_plugins.analyze_utilities import tableau -from skeinforge_application.skeinforge_plugins.analyze_plugins.analyze_utilities import view_move -from skeinforge_application.skeinforge_plugins.analyze_plugins.analyze_utilities import view_rotate -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def compareLayerSequence( first, second ): - """Get comparison in order to sort skein panes in ascending order of layer zone index then sequence index.""" - if first.layerZoneIndex < second.layerZoneIndex: - return - 1 - if first.layerZoneIndex > second.layerZoneIndex: - return 1 - if first.sequenceIndex < second.sequenceIndex: - return - 1 - return int( first.sequenceIndex > second.sequenceIndex ) - -def getNewRepository(): - """Get new repository.""" - return SkeinisoRepository() - -def getWindowAnalyzeFile(fileName): - """Skeiniso a gcode file.""" - gcodeText = archive.getFileText(fileName) - return getWindowAnalyzeFileGivenText(fileName, gcodeText) - -def getWindowAnalyzeFileGivenText( fileName, gcodeText, repository=None): - """Display a skeiniso gcode file for a gcode file.""" - if gcodeText == '': - return None - if repository is None: - repository = settings.getReadRepository( SkeinisoRepository() ) - skeinWindow = getWindowGivenTextRepository( fileName, gcodeText, repository ) - skeinWindow.updateDeiconify() - return skeinWindow - -def getWindowGivenTextRepository( fileName, gcodeText, repository ): - """Display the gcode text in a skeiniso viewer.""" - skein = SkeinisoSkein() - skein.parseGcode( fileName, gcodeText, repository ) - return SkeinWindow( repository, skein ) - -def writeOutput(fileName, fileNamePenultimate, fileNameSuffix, filePenultimateWritten, gcodeText=''): - """Write a skeinisoed gcode file for a skeinforge gcode file, if 'Activate Skeiniso' is selected.""" - try: - import Tkinter - except: - print('Warning, skeiniso will do nothing because Tkinter is not installed.') - return - repository = settings.getReadRepository( SkeinisoRepository() ) - if repository.activateSkeiniso.value: - gcodeText = archive.getTextIfEmpty( fileNameSuffix, gcodeText ) - return getWindowAnalyzeFileGivenText( fileNameSuffix, gcodeText, repository ) - - -class SkeinisoRepository( tableau.TableauRepository ): - """A class to handle the skeiniso settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.analyze_plugins.skeiniso.html', self) - self.baseNameSynonym = 'behold.csv' - self.fileNameInput = settings.FileNameInput().getFromFileName( [ ('Gcode text files', '*.gcode') ], 'Open File for Skeiniso', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Skeiniso') - self.activateSkeiniso = settings.BooleanSetting().getFromValue('Activate Skeiniso', self, True ) - self.addAnimation() - self.axisRulings = settings.BooleanSetting().getFromValue('Axis Rulings', self, True ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Banding -', self ) - self.bandHeight = settings.IntSpinUpdate().getFromValue( 0, 'Band Height (layers):', self, 10, 5 ) - self.bottomBandBrightness = settings.FloatSpinUpdate().getFromValue( 0.0, 'Bottom Band Brightness (ratio):', self, 1.0, 0.7 ) - self.bottomLayerBrightness = settings.FloatSpinUpdate().getFromValue( 0.0, 'Bottom Layer Brightness (ratio):', self, 1.0, 1.0 ) - self.brightBandStart = settings.MenuButtonDisplay().getFromName('Bright Band Start:', self ) - self.fromTheBottom = settings.MenuRadio().getFromMenuButtonDisplay( self.brightBandStart, 'From the Bottom', self, False ) - self.fromTheTop = settings.MenuRadio().getFromMenuButtonDisplay( self.brightBandStart, 'From the Top', self, True ) - settings.LabelSeparator().getFromRepository(self) - self.drawArrows = settings.BooleanSetting().getFromValue('Draw Arrows', self, False ) - self.goAroundExtruderOffTravel = settings.BooleanSetting().getFromValue('Go Around Extruder Off Travel', self, False ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Layers -', self ) - self.layer = settings.IntSpinNotOnMenu().getSingleIncrementFromValue( 0, 'Layer (index):', self, 912345678, 0 ) - self.layerExtraSpan = settings.IntSpinUpdate().getSingleIncrementFromValue( - 912345678, 'Layer Extra Span (integer):', self, 912345678, 912345678 ) - settings.LabelSeparator().getFromRepository(self) - self.line = settings.IntSpinNotOnMenu().getSingleIncrementFromValue( 0, 'Line (index):', self, 912345678, 0 ) - self.mouseMode = settings.MenuButtonDisplay().getFromName('Mouse Mode:', self ) - self.displayLine = settings.MenuRadio().getFromMenuButtonDisplay( self.mouseMode, 'Display Line', self, True ) - self.viewMove = settings.MenuRadio().getFromMenuButtonDisplay( self.mouseMode, 'View Move', self, False ) - self.viewRotate = settings.MenuRadio().getFromMenuButtonDisplay( self.mouseMode, 'View Rotate', self, False ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Number of Fill Layers -', self ) - self.numberOfFillBottomLayers = settings.IntSpinUpdate().getFromValue( 0, 'Number of Fill Bottom Layers (integer):', self, 5, 1 ) - self.numberOfFillTopLayers = settings.IntSpinUpdate().getFromValue( 0, 'Number of Fill Top Layers (integer):', self, 5, 1 ) - settings.LabelSeparator().getFromRepository(self) - self.addScaleScreenSlide() - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Viewpoint -', self ) - self.viewpointLatitude = settings.FloatSpin().getFromValue( 0.0, 'Viewpoint Latitude (degrees):', self, 180.0, 15.0 ) - self.viewpointLongitude = settings.FloatSpin().getFromValue( 0.0, 'Viewpoint Longitude (degrees):', self, 360.0, 210.0 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Width -', self ) - self.widthOfAxisNegativeSide = settings.IntSpinUpdate().getFromValue( 0, 'Width of Axis Negative Side (pixels):', self, 10, 2 ) - self.widthOfAxisPositiveSide = settings.IntSpinUpdate().getFromValue( 0, 'Width of Axis Positive Side (pixels):', self, 10, 6 ) - self.widthOfFillBottomThread = settings.IntSpinUpdate().getFromValue( 0, 'Width of Fill Bottom Thread (pixels):', self, 10, 2 ) - self.widthOfFillTopThread = settings.IntSpinUpdate().getFromValue( 0, 'Width of Fill Top Thread (pixels):', self, 10, 2 ) - self.widthOfInfillThread = settings.IntSpinUpdate().getFromValue( 0, 'Width of Infill Thread (pixels):', self, 10, 1 ) - self.widthOfLoopThread = settings.IntSpinUpdate().getFromValue( 0, 'Width of Loop Thread (pixels):', self, 10, 2 ) - self.widthOfPerimeterInsideThread = settings.IntSpinUpdate().getFromValue( 0, 'Width of Perimeter Inside Thread (pixels):', self, 10, 8 ) - self.widthOfPerimeterOutsideThread = settings.IntSpinUpdate().getFromValue( 0, 'Width of Perimeter Outside Thread (pixels):', self, 10, 8 ) - self.widthOfRaftThread = settings.IntSpinUpdate().getFromValue( 0, 'Width of Raft Thread (pixels):', self, 10, 1 ) - self.widthOfSelectionThread = settings.IntSpinUpdate().getFromValue( 0, 'Width of Selection Thread (pixels):', self, 10, 6 ) - self.widthOfTravelThread = settings.IntSpinUpdate().getFromValue( 0, 'Width of Travel Thread (pixels):', self, 10, 0 ) - self.executeTitle = 'Skeiniso' - - def execute(self): - """Write button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrGcodeDirectory( self.fileNameInput.value, self.fileNameInput.wasCancelled ) - for fileName in fileNames: - getWindowAnalyzeFile(fileName) - - -class SkeinisoSkein: - """A class to write a get a scalable vector graphics text for a gcode skein.""" - def __init__(self): - self.coloredThread = [] - self.feedRateMinute = 960.1 - self.hasASurroundingLoopBeenReached = False - self.isLoop = False - self.isPerimeter = False - self.isOuter = False - self.isThereALayerStartWord = False - self.layerCount = settings.LayerCount() - self.layerTops = [] - self.lineIndex = 0 - self.oldLayerZoneIndex = 0 - self.oldZ = - 999987654321.0 - self.skeinPane = None - self.skeinPanes = [] - self.thirdLayerThickness = 0.133333 - - def addToPath( self, line, location ): - """Add a point to travel and maybe extrusion.""" - if self.oldLocation is None: - return - begin = self.scale * self.oldLocation - self.scaleCenterBottom - end = self.scale * location - self.scaleCenterBottom - displayString = '%s %s' % ( self.lineIndex + 1, line ) - tagString = 'colored_line_index: %s %s' % ( len( self.skeinPane.coloredLines ), len( self.skeinPanes ) - 1 ) - coloredLine = tableau.ColoredLine( begin, '', displayString, end, tagString ) - coloredLine.z = location.z - self.skeinPane.coloredLines.append( coloredLine ) - self.coloredThread.append( coloredLine ) - - def getLayerTop(self): - """Get the layer top.""" - if len( self.layerTops ) < 1: - return - 9123456789123.9 - return self.layerTops[-1] - - def getLayerZoneIndex( self, z ): - """Get the layer zone index.""" - if self.layerTops[ self.oldLayerZoneIndex ] > z: - if self.oldLayerZoneIndex == 0: - return 0 - elif self.layerTops[ self.oldLayerZoneIndex - 1 ] < z: - return self.oldLayerZoneIndex - for layerTopIndex in xrange( len( self.layerTops ) ): - layerTop = self.layerTops[ layerTopIndex ] - if layerTop > z: - self.oldLayerZoneIndex = layerTopIndex - return layerTopIndex - self.oldLayerZoneIndex = len( self.layerTops ) - 1 - return self.oldLayerZoneIndex - - def initializeActiveLocation(self): - """Set variables to default.""" - self.extruderActive = False - self.oldLocation = None - - def linearCorner( self, splitLine ): - """Update the bounding corners.""" - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - if self.extruderActive or self.goAroundExtruderOffTravel: - self.cornerMaximum.maximize(location) - self.cornerMinimum.minimize(location) - self.oldLocation = location - - def linearMove( self, line, location ): - """Get statistics for a linear move.""" - if self.skeinPane is None: - return - self.addToPath(line, location) - - def moveColoredThreadToSkeinPane(self): - """Move a colored thread to the skein pane.""" - if len( self.coloredThread ) <= 0: - return - layerZoneIndex = self.getLayerZoneIndex( self.coloredThread[0].z ) - if not self.extruderActive: - self.setColoredThread( ( 190.0, 190.0, 190.0 ), self.skeinPane.travelLines ) #grey - return - self.skeinPane.layerZoneIndex = layerZoneIndex - if self.isPerimeter: - if self.isOuter: - self.setColoredThread( ( 255.0, 0.0, 0.0 ), self.skeinPane.perimeterOutsideLines ) #red - else: - self.setColoredThread( ( 255.0, 165.0, 0.0 ), self.skeinPane.perimeterInsideLines ) #orange - return - if self.isLoop: - self.setColoredThread( ( 255.0, 255.0, 0.0 ), self.skeinPane.loopLines ) #yellow - return - if not self.hasASurroundingLoopBeenReached: - self.setColoredThread( ( 165.0, 42.0, 42.0 ), self.skeinPane.raftLines ) #brown - return - if layerZoneIndex < self.repository.numberOfFillBottomLayers.value: - self.setColoredThread( ( 128.0, 128.0, 0.0 ), self.skeinPane.fillBottomLines ) #olive - return - if layerZoneIndex >= self.firstTopLayer: - self.setColoredThread( ( 0.0, 0.0, 255.0 ), self.skeinPane.fillTopLines ) #blue - return - self.setColoredThread( ( 0.0, 255.0, 0.0 ), self.skeinPane.infillLines ) #green - - def parseCorner(self, line): - """Parse a gcode line and use the location to update the bounding corners.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if tableau.getIsLayerStart(firstWord, self, splitLine): - if firstWord == '(': - self.layerTopZ = float(splitLine[1]) + self.thirdLayerThickness - else: - self.layerTopZ = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine).z + self.thirdLayerThickness - self.layerTops.append( self.layerTopZ ) - if firstWord == 'G1': - self.linearCorner(splitLine) - elif firstWord == 'M101': - self.extruderActive = True - elif firstWord == 'M103': - self.extruderActive = False - elif firstWord == '(': - self.thirdLayerThickness = 0.33333333333 * float(splitLine[1]) - if firstWord == '()': - if self.layerTopZ > self.getLayerTop(): - self.layerTops.append( self.layerTopZ ) - - def parseGcode( self, fileName, gcodeText, repository ): - """Parse gcode text and store the vector output.""" - self.repository = repository - self.fileName = fileName - self.gcodeText = gcodeText - self.initializeActiveLocation() - self.cornerMaximum = Vector3(-987654321.0, -987654321.0, -987654321.0) - self.cornerMinimum = Vector3(987654321.0, 987654321.0, 987654321.0) - self.goAroundExtruderOffTravel = repository.goAroundExtruderOffTravel.value - self.lines = archive.getTextLines(gcodeText) - self.isThereALayerStartWord = (gcodec.getFirstWordIndexReverse('(', self.lines, 1) > -1) - if self.isThereALayerStartWord: - self.parseInitialization() - else: - print('') - print('') - print('') - print('Warning, there are no skeinforge comments in this text, probably because they have been removed by export.') - print('So there is no loop information, and therefore the lines will not be colored.') - print('') - print('To see the full information in an exported file, either deselect Delete Comments in export, or') - print('select Save Penultimate Gcode in export, and open the generated file with the suffix _penultimate.gcode.') - print('') - print('') - print('') - for line in self.lines[self.lineIndex :]: - self.parseCorner(line) - self.oldZ = - 999987654321.0 - if len( self.layerTops ) > 0: - self.layerTops[-1] += 912345678.9 - if len( self.layerTops ) > 1: - self.oneMinusBrightnessOverTopLayerIndex = ( 1.0 - repository.bottomLayerBrightness.value ) / float( len( self.layerTops ) - 1 ) - self.firstTopLayer = len( self.layerTops ) - self.repository.numberOfFillTopLayers.value - self.centerComplex = 0.5 * ( self.cornerMaximum.dropAxis() + self.cornerMinimum.dropAxis() ) - self.centerBottom = Vector3( self.centerComplex.real, self.centerComplex.imag, self.cornerMinimum.z ) - self.scale = repository.scale.value - self.scaleCenterBottom = self.scale * self.centerBottom - self.scaleCornerHigh = self.scale * self.cornerMaximum.dropAxis() - self.scaleCornerLow = self.scale * self.cornerMinimum.dropAxis() - print("The lower left corner of the skeiniso window is at %s, %s" % (self.cornerMinimum.x, self.cornerMinimum.y)) - print("The upper right corner of the skeiniso window is at %s, %s" % (self.cornerMaximum.x, self.cornerMaximum.y)) - self.cornerImaginaryTotal = self.cornerMaximum.y + self.cornerMinimum.y - margin = complex( 5.0, 5.0 ) - self.marginCornerLow = self.scaleCornerLow - margin - self.screenSize = margin + 2.0 * ( self.scaleCornerHigh - self.marginCornerLow ) - self.initializeActiveLocation() - for self.lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[self.lineIndex] - self.parseLine(line) - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == '()': - return - elif firstWord == '(': - self.feedRateMinute = 60.0 * float(splitLine[1]) - - def parseLine(self, line): - """Parse a gcode line and add it to the vector output.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if tableau.getIsLayerStart(firstWord, self, splitLine): - self.layerCount.printProgressIncrement('skeiniso') - self.skeinPane = SkeinPane( len( self.skeinPanes ) ) - self.skeinPanes.append( self.skeinPane ) - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - self.linearMove(line, location) - self.oldLocation = location - elif firstWord == 'M101': - self.moveColoredThreadToSkeinPane() - self.extruderActive = True - elif firstWord == 'M103': - self.moveColoredThreadToSkeinPane() - self.extruderActive = False - self.isLoop = False - self.isPerimeter = False - elif firstWord == '(': - self.isLoop = True - elif firstWord == '()': - self.moveColoredThreadToSkeinPane() - self.isLoop = False - elif firstWord == '()': - self.hasASurroundingLoopBeenReached = True - elif firstWord == '(': - self.isPerimeter = True - self.isOuter = ( splitLine[1] == 'outer') - elif firstWord == '()': - self.moveColoredThreadToSkeinPane() - self.isPerimeter = False - if firstWord == 'G2' or firstWord == 'G3': - relativeLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - relativeLocation.z = 0.0 - location = self.oldLocation + relativeLocation - self.linearMove(line, location) - self.oldLocation = location - - def setColoredLineColor( self, coloredLine, colorTuple ): - """Set the color and stipple of the colored line.""" - layerZoneIndex = self.getLayerZoneIndex( coloredLine.z ) - multiplier = self.repository.bottomLayerBrightness.value - if len( self.layerTops ) > 1: - multiplier += self.oneMinusBrightnessOverTopLayerIndex * float( layerZoneIndex ) - bandIndex = layerZoneIndex / self.repository.bandHeight.value - if self.repository.fromTheTop.value: - brightZoneIndex = len( self.layerTops ) - 1 - layerZoneIndex - bandIndex = brightZoneIndex / self.repository.bandHeight.value + 1 - if bandIndex % 2 == 0: - multiplier *= self.repository.bottomBandBrightness.value - red = settings.getWidthHex( int( colorTuple[0] * multiplier ), 2 ) - green = settings.getWidthHex( int( colorTuple[1] * multiplier ), 2 ) - blue = settings.getWidthHex( int( colorTuple[2] * multiplier ), 2 ) - coloredLine.colorName = '#%s%s%s' % ( red, green, blue ) - - def setColoredThread( self, colorTuple, lineList ): - """Set the colored thread, then move it to the line list and stipple of the colored line.""" - for coloredLine in self.coloredThread: - self.setColoredLineColor( coloredLine, colorTuple ) - lineList += self.coloredThread - self.coloredThread = [] - - -class SkeinPane: - """A class to hold the colored lines for a layer.""" - def __init__( self, sequenceIndex ): - """Create empty line lists.""" - self.coloredLines = [] - self.fillBottomLines = [] - self.fillTopLines = [] - self.index = 0 - self.infillLines = [] - self.layerZoneIndex = 0 - self.loopLines = [] - self.perimeterInsideLines = [] - self.perimeterOutsideLines = [] - self.raftLines = [] - self.sequenceIndex = sequenceIndex - self.travelLines = [] - - -class Ruling: - def __init__( self, modelDistance, roundedRulingText ): - """Initialize the ruling.""" - self.modelDistance = modelDistance - self.roundedRulingText = roundedRulingText - - -class SkeinWindow( tableau.TableauWindow ): - def __init__( self, repository, skein ): - """Initialize the skein window.""" - self.arrowshape = ( 24, 30, 9 ) - self.addCanvasMenuRootScrollSkein( repository, skein, '_skeiniso', 'Skeiniso') - self.center = 0.5 * self.screenSize - self.motionStippleName = 'gray75' - halfCenter = 0.5 * self.center.real - negativeHalfCenter = - halfCenter - self.halfCenterModel = halfCenter / skein.scale - negativeHalfCenterModel = - self.halfCenterModel - roundedHalfCenter = euclidean.getThreeSignificantFigures( self.halfCenterModel ) - roundedNegativeHalfCenter = euclidean.getThreeSignificantFigures( negativeHalfCenterModel ) - self.negativeAxisLineX = tableau.ColoredLine( Vector3(), 'darkorange', None, Vector3( negativeHalfCenter ), 'X Negative Axis: Origin -> %s,0,0' % roundedNegativeHalfCenter ) - self.negativeAxisLineY = tableau.ColoredLine( Vector3(), 'gold', None, Vector3( 0.0, negativeHalfCenter ), 'Y Negative Axis: Origin -> 0,%s,0' % roundedNegativeHalfCenter ) - self.negativeAxisLineZ = tableau.ColoredLine( Vector3(), 'skyblue', None, Vector3( 0.0, 0.0, negativeHalfCenter ), 'Z Negative Axis: Origin -> 0,0,%s' % roundedNegativeHalfCenter ) - self.positiveAxisLineX = tableau.ColoredLine( Vector3(), 'darkorange', None, Vector3( halfCenter ), 'X Positive Axis: Origin -> %s,0,0' % roundedHalfCenter ) - self.positiveAxisLineY = tableau.ColoredLine( Vector3(), 'gold', None, Vector3( 0.0, halfCenter ), 'Y Positive Axis: Origin -> 0,%s,0' % roundedHalfCenter ) - self.positiveAxisLineZ = tableau.ColoredLine( Vector3(), 'skyblue', None, Vector3( 0.0, 0.0, halfCenter ), 'Z Positive Axis: Origin -> 0,0,%s' % roundedHalfCenter ) - self.repository.axisRulings.setUpdateFunction( self.setWindowToDisplaySaveUpdate ) - self.repository.bandHeight.setUpdateFunction( self.setWindowToDisplaySavePhoenixUpdate ) - self.repository.bottomBandBrightness.setUpdateFunction( self.setWindowToDisplaySavePhoenixUpdate ) - self.repository.bottomLayerBrightness.setUpdateFunction( self.setWindowToDisplaySavePhoenixUpdate ) - self.repository.fromTheBottom.setUpdateFunction( self.setWindowToDisplaySavePhoenixUpdate ) - self.repository.fromTheTop.setUpdateFunction( self.setWindowToDisplaySavePhoenixUpdate ) - self.setWindowNewMouseTool( display_line.getNewMouseTool, self.repository.displayLine ) - self.setWindowNewMouseTool( view_move.getNewMouseTool, self.repository.viewMove ) - self.setWindowNewMouseTool( view_rotate.getNewMouseTool, self.repository.viewRotate ) - self.repository.numberOfFillBottomLayers.setUpdateFunction( self.setWindowToDisplaySavePhoenixUpdate ) - self.repository.numberOfFillTopLayers.setUpdateFunction( self.setWindowToDisplaySavePhoenixUpdate ) - self.repository.viewpointLatitude.setUpdateFunction( self.setWindowToDisplaySaveUpdate ) - self.repository.viewpointLongitude.setUpdateFunction( self.setWindowToDisplaySaveUpdate ) - self.repository.widthOfAxisNegativeSide.setUpdateFunction( self.setWindowToDisplaySaveUpdate ) - self.repository.widthOfAxisPositiveSide.setUpdateFunction( self.setWindowToDisplaySaveUpdate ) - self.repository.widthOfFillBottomThread.setUpdateFunction( self.setWindowToDisplaySaveUpdate ) - self.repository.widthOfFillTopThread.setUpdateFunction( self.setWindowToDisplaySaveUpdate ) - self.repository.widthOfInfillThread.setUpdateFunction( self.setWindowToDisplaySaveUpdate ) - self.repository.widthOfLoopThread.setUpdateFunction( self.setWindowToDisplaySaveUpdate ) - self.repository.widthOfPerimeterInsideThread.setUpdateFunction( self.setWindowToDisplaySaveUpdate ) - self.repository.widthOfPerimeterOutsideThread.setUpdateFunction( self.setWindowToDisplaySaveUpdate ) - self.repository.widthOfRaftThread.setUpdateFunction( self.setWindowToDisplaySaveUpdate ) - self.addMouseToolsBind() - self.negativeRulings = [] - self.positiveRulings = [] - for rulingIndex in xrange( 1, int( math.ceil( self.halfCenterModel / self.rulingSeparationWidthMillimeters ) ) ): - modelDistance = rulingIndex * self.rulingSeparationWidthMillimeters - self.negativeRulings.append( Ruling( modelDistance, self.getRoundedRulingText( 1, - modelDistance ) ) ) - self.positiveRulings.append( Ruling( modelDistance, self.getRoundedRulingText( 1, modelDistance ) ) ) - self.rulingExtentHalf = 0.5 * self.rulingExtent - - def drawRuling( self, projectiveSpace, relativeRulingEnd, ruling, tags, viewBegin, viewEnd ): - """Draw ruling.""" - alongWay = ruling.modelDistance / self.halfCenterModel - oneMinusAlongWay = 1.0 - alongWay - alongScreen = alongWay * viewEnd + oneMinusAlongWay * viewBegin - alongScreenEnd = alongScreen + relativeRulingEnd - self.canvas.create_line( - alongScreen.real, - alongScreen.imag, - alongScreenEnd.real, - alongScreenEnd.imag, - fill = 'black', - tags = tags, - width = 2 ) - self.canvas.create_text( int( alongScreenEnd.real ) + 3, alongScreenEnd.imag, anchor = settings.Tkinter.W, text = ruling.roundedRulingText ) - - def drawRulings( self, axisLine, projectiveSpace, rulings ): - """Draw rulings for the axis line.""" - if not self.repository.axisRulings.value: - return - viewBegin = self.getScreenView( axisLine.begin, projectiveSpace ) - viewEnd = self.getScreenView( axisLine.end, projectiveSpace ) - viewSegment = viewEnd - viewBegin - viewSegmentLength = abs( viewSegment ) - if viewSegmentLength < self.rulingExtent: - return - normalizedViewSegment = viewSegment / viewSegmentLength - relativeRulingEnd = complex( - normalizedViewSegment.imag, normalizedViewSegment.real ) - if normalizedViewSegment.imag > 0.0: - relativeRulingEnd = complex( normalizedViewSegment.imag, - normalizedViewSegment.real ) - for ruling in rulings: - self.drawRuling( projectiveSpace, relativeRulingEnd * self.rulingExtentHalf, ruling, axisLine.tagString, viewBegin, viewEnd ) - - def drawSkeinPane( self, projectiveSpace, skeinPane ): - """Draw colored lines.""" - self.getDrawnColoredLines( skeinPane.raftLines, projectiveSpace, self.repository.widthOfRaftThread.value ) - self.getDrawnColoredLines( skeinPane.travelLines, projectiveSpace, self.repository.widthOfTravelThread.value ) - self.getDrawnColoredLines( skeinPane.fillBottomLines, projectiveSpace, self.repository.widthOfFillBottomThread.value ) - self.getDrawnColoredLines( skeinPane.fillTopLines, projectiveSpace, self.repository.widthOfFillTopThread.value ) - self.getDrawnColoredLines( skeinPane.infillLines, projectiveSpace, self.repository.widthOfInfillThread.value ) - self.getDrawnColoredLines( skeinPane.loopLines, projectiveSpace, self.repository.widthOfLoopThread.value ) - self.getDrawnColoredLines( skeinPane.perimeterInsideLines, projectiveSpace, self.repository.widthOfPerimeterInsideThread.value ) - self.getDrawnColoredLines( skeinPane.perimeterOutsideLines, projectiveSpace, self.repository.widthOfPerimeterOutsideThread.value ) - - def drawXYAxisLines( self, projectiveSpace ): - """Draw the x and y axis lines.""" - if self.repository.widthOfAxisNegativeSide.value > 0: - self.getDrawnColoredLineWithoutArrow( self.negativeAxisLineX, projectiveSpace, self.negativeAxisLineX.tagString, self.repository.widthOfAxisNegativeSide.value ) - self.getDrawnColoredLineWithoutArrow( self.negativeAxisLineY, projectiveSpace, self.negativeAxisLineY.tagString, self.repository.widthOfAxisNegativeSide.value ) - if self.repository.widthOfAxisPositiveSide.value > 0: - self.getDrawnColoredLine('last', self.positiveAxisLineX, projectiveSpace, self.positiveAxisLineX.tagString, self.repository.widthOfAxisPositiveSide.value ) - self.getDrawnColoredLine('last', self.positiveAxisLineY, projectiveSpace, self.positiveAxisLineY.tagString, self.repository.widthOfAxisPositiveSide.value ) - - def drawZAxisLine( self, projectiveSpace ): - """Draw the z axis line.""" - if self.repository.widthOfAxisNegativeSide.value > 0: - self.getDrawnColoredLineWithoutArrow( self.negativeAxisLineZ, projectiveSpace, self.negativeAxisLineZ.tagString, self.repository.widthOfAxisNegativeSide.value ) - if self.repository.widthOfAxisPositiveSide.value > 0: - self.getDrawnColoredLine('last', self.positiveAxisLineZ, projectiveSpace, self.positiveAxisLineZ.tagString, self.repository.widthOfAxisPositiveSide.value ) - - def getCentered( self, coordinate ): - """Get the centered coordinate.""" - relativeToCenter = complex( coordinate.real - self.center.real, self.center.imag - coordinate.imag ) - if abs( relativeToCenter ) < 1.0: - relativeToCenter = complex( 0.0, 1.0 ) - return relativeToCenter - - def getCanvasRadius(self): - """Get half of the minimum of the canvas height and width.""" - return 0.5 * min( float( self.canvasHeight ), float( self.canvasWidth ) ) - - def getCenteredScreened( self, coordinate ): - """Get the normalized centered coordinate.""" - return self.getCentered( coordinate ) / self.getCanvasRadius() - - def getColoredLines(self): - """Get the colored lines from the skein pane.""" - return self.skeinPanes[ self.repository.layer.value ].coloredLines - - def getCopy(self): - """Get a copy of this window.""" - return SkeinWindow( self.repository, self.skein ) - - def getCopyWithNewSkein(self): - """Get a copy of this window with a new skein.""" - return getWindowGivenTextRepository( self.skein.fileName, self.skein.gcodeText, self.repository ) - - def getDrawnColoredLine( self, arrowType, coloredLine, projectiveSpace, tags, width ): - """Draw colored line.""" - viewBegin = self.getScreenView( coloredLine.begin, projectiveSpace ) - viewEnd = self.getScreenView( coloredLine.end, projectiveSpace ) - return self.canvas.create_line( - viewBegin.real, - viewBegin.imag, - viewEnd.real, - viewEnd.imag, - fill = coloredLine.colorName, - arrow = arrowType, - tags = tags, - width = width ) - - def getDrawnColoredLineMotion( self, coloredLine, projectiveSpace, width ): - """Draw colored line with motion stipple and tag.""" - viewBegin = self.getScreenView( coloredLine.begin, projectiveSpace ) - viewEnd = self.getScreenView( coloredLine.end, projectiveSpace ) - return self.canvas.create_line( - viewBegin.real, - viewBegin.imag, - viewEnd.real, - viewEnd.imag, - fill = coloredLine.colorName, - arrow = 'last', - arrowshape = self.arrowshape, - stipple = self.motionStippleName, - tags = 'mouse_item', - width = width + 4 ) - - def getDrawnColoredLines( self, coloredLines, projectiveSpace, width ): - """Draw colored lines.""" - if width <= 0: - return - drawnColoredLines = [] - for coloredLine in coloredLines: - drawnColoredLines.append( self.getDrawnColoredLine( self.arrowType, coloredLine, projectiveSpace, coloredLine.tagString, width ) ) - return drawnColoredLines - - def getDrawnColoredLineWithoutArrow( self, coloredLine, projectiveSpace, tags, width ): - """Draw colored line without an arrow.""" - viewBegin = self.getScreenView( coloredLine.begin, projectiveSpace ) - viewEnd = self.getScreenView( coloredLine.end, projectiveSpace ) - return self.canvas.create_line( - viewBegin.real, - viewBegin.imag, - viewEnd.real, - viewEnd.imag, - fill = coloredLine.colorName, - tags = tags, - width = width ) - - def getDrawnSelectedColoredLine( self, coloredLine ): - """Get the drawn selected colored line.""" - projectiveSpace = euclidean.ProjectiveSpace().getByLatitudeLongitude( self.repository.viewpointLatitude.value, self.repository.viewpointLongitude.value ) - return self.getDrawnColoredLine( self.arrowType, coloredLine, projectiveSpace, 'selection_line', self.repository.widthOfSelectionThread.value ) - - def getScreenComplex( self, pointComplex ): - """Get the point in screen perspective.""" - return complex( pointComplex.real, - pointComplex.imag ) + self.center - - def getScreenView( self, point, projectiveSpace ): - """Get the point in screen view perspective.""" - return self.getScreenComplex( projectiveSpace.getDotComplex(point) ) - - def printHexadecimalColorName(self, name): - """Print the color name in hexadecimal.""" - colorTuple = self.canvas.winfo_rgb( name ) - print('#%s%s%s' % ( settings.getWidthHex( colorTuple[0], 2 ), settings.getWidthHex( colorTuple[1], 2 ), settings.getWidthHex( colorTuple[2], 2 ) ) ) - - def update(self): - """Update the screen.""" - if len( self.skeinPanes ) < 1: - return - self.limitIndexSetArrowMouseDeleteCanvas() - self.repository.viewpointLatitude.value = view_rotate.getBoundedLatitude( self.repository.viewpointLatitude.value ) - self.repository.viewpointLongitude.value = round( self.repository.viewpointLongitude.value, 1 ) - projectiveSpace = euclidean.ProjectiveSpace().getByLatitudeLongitude( self.repository.viewpointLatitude.value, self.repository.viewpointLongitude.value ) - skeinPanesCopy = self.getUpdateSkeinPanes()[:] - skeinPanesCopy.sort( compareLayerSequence ) - if projectiveSpace.basisZ.z > 0.0: - self.drawXYAxisLines( projectiveSpace ) - else: - skeinPanesCopy.reverse() - self.drawZAxisLine( projectiveSpace ) - for skeinPane in skeinPanesCopy: - self.drawSkeinPane( projectiveSpace, skeinPane ) - if projectiveSpace.basisZ.z > 0.0: - self.drawZAxisLine( projectiveSpace ) - else: - self.drawXYAxisLines( projectiveSpace ) - if self.repository.widthOfAxisNegativeSide.value > 0: - self.drawRulings( self.negativeAxisLineX, projectiveSpace, self.negativeRulings ) - self.drawRulings( self.negativeAxisLineY, projectiveSpace, self.negativeRulings ) - self.drawRulings( self.negativeAxisLineZ, projectiveSpace, self.negativeRulings ) - if self.repository.widthOfAxisPositiveSide.value > 0: - self.drawRulings( self.positiveAxisLineX, projectiveSpace, self.positiveRulings ) - self.drawRulings( self.positiveAxisLineY, projectiveSpace, self.positiveRulings ) - self.drawRulings( self.positiveAxisLineZ, projectiveSpace, self.positiveRulings ) - self.setDisplayLayerIndex() - - -def main(): - """Display the skeiniso dialog.""" - if len(sys.argv) > 1: - settings.startMainLoopFromWindow( getWindowAnalyzeFile(' '.join(sys.argv[1 :])) ) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/skeinlayer.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/skeinlayer.py deleted file mode 100644 index 0ac009d..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/skeinlayer.py +++ /dev/null @@ -1,575 +0,0 @@ -""" -This page is in the table of contents. -Skeinlayer is a script to display each layer of a gcode file. - -The skeinlayer manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Skeinlayer - -Skeinlayer is derived from Nophead's preview script. The extruded lines are in the resistor colors red, orange, yellow, green, blue, purple & brown. When the extruder is off, the travel line is grey. Skeinlayer is useful for a detailed view of the extrusion, skeiniso is better to see the orientation of the shape. To get an initial overview of the skein, when the skeinlayer display window appears, click the Soar button (double right arrow button beside the layer field). - -==Operation== -The default 'Activate Skeinlayer' checkbox is on. When it is on, the functions described below will work when called from the skeinforge toolchain, when it is off, the functions will not be called from the toolchain. The functions will still be called, whether or not the 'Activate Skeinlayer' checkbox is on, when skeinlayer is run directly. Skeinlayer has trouble separating the layers when it reads gcode without comments. - -==Settings== -===Animation=== -====Animation Line Quickening==== -Default is one. - -The quickness of the tool animation over the quickness of the actual tool. - -====Animation Slide Show Rate==== -Default is two layers per second. - -The rate, in layers per second, at which the layer changes when the soar or dive button is pressed.. - -===Draw Arrows=== -Default is on. - -When selected, arrows will be drawn at the end of each line segment. - -===Export Menu=== -When the submenu in the export menu item in the file menu is clicked, an export canvas dialog will be displayed, which can export the canvas to a file. - -===Go Around Extruder Off Travel=== -Default is off. - -When selected, the display will include the travel when the extruder is off, which means it will include the nozzle wipe path if any. - -===Layers=== -====Layer==== -Default is zero. - -On the display window, the Up button increases the 'Layer' by one, and the Down button decreases the layer by one. When the layer displayed in the layer spin box is changed then is hit, the layer shown will be set to the spin box, to a mimimum of zero and to a maximum of the highest index layer.The Soar button increases the layer at the 'Animation Slide Show Rate', and the Dive (double left arrow button beside the layer field) button decreases the layer at the slide show rate. - -====Layer Extra Span==== -Default is zero. - -The viewer will draw the layers in the range including the 'Layer' index and the 'Layer' index plus the 'Layer Extra Span'. If the 'Layer Extra Span' is negative, the layers viewed will start at the 'Layer' index, plus the 'Layer Extra Span', and go up to and include the 'Layer' index. If the 'Layer Extra Span' is zero, only the 'Layer' index layer will be displayed. If the 'Layer Extra Span' is positive, the layers viewed will start at the 'Layer' index, and go up to and include the 'Layer' index plus the 'Layer Extra Span'. - -===Line=== -Default is zero. - -The index of the selected line on the layer that is highlighted when the 'Display Line' mouse tool is chosen. The line spin box up button increases the 'Line' by one. If the line index of the layer goes over the index of the last line, the layer index will be increased by one and the new line index will be zero. The down button decreases the line index by one. If the line index goes below the index of the first line, the layer index will be decreased by one and the new line index will be at the last line. When the line displayed in the line field is changed then is hit, the line shown will be set to the line field, to a mimimum of zero and to a maximum of the highest index line. The Soar button increases the line at the speed at which the extruder would move, times the 'Animation Line Quickening' ratio, and the Dive (double left arrow button beside the line field) button decreases the line at the animation line quickening ratio. - -===Mouse Mode=== -Default is 'Display Line'. - -The mouse tool can be changed from the 'Mouse Mode' menu button or picture button. The mouse tools listen to the arrow keys when the canvas has the focus. Clicking in the canvas gives the canvas the focus, and when the canvas has the focus a thick black border is drawn around the canvas. - -====Display Line==== -The 'Display Line' tool will display the highlight the selected line, and display the file line count, counting from one, and the gcode line itself. When the 'Display Line' tool is active, clicking the canvas will select the nearest line to the mouse click. - -====Viewpoint Move==== -The 'Viewpoint Move' tool will move the viewpoint in the xy plane when the mouse is clicked and dragged on the canvas. - -===Numeric Pointer=== -Default is on. - -When selected, the distance along the ruler of the arrow pointers will be drawn next to the pointers. - -===Scale=== -Default is ten. - -The scale setting is the scale of the image in pixels per millimeter, the higher the number, the greater the size of the display. - -The zoom in mouse tool will zoom in the display at the point where the mouse was clicked, increasing the scale by a factor of two. The zoom out tool will zoom out the display at the point where the mouse was clicked, decreasing the scale by a factor of two. - -===Screen Inset=== -====Screen Horizontal Inset==== -Default is one hundred. - -The "Screen Horizontal Inset" determines how much the canvas will be inset in the horizontal direction from the edge of screen, the higher the number the more it will be inset and the smaller it will be. - -====Screen Vertical Inset==== -Default is two hundred and twenty. - -The "Screen Vertical Inset" determines how much the canvas will be inset in the vertical direction from the edge of screen, the higher the number the more it will be inset and the smaller it will be. - -===Width=== -The width of each type of thread and of each axis can be changed. If the width is set to zero, the thread will not be visible. - -====Width of Extrusion Thread==== -Default is three. - -The "Width of Extrusion Thread" sets the width of the extrusion threads. - -====Width of Selection Thread==== -Default is six. - -The "Width of Selection Thread" sets the width of the selected line. - -====Width of Travel Thread==== -Default is one. - -The "Width of Travel Thread" sets the width of the grey extruder off travel threads. - -==Icons== -The dive, soar and zoom icons are from Mark James' soarSilk icon set 1.3 at: -http://www.famfamfam.com/lab/icons/silk/ - -==Gcodes== -An explanation of the gcodes is at: -http://reprap.org/bin/view/Main/Arduino_GCode_Interpreter - -and at: -http://reprap.org/bin/view/Main/MCodeReference - -A gode example is at: -http://forums.reprap.org/file.php?12,file=565 - -==Examples== -Below are examples of skeinlayer being used. These examples are run in a terminal in the folder which contains Screw Holder_penultimate.gcode and skeinlayer.py. - -> python skeinlayer.py -This brings up the skeinlayer dialog. - -> python skeinlayer.py Screw Holder_penultimate.gcode -This brings up the skeinlayer viewer to view each layer of a gcode file. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_plugins.analyze_plugins.analyze_utilities import display_line -from skeinforge_application.skeinforge_plugins.analyze_plugins.analyze_utilities import tableau -from skeinforge_application.skeinforge_plugins.analyze_plugins.analyze_utilities import view_move -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import os -import sys - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewRepository(): - """Get new repository.""" - return SkeinlayerRepository() - -def getRankIndex( rulingSeparationWidthMillimeters, screenOrdinate ): - """Get rank index.""" - return int( round( screenOrdinate / rulingSeparationWidthMillimeters ) ) - -def getWindowAnalyzeFile(fileName): - """Display a gcode file in a skeinlayer window.""" - gcodeText = archive.getFileText(fileName) - return getWindowAnalyzeFileGivenText(fileName, gcodeText) - -def getWindowAnalyzeFileGivenText( fileName, gcodeText, repository=None): - """Display a gcode file in a skeinlayer window given the text.""" - if gcodeText == '': - return None - if repository is None: - repository = settings.getReadRepository( SkeinlayerRepository() ) - skeinWindow = getWindowGivenTextRepository( fileName, gcodeText, repository ) - skeinWindow.updateDeiconify() - return skeinWindow - -def getWindowGivenTextRepository( fileName, gcodeText, repository ): - """Display a gcode file in a skeinlayer window given the text and settings.""" - skein = SkeinlayerSkein() - skein.parseGcode( fileName, gcodeText, repository ) - return SkeinWindow( repository, skein ) - -def writeOutput(fileName, fileNamePenultimate, fileNameSuffix, filePenultimateWritten, gcodeText=''): - """Display a skeinlayered gcode file for a skeinforge gcode file, if 'Activate Skeinlayer' is selected.""" - try: - import Tkinter - except: - print('Warning, skeinlayer will do nothing because Tkinter is not installed.') - return - repository = settings.getReadRepository( SkeinlayerRepository() ) - if repository.activateSkeinlayer.value: - gcodeText = archive.getTextIfEmpty( fileNameSuffix, gcodeText ) - return getWindowAnalyzeFileGivenText( fileNameSuffix, gcodeText, repository ) - - -class SkeinlayerRepository( tableau.TableauRepository ): - """A class to handle the skeinlayer settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.analyze_plugins.skeinlayer.html', self) - self.baseNameSynonym = 'skeinview.csv' - self.fileNameInput = settings.FileNameInput().getFromFileName( [ ('Gcode text files', '*.gcode') ], 'Open File for Skeinlayer', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Skeinlayer') - self.activateSkeinlayer = settings.BooleanSetting().getFromValue('Activate Skeinlayer', self, True ) - self.addAnimation() - self.drawArrows = settings.BooleanSetting().getFromValue('Draw Arrows', self, True ) - self.goAroundExtruderOffTravel = settings.BooleanSetting().getFromValue('Go Around Extruder Off Travel', self, False ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Layers -', self ) - self.layer = settings.IntSpinNotOnMenu().getSingleIncrementFromValue( 0, 'Layer (index):', self, 912345678, 0 ) - self.layerExtraSpan = settings.IntSpinUpdate().getSingleIncrementFromValue( - 3, 'Layer Extra Span (integer):', self, 3, 0 ) - settings.LabelSeparator().getFromRepository(self) - self.line = settings.IntSpinNotOnMenu().getSingleIncrementFromValue( 0, 'Line (index):', self, 912345678, 0 ) - self.mouseMode = settings.MenuButtonDisplay().getFromName('Mouse Mode:', self ) - self.displayLine = settings.MenuRadio().getFromMenuButtonDisplay( self.mouseMode, 'Display Line', self, True ) - self.viewMove = settings.MenuRadio().getFromMenuButtonDisplay( self.mouseMode, 'View Move', self, False ) - self.addScaleScreenSlide() - self.showPosition = settings.BooleanSetting().getFromValue('Show Position', self, True ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Width -', self ) - self.widthOfExtrusionThread = settings.IntSpinUpdate().getSingleIncrementFromValue( 0, 'Width of Extrusion Thread (pixels):', self, 5, 3 ) - self.widthOfSelectionThread = settings.IntSpinUpdate().getSingleIncrementFromValue( 0, 'Width of Selection Thread (pixels):', self, 10, 6 ) - self.widthOfTravelThread = settings.IntSpinUpdate().getSingleIncrementFromValue( 0, 'Width of Travel Thread (pixels):', self, 5, 1 ) - self.executeTitle = 'Skeinlayer' - - def execute(self): - """Write button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrGcodeDirectory( self.fileNameInput.value, self.fileNameInput.wasCancelled ) - for fileName in fileNames: - getWindowAnalyzeFile(fileName) - - -class SkeinlayerSkein: - """A class to write a get a scalable vector graphics text for a gcode skein.""" - def __init__(self): - """Initialize.""" - self.extrusionNumber = 0 - self.feedRateMinute = 960.1 - self.isThereALayerStartWord = False - self.layerCount = settings.LayerCount() - self.oldZ = - 999987654321.0 - self.skeinPane = None - self.skeinPanes = [] - - def addToPath( self, line, location ): - """Add a point to travel and maybe extrusion.""" - if self.oldLocation is None: - return - colorName = 'gray' - locationComplex = location.dropAxis() - oldLocationComplex = self.oldLocation.dropAxis() - begin = self.getScreenCoordinates( oldLocationComplex ) - end = self.getScreenCoordinates( locationComplex ) - if self.extruderActive: - colorName = self.colorNames[ self.extrusionNumber % len( self.colorNames ) ] - displayString = '%s %s' % ( self.lineIndex + 1, line ) - tagString = 'colored_line_index: %s %s' % ( len( self.skeinPane ), len( self.skeinPanes ) - 1 ) - coloredLine = tableau.ColoredLine( begin, colorName, displayString, end, tagString ) - coloredLine.isExtrusionThread = self.extruderActive - self.skeinPane.append( coloredLine ) - - def getModelCoordinates( self, screenCoordinates ): - """Get the model coordinates.""" - modelCoordinates = ( screenCoordinates + self.marginCornerLow ) / self.scale - return complex( modelCoordinates.real, self.cornerImaginaryTotal - modelCoordinates.imag ) - - def getScreenCoordinates( self, pointComplex ): - """Get the screen coordinates.""" - pointComplex = complex( pointComplex.real, self.cornerImaginaryTotal - pointComplex.imag ) - return self.scale * pointComplex - self.marginCornerLow - - def initializeActiveLocation(self): - """Set variables to default.""" - self.extruderActive = False - self.oldLocation = None - - def linearCorner( self, splitLine ): - """Update the bounding corners.""" - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - if self.extruderActive or self.repository.goAroundExtruderOffTravel.value: - self.cornerMaximum.maximize(location) - self.cornerMinimum.minimize(location) - self.oldLocation = location - - def linearMove( self, line, location ): - """Get statistics for a linear move.""" - if self.skeinPane is not None: - self.addToPath(line, location) - - def parseCorner(self, line): - """Parse a gcode line and use the location to update the bounding corners.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - self.linearCorner(splitLine) - elif firstWord == 'M101': - self.extruderActive = True - elif firstWord == 'M103': - self.extruderActive = False - - def parseGcode( self, fileName, gcodeText, repository ): - """Parse gcode text and store the vector output.""" - self.fileName = fileName - self.gcodeText = gcodeText - self.repository = repository - self.initializeActiveLocation() - self.cornerMaximum = Vector3(-987654321.0, -987654321.0, -987654321.0) - self.cornerMinimum = Vector3(987654321.0, 987654321.0, 987654321.0) - self.lines = archive.getTextLines(gcodeText) - self.isThereALayerStartWord = (gcodec.getFirstWordIndexReverse('(', self.lines, 1) > -1) - self.parseInitialization() - for line in self.lines[self.lineIndex :]: - self.parseCorner(line) - self.cornerMaximumComplex = self.cornerMaximum.dropAxis() - self.cornerMinimumComplex = self.cornerMinimum.dropAxis() - self.scale = repository.scale.value - self.scaleCornerHigh = self.scale * self.cornerMaximumComplex - self.scaleCornerLow = self.scale * self.cornerMinimumComplex - self.cornerImaginaryTotal = self.cornerMaximum.y + self.cornerMinimum.y - self.margin = complex( 10.0, 10.0 ) - self.marginCornerHigh = self.scaleCornerHigh + self.margin - self.marginCornerLow = self.scaleCornerLow - self.margin - self.screenSize = self.marginCornerHigh - self.marginCornerLow - self.initializeActiveLocation() - self.colorNames = ['brown', 'red', 'orange', 'yellow', 'green', 'blue', 'purple'] - for self.lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[self.lineIndex] - self.parseLine(line) - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == '()': - return - elif firstWord == '(': - self.feedRateMinute = 60.0 * float(splitLine[1]) - self.lineIndex = 0 - - def parseLine(self, line): - """Parse a gcode line and add it to the vector output.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if tableau.getIsLayerStart(firstWord, self, splitLine): - self.extrusionNumber = 0 - self.layerCount.printProgressIncrement('skeinlayer') - self.skeinPane = [] - self.skeinPanes.append( self.skeinPane ) - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - self.linearMove(line, location) - self.oldLocation = location - elif firstWord == 'M101': - self.extruderActive = True - self.extrusionNumber += 1 - elif firstWord == 'M103': - self.extruderActive = False - if firstWord == 'G2' or firstWord == 'G3': - relativeLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - relativeLocation.z = 0.0 - location = self.oldLocation + relativeLocation - self.linearMove(line, location) - self.oldLocation = location - - -class SkeinWindow( tableau.TableauWindow ): - def __init__(self, repository, skein): - """Initialize the skein window.setWindowNewMouseTool""" - self.addCanvasMenuRootScrollSkein(repository, skein, '_skeinlayer', 'Skeinlayer') - horizontalRulerBoundingBox = (0, 0, int( skein.screenSize.real ), self.rulingExtent) - self.horizontalRulerCanvas = settings.Tkinter.Canvas(self.root, width = self.canvasWidth, height = self.rulingExtent, scrollregion=horizontalRulerBoundingBox) - self.horizontalRulerCanvas.grid(row=1, column=2, columnspan=96, sticky=settings.Tkinter.E+settings.Tkinter.W) - self.horizontalRulerCanvas['xscrollcommand'] = self.xScrollbar.set - verticalRulerBoundingBox = (0, 0, self.rulingExtent, int(skein.screenSize.imag)) - self.verticalRulerCanvas = settings.Tkinter.Canvas(self.root, width=self.rulingExtent, height=self.canvasHeight, scrollregion=verticalRulerBoundingBox) - self.verticalRulerCanvas.grid(row=2, rowspan=96, column=1, sticky=settings.Tkinter.N+settings.Tkinter.S) - self.verticalRulerCanvas['yscrollcommand'] = self.yScrollbar.set - self.xStringVar = settings.Tkinter.StringVar(self.root) - self.xLabel = settings.Tkinter.Label(self.root, textvariable=self.xStringVar) - self.xLabel.grid(row=0, column=3, sticky=settings.Tkinter.W) - self.yStringVar = settings.Tkinter.StringVar(self.root) - self.yLabel = settings.Tkinter.Label(self.root, textvariable=self.yStringVar) - self.yLabel.grid(row=0, column=4, sticky=settings.Tkinter.W) - self.setWindowNewMouseTool(display_line.getNewMouseTool, repository.displayLine) - self.setWindowNewMouseTool(view_move.getNewMouseTool, repository.viewMove) - repository.showPosition.setUpdateFunction(self.setWindowToDisplaySaveUpdate) - repository.widthOfExtrusionThread.setUpdateFunction(self.setWindowToDisplaySaveUpdate) - self.addMouseToolsBind() - self.createRulers() - - def addHorizontalRulerRuling( self, xMillimeters ): - """Add a ruling to the horizontal ruler.""" - xPixel = self.skein.getScreenCoordinates( complex( xMillimeters, 0.0 ) ).real - self.createVerticalLine( 0.0, xPixel ) - self.horizontalRulerCanvas.create_text( xPixel + 2, 0, anchor = settings.Tkinter.NW, text = self.getRoundedRulingText( 1, xMillimeters ) ) - cumulativeDistance = xMillimeters - self.createVerticalLine( self.rulingExtentTiny, self.skein.getScreenCoordinates( complex( xMillimeters + self.separationWidthMillimetersTenth, 0.0 ) ).real ) - for subRulingIndex in xrange(4): - cumulativeDistance += self.separationWidthMillimetersFifth - self.createVerticalLine( self.rulingExtentShort, self.skein.getScreenCoordinates( complex( cumulativeDistance, 0.0 ) ).real ) - self.createVerticalLine( self.rulingExtentTiny, self.skein.getScreenCoordinates( complex( cumulativeDistance + self.separationWidthMillimetersTenth, 0.0 ) ).real ) - - def addVerticalRulerRuling( self, yMillimeters ): - """Add a ruling to the vertical ruler.""" - fontHeight = 12 - yPixel = self.skein.getScreenCoordinates( complex( 0.0, yMillimeters ) ).imag - self.createHorizontalLine( 0.0, yPixel ) - yPixel += 2 - roundedRulingText = self.getRoundedRulingText( 1, yMillimeters ) - effectiveRulingTextLength = len( roundedRulingText ) - if roundedRulingText.find('.') != - 1: - effectiveRulingTextLength -= 1 - cumulativeDistance = yMillimeters - self.createHorizontalLine( self.rulingExtentTiny, self.skein.getScreenCoordinates( complex( 0.0, yMillimeters + self.separationWidthMillimetersTenth ) ).imag ) - for subRulingIndex in xrange(4): - cumulativeDistance += self.separationWidthMillimetersFifth - self.createHorizontalLine( self.rulingExtentShort, self.skein.getScreenCoordinates( complex( 0.0, cumulativeDistance ) ).imag ) - self.createHorizontalLine( self.rulingExtentTiny, self.skein.getScreenCoordinates( complex( 0.0, cumulativeDistance + self.separationWidthMillimetersTenth ) ).imag ) - if effectiveRulingTextLength < 4: - self.verticalRulerCanvas.create_text( 0, yPixel, anchor = settings.Tkinter.NW, text = roundedRulingText ) - return - for character in roundedRulingText: - if character == '.': - yPixel -= fontHeight * 2 / 3 - self.verticalRulerCanvas.create_text( 0, yPixel, anchor = settings.Tkinter.NW, text = character ) - yPixel += fontHeight - - def createHorizontalLine( self, begin, yPixel ): - """Create a horizontal line for the horizontal ruler.""" - self.verticalRulerCanvas.create_line( begin, yPixel, self.rulingExtent, yPixel, fill = 'black') - - def createRulers(self): - """Create the rulers..""" - self.rulingExtentShort = 0.382 * self.rulingExtent - self.rulingExtentTiny = 0.764 * self.rulingExtent - self.rulingExtentPointer = 0.5 * ( self.rulingExtentShort + self.rulingExtentTiny ) - self.rulingPointerRadius = self.rulingExtent - self.rulingExtentPointer - self.textBoxHeight = int( 0.8 * self.rulingExtent ) - self.textBoxWidth = int( 2.5 * self.rulingExtent ) - self.separationWidthMillimetersFifth = 0.2 * self.rulingSeparationWidthMillimeters - self.separationWidthMillimetersTenth = 0.1 * self.rulingSeparationWidthMillimeters - rulingSeparationWidthPixels = self.getRulingSeparationWidthPixels( self.rank ) - marginOverScale = self.skein.margin / self.skein.scale - cornerMaximumMargin = self.skein.cornerMaximumComplex + marginOverScale - cornerMinimumMargin = self.skein.cornerMinimumComplex - marginOverScale - xRankIndexHigh = getRankIndex( self.rulingSeparationWidthMillimeters, cornerMaximumMargin.real ) - xRankIndexLow = getRankIndex( self.rulingSeparationWidthMillimeters, cornerMinimumMargin.real ) - for xRankIndex in xrange( xRankIndexLow - 2, xRankIndexHigh + 2 ): # 1 is enough, 2 is to be on the safe side - self.addHorizontalRulerRuling( xRankIndex * self.rulingSeparationWidthMillimeters ) - yRankIndexHigh = getRankIndex( self.rulingSeparationWidthMillimeters, cornerMaximumMargin.imag ) - yRankIndexLow = getRankIndex( self.rulingSeparationWidthMillimeters, cornerMinimumMargin.imag ) - for yRankIndex in xrange( yRankIndexLow - 2, yRankIndexHigh + 2 ): # 1 is enough, 2 is to be on the safe side - self.addVerticalRulerRuling( yRankIndex * self.rulingSeparationWidthMillimeters ) - - def createVerticalLine( self, begin, xPixel ): - """Create a vertical line for the horizontal ruler.""" - self.horizontalRulerCanvas.create_line( xPixel, begin, xPixel, self.rulingExtent, fill = 'black') - - def getColoredLines(self): - """Get the colored lines from the skein pane.""" - return self.skeinPanes[self.repository.layer.value] - - def getCopy(self): - """Get a copy of this window.""" - return SkeinWindow(self.repository, self.skein) - - def getCopyWithNewSkein(self): - """Get a copy of this window with a new skein.""" - return getWindowGivenTextRepository( self.skein.fileName, self.skein.gcodeText, self.repository ) - - def getDrawnColoredLine( self, coloredLine, tags, width ): - """Get the drawn colored line.""" - return self.canvas.create_line( - coloredLine.begin.real, - coloredLine.begin.imag, - coloredLine.end.real, - coloredLine.end.imag, - fill = coloredLine.colorName, - arrow = self.arrowType, - tags = tags, - width = width ) - - def getDrawnColoredLineIfThick( self, coloredLine, width ): - """Get the drawn colored line if it has a positive thickness.""" - if width > 0: - return self.getDrawnColoredLine( coloredLine, coloredLine.tagString, width ) - - def getDrawnSelectedColoredLine(self, coloredLine): - """Get the drawn selected colored line.""" - return self.getDrawnColoredLine(coloredLine, 'selection_line', self.repository.widthOfSelectionThread.value) - - def motion(self, event): - """The mouse moved.""" - self.mouseTool.motion(event) - xString = '' - yString = '' - x = self.canvas.canvasx( event.x ) - y = self.canvas.canvasy( event.y ) - self.horizontalRulerCanvas.delete('pointer') - self.horizontalRulerCanvas.create_polygon( x - self.rulingPointerRadius, self.rulingExtentPointer, x + self.rulingPointerRadius, self.rulingExtentPointer, x, self.rulingExtent, tag = 'pointer') - self.verticalRulerCanvas.delete('pointer') - self.verticalRulerCanvas.create_polygon( self.rulingExtentPointer, y - self.rulingPointerRadius, self.rulingExtentPointer, y + self.rulingPointerRadius, self.rulingExtent, y, tag = 'pointer') - if self.repository.showPosition.value: - motionCoordinate = complex(x, y) - modelCoordinates = self.skein.getModelCoordinates( motionCoordinate ) - roundedXText = self.getRoundedRulingText(3, modelCoordinates.real) - roundedYText = self.getRoundedRulingText(3, modelCoordinates.imag) - xString = 'X: ' + roundedXText - yString = 'Y: ' + roundedYText - self.xStringVar.set(xString) - self.yStringVar.set(yString) - - def qqqmotion(self, event): - """The mouse moved.""" - self.mouseTool.motion(event) - x = self.canvas.canvasx( event.x ) - y = self.canvas.canvasy( event.y ) - self.horizontalRulerCanvas.delete('pointer') - self.horizontalRulerCanvas.create_polygon( x - self.rulingPointerRadius, self.rulingExtentPointer, x + self.rulingPointerRadius, self.rulingExtentPointer, x, self.rulingExtent, tag = 'pointer') - self.verticalRulerCanvas.delete('pointer') - self.verticalRulerCanvas.create_polygon( self.rulingExtentPointer, y - self.rulingPointerRadius, self.rulingExtentPointer, y + self.rulingPointerRadius, self.rulingExtent, y, tag = 'pointer') - if not self.repository.numericPointer.value: - return - motionCoordinate = complex(x, y) - modelCoordinates = self.skein.getModelCoordinates( motionCoordinate ) - roundedXText = self.getRoundedRulingText( 3, modelCoordinates.real ) - yStart = self.canvas.canvasy( 0 ) - self.canvas.create_rectangle( x - 2, yStart, x + self.textBoxWidth, yStart + self.textBoxHeight + 5, fill = self.canvas['background'], tag = 'pointer') - self.canvas.create_text( x, yStart + 5, anchor = settings.Tkinter.NW, tag = 'pointer', text = roundedXText ) - roundedYText = self.getRoundedRulingText( 3, modelCoordinates.imag ) - xStart = self.canvas.canvasx( 0 ) - self.canvas.create_rectangle( xStart, y - 2, xStart + self.textBoxWidth + 5, y + self.textBoxHeight, fill = self.canvas['background'], tag = 'pointer') - self.canvas.create_text( xStart + 5, y, anchor = settings.Tkinter.NW, tag = 'pointer', text = roundedYText ) - xString = '' - xString = 'X: ' + roundedXText - self.xStringVar.set(xString) - - def relayXview( self, *args ): - """Relay xview changes.""" - self.canvas.xview( *args ) - self.horizontalRulerCanvas.xview( *args ) - - def relayYview( self, *args ): - """Relay yview changes.""" - self.canvas.yview( *args ) - self.verticalRulerCanvas.yview( *args ) - - def update(self): - """Update the window.""" - if len( self.skeinPanes ) < 1: - return - self.limitIndexSetArrowMouseDeleteCanvas() - for coloredLines in self.getUpdateSkeinPanes(): - for coloredLine in coloredLines: - if coloredLine.isExtrusionThread: - self.getDrawnColoredLineIfThick( coloredLine, self.repository.widthOfExtrusionThread.value ) - else: - self.getDrawnColoredLineIfThick( coloredLine, self.repository.widthOfTravelThread.value ) - self.setDisplayLayerIndex() - - -def main(): - """Display the skeinlayer dialog.""" - if len(sys.argv) > 1: - settings.startMainLoopFromWindow(getWindowAnalyzeFile(' '.join(sys.argv[1 :]))) - else: - settings.startMainLoopFromConstructor(getNewRepository()) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/statistic.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/statistic.py deleted file mode 100644 index 0035f51..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/statistic.py +++ /dev/null @@ -1,348 +0,0 @@ -""" -This page is in the table of contents. -Statistic is a script to generate statistics a gcode file. - -The statistic manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Statistic - -==Operation== -The default 'Activate Statistic' checkbox is on. When it is on, the functions described below will work when called from the skeinforge toolchain, when it is off, the functions will not be called from the toolchain. The functions will still be called, whether or not the 'Activate Statistic' checkbox is on, when statistic is run directly. - -==Settings== -===Extrusion Diameter over Thickness=== -Default is 1.25. - -The 'Extrusion Diameter over Thickness is the ratio of the extrusion diameter over the layer thickness, the default is 1.25. The extrusion fill density ratio that is printed to the console, ( it is derived quantity not a parameter ) is the area of the extrusion diameter over the extrusion width over the layer thickness. Assuming the extrusion diameter is correct, a high value means the filament will be packed tightly, and the object will be almost as dense as the filament. If the fill density ratio is too high, there could be too little room for the filament, and the extruder will end up plowing through the extra filament. A low fill density ratio means the filaments will be far away from each other, the object will be leaky and light. The fill density ratio with the default extrusion settings is around 0.68. - -===Print Statistics=== -Default is on. - -When the 'Print Statistics' checkbox is on, the statistics will be printed to the console. - -===Save Statistics=== -Default is off. - -When the 'Save Statistics' checkbox is on, the statistics will be saved as a .txt file. - -==Gcodes== -An explanation of the gcodes is at: -http://reprap.org/bin/view/Main/Arduino_GCode_Interpreter - -and at: -http://reprap.org/bin/view/Main/MCodeReference - -A gode example is at: -http://forums.reprap.org/file.php?12,file=565 - -==Examples== -Below are examples of statistic being used. These examples are run in a terminal in the folder which contains Screw Holder_penultimate.gcode and statistic.py. The 'Save Statistics' checkbox is selected. - -> python statistic.py -This brings up the statistic dialog. - -> python statistic.py Screw Holder_penultimate.gcode -The statistic file is saved as Screw_Holder_penultimate_statistic.txt - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import cStringIO -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewRepository(): - """Get new repository.""" - return StatisticRepository() - -def getWindowAnalyzeFile(fileName): - """Write statistics for a gcode file.""" - return getWindowAnalyzeFileGivenText( fileName, archive.getFileText(fileName) ) - -def getWindowAnalyzeFileGivenText( fileName, gcodeText, repository=None): - """Write statistics for a gcode file.""" - print('') - print('') - print('Statistics are being generated for the file ' + archive.getSummarizedFileName(fileName) ) - if repository is None: - repository = settings.getReadRepository( StatisticRepository() ) - skein = StatisticSkein() - statisticGcode = skein.getCraftedGcode(gcodeText, repository) - if repository.printStatistics.value: - print( statisticGcode ) - if repository.saveStatistics.value: - archive.writeFileMessageEnd('.txt', fileName, statisticGcode, 'The statistics file is saved as ') - -def writeOutput(fileName, fileNamePenultimate, fileNameSuffix, filePenultimateWritten, gcodeText=''): - """Write statistics for a skeinforge gcode file, if 'Write Statistics File for Skeinforge Chain' is selected.""" - repository = settings.getReadRepository( StatisticRepository() ) - if gcodeText == '': - gcodeText = archive.getFileText( fileNameSuffix ) - if repository.activateStatistic.value: - getWindowAnalyzeFileGivenText( fileNameSuffix, gcodeText, repository ) - - -class StatisticRepository: - """A class to handle the statistics settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.analyze_plugins.statistic.html', self) - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Statistic') - self.activateStatistic = settings.BooleanSetting().getFromValue('Activate Statistic', self, True ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Cost -', self ) - self.machineTime = settings.FloatSpin().getFromValue( 0.0, 'Machine Time ($/hour):', self, 5.0, 1.0 ) - self.material = settings.FloatSpin().getFromValue( 0.0, 'Material ($/kg):', self, 40.0, 20.0 ) - settings.LabelSeparator().getFromRepository(self) - self.density = settings.FloatSpin().getFromValue( 500.0, 'Density (kg/m3):', self, 2000.0, 930.0 ) - self.extrusionDiameterOverThickness = settings.FloatSpin().getFromValue( 1.0, 'Extrusion Diameter over Thickness (ratio):', self, 1.5, 1.25 ) - self.fileNameInput = settings.FileNameInput().getFromFileName( [ ('Gcode text files', '*.gcode') ], 'Open File to Generate Statistics for', self, '') - self.printStatistics = settings.BooleanSetting().getFromValue('Print Statistics', self, True ) - self.saveStatistics = settings.BooleanSetting().getFromValue('Save Statistics', self, False ) - self.executeTitle = 'Generate Statistics' - - def execute(self): - """Write button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrGcodeDirectory( self.fileNameInput.value, self.fileNameInput.wasCancelled, ['_comment'] ) - for fileName in fileNames: - getWindowAnalyzeFile(fileName) - - -class StatisticSkein: - """A class to get statistics for a gcode skein.""" - def __init__(self): - self.extrusionDiameter = None - self.oldLocation = None - self.operatingFeedRatePerSecond = None - self.output = cStringIO.StringIO() - self.profileName = None - self.version = None - - def addLine(self, line): - """Add a line of text and a newline to the output.""" - self.output.write(line + '\n') - - def addToPath(self, location): - """Add a point to travel and maybe extrusion.""" - if self.oldLocation is not None: - travel = location.distance( self.oldLocation ) - if self.feedRateMinute > 0.0: - self.totalBuildTime += 60.0 * travel / self.feedRateMinute - self.totalDistanceTraveled += travel - if self.extruderActive: - self.totalDistanceExtruded += travel - self.cornerMaximum.maximize(location) - self.cornerMinimum.minimize(location) - self.oldLocation = location - - def extruderSet( self, active ): - """Maybe increment the number of times the extruder was toggled.""" - if self.extruderActive != active: - self.extruderToggled += 1 - self.extruderActive = active - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the statistics.""" - self.absolutePerimeterWidth = 0.4 - self.characters = 0 - self.cornerMaximum = Vector3(-987654321.0, -987654321.0, -987654321.0) - self.cornerMinimum = Vector3(987654321.0, 987654321.0, 987654321.0) - self.extruderActive = False - self.extruderSpeed = None - self.extruderToggled = 0 - self.feedRateMinute = 600.0 - self.layerThickness = 0.4 - self.numberOfLines = 0 - self.procedures = [] - self.repository = repository - self.totalBuildTime = 0.0 - self.totalDistanceExtruded = 0.0 - self.totalDistanceTraveled = 0.0 - lines = archive.getTextLines(gcodeText) - for line in lines: - self.parseLine(line) - averageFeedRate = self.totalDistanceTraveled / self.totalBuildTime - self.characters += self.numberOfLines - kilobytes = round( self.characters / 1024.0 ) - halfPerimeterWidth = 0.5 * self.absolutePerimeterWidth - halfExtrusionCorner = Vector3( halfPerimeterWidth, halfPerimeterWidth, halfPerimeterWidth ) - self.cornerMaximum += halfExtrusionCorner - self.cornerMinimum -= halfExtrusionCorner - extent = self.cornerMaximum - self.cornerMinimum - roundedHigh = euclidean.getRoundedPoint( self.cornerMaximum ) - roundedLow = euclidean.getRoundedPoint( self.cornerMinimum ) - roundedExtent = euclidean.getRoundedPoint( extent ) - axisString = " axis extrusion starts at " - crossSectionArea = 0.9 * self.absolutePerimeterWidth * self.layerThickness # 0.9 if from the typical fill density - if self.extrusionDiameter is not None: - crossSectionArea = math.pi / 4.0 * self.extrusionDiameter * self.extrusionDiameter - volumeExtruded = 0.001 * crossSectionArea * self.totalDistanceExtruded - mass = volumeExtruded / repository.density.value - machineTimeCost = repository.machineTime.value * self.totalBuildTime / 3600.0 - materialCost = repository.material.value * mass - self.addLine(' ') - self.addLine('Cost') - self.addLine( "Machine time cost is %s$." % round( machineTimeCost, 2 ) ) - self.addLine( "Material cost is %s$." % round( materialCost, 2 ) ) - self.addLine( "Total cost is %s$." % round( machineTimeCost + materialCost, 2 ) ) - self.addLine(' ') - self.addLine('Extent') - self.addLine( "X%s%s mm and ends at %s mm, for a width of %s mm." % ( axisString, int( roundedLow.x ), int( roundedHigh.x ), int( extent.x ) ) ) - self.addLine( "Y%s%s mm and ends at %s mm, for a depth of %s mm." % ( axisString, int( roundedLow.y ), int( roundedHigh.y ), int( extent.y ) ) ) - self.addLine( "Z%s%s mm and ends at %s mm, for a height of %s mm." % ( axisString, int( roundedLow.z ), int( roundedHigh.z ), int( extent.z ) ) ) - self.addLine(' ') - self.addLine('Extruder') - self.addLine( "Build time is %s." % euclidean.getDurationString( self.totalBuildTime ) ) - self.addLine( "Distance extruded is %s mm." % euclidean.getThreeSignificantFigures( self.totalDistanceExtruded ) ) - self.addLine( "Distance traveled is %s mm." % euclidean.getThreeSignificantFigures( self.totalDistanceTraveled ) ) - if self.extruderSpeed is not None: - self.addLine( "Extruder speed is %s" % euclidean.getThreeSignificantFigures( self.extruderSpeed ) ) - self.addLine( "Extruder was extruding %s percent of the time." % euclidean.getThreeSignificantFigures( 100.0 * self.totalDistanceExtruded / self.totalDistanceTraveled ) ) - self.addLine( "Extruder was toggled %s times." % self.extruderToggled ) - if self.operatingFeedRatePerSecond is not None: - flowRate = crossSectionArea * self.operatingFeedRatePerSecond - self.addLine( "Operating flow rate is %s mm3/s." % euclidean.getThreeSignificantFigures( flowRate ) ) - self.addLine( "Feed rate average is %s mm/s, (%s mm/min)." % ( euclidean.getThreeSignificantFigures( averageFeedRate ), euclidean.getThreeSignificantFigures( 60.0 * averageFeedRate ) ) ) - self.addLine(' ') - self.addLine('Filament') - self.addLine( "Cross section area is %s mm2." % euclidean.getThreeSignificantFigures( crossSectionArea ) ) - if self.extrusionDiameter is not None: - self.addLine( "Extrusion diameter is %s mm." % euclidean.getThreeSignificantFigures( self.extrusionDiameter ) ) - self.addLine('Extrusion fill density ratio is %s' % euclidean.getThreeSignificantFigures( crossSectionArea / self.absolutePerimeterWidth / self.layerThickness ) ) - self.addLine(' ') - self.addLine('Material') - self.addLine( "Mass extruded is %s grams." % euclidean.getThreeSignificantFigures( 1000.0 * mass ) ) - self.addLine( "Volume extruded is %s cc." % euclidean.getThreeSignificantFigures( volumeExtruded ) ) - self.addLine(' ') - self.addLine('Meta') - self.addLine( "Text has %s lines and a size of %s KB." % ( self.numberOfLines, kilobytes ) ) - if self.version is not None: - self.addLine( "Version is " + self.version ) - self.addLine(' ') - self.addLine( "Procedures" ) - for procedure in self.procedures: - self.addLine(procedure) - if self.profileName is not None: - self.addLine(' ') - self.addLine( 'Profile' ) - self.addLine(self.profileName) - self.addLine(' ') - self.addLine('Slice') - self.addLine( "Layer thickness is %s mm." % euclidean.getThreeSignificantFigures( self.layerThickness ) ) - self.addLine( "Perimeter width is %s mm." % euclidean.getThreeSignificantFigures( self.absolutePerimeterWidth ) ) - self.addLine(' ') - return self.output.getvalue() - - def getLocationSetFeedRateToSplitLine( self, splitLine ): - """Get location ans set feed rate to the plsit line.""" - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - indexOfF = gcodec.getIndexOfStartingWithSecond( "F", splitLine ) - if indexOfF > 0: - self.feedRateMinute = gcodec.getDoubleAfterFirstLetter( splitLine[indexOfF] ) - return location - - def helicalMove( self, isCounterclockwise, splitLine ): - """Get statistics for a helical move.""" - if self.oldLocation is None: - return - location = self.getLocationSetFeedRateToSplitLine(splitLine) - location += self.oldLocation - center = self.oldLocation.copy() - indexOfR = gcodec.getIndexOfStartingWithSecond( "R", splitLine ) - if indexOfR > 0: - radius = gcodec.getDoubleAfterFirstLetter( splitLine[ indexOfR ] ) - halfLocationMinusOld = location - self.oldLocation - halfLocationMinusOld *= 0.5 - halfLocationMinusOldLength = halfLocationMinusOld.magnitude() - centerMidpointDistanceSquared = radius * radius - halfLocationMinusOldLength * halfLocationMinusOldLength - centerMidpointDistance = math.sqrt( max( centerMidpointDistanceSquared, 0.0 ) ) - centerMinusMidpoint = euclidean.getRotatedWiddershinsQuarterAroundZAxis( halfLocationMinusOld ) - centerMinusMidpoint.normalize() - centerMinusMidpoint *= centerMidpointDistance - if isCounterclockwise: - center.setToVector3( halfLocationMinusOld + centerMinusMidpoint ) - else: - center.setToVector3( halfLocationMinusOld - centerMinusMidpoint ) - else: - center.x = gcodec.getDoubleForLetter( "I", splitLine ) - center.y = gcodec.getDoubleForLetter( "J", splitLine ) - curveSection = 0.5 - center += self.oldLocation - afterCenterSegment = location - center - beforeCenterSegment = self.oldLocation - center - afterCenterDifferenceAngle = euclidean.getAngleAroundZAxisDifference( afterCenterSegment, beforeCenterSegment ) - absoluteDifferenceAngle = abs( afterCenterDifferenceAngle ) - steps = int( round( 0.5 + max( absoluteDifferenceAngle * 2.4, absoluteDifferenceAngle * beforeCenterSegment.magnitude() / curveSection ) ) ) - stepPlaneAngle = euclidean.getWiddershinsUnitPolar( afterCenterDifferenceAngle / steps ) - zIncrement = ( afterCenterSegment.z - beforeCenterSegment.z ) / float( steps ) - for step in xrange( 1, steps ): - beforeCenterSegment = euclidean.getRoundZAxisByPlaneAngle( stepPlaneAngle, beforeCenterSegment ) - beforeCenterSegment.z += zIncrement - arcPoint = center + beforeCenterSegment - self.addToPath( arcPoint ) - self.addToPath( location ) - - def linearMove( self, splitLine ): - """Get statistics for a linear move.""" - location = self.getLocationSetFeedRateToSplitLine(splitLine) - self.addToPath( location ) - - def parseLine(self, line): - """Parse a gcode line and add it to the statistics.""" - self.characters += len(line) - self.numberOfLines += 1 - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - self.linearMove(splitLine) - elif firstWord == 'G2': - self.helicalMove( False, splitLine ) - elif firstWord == 'G3': - self.helicalMove( True, splitLine ) - elif firstWord == 'M101': - self.extruderSet( True ) - elif firstWord == 'M102': - self.extruderSet( False ) - elif firstWord == 'M103': - self.extruderSet( False ) - elif firstWord == '(': - self.layerThickness = float(splitLine[1]) - self.extrusionDiameter = self.repository.extrusionDiameterOverThickness.value * self.layerThickness - elif firstWord == '(': - self.operatingFeedRatePerSecond = float(splitLine[1]) - elif firstWord == '(': - self.absolutePerimeterWidth = abs(float(splitLine[1])) - elif firstWord == '(': - self.procedures.append(splitLine[1]) - elif firstWord == '(': - self.profileName = line.replace('(', '').replace(')', '').strip() - elif firstWord == '(': - self.version = splitLine[1] - - -def main(): - """Display the statistics dialog.""" - if len(sys.argv) > 1: - getWindowAnalyzeFile(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/vectorwrite.py b/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/vectorwrite.py deleted file mode 100644 index 5132017..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/analyze_plugins/vectorwrite.py +++ /dev/null @@ -1,357 +0,0 @@ -""" -This page is in the table of contents. -Vectorwrite is a script to write Scalable Vector Graphics for a gcode file. - -The vectorwrite manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Vectorwrite - -Vectorwrite generates a Scalable Vector Graphics file which can be opened by an SVG viewer or an SVG capable browser like Mozilla: -http://www.mozilla.com/firefox/ - -==Operation== -The default 'Activate Vectorwrite' checkbox is on. When it is on, the functions described below will work when called from the skeinforge toolchain, when it is off, the functions will not be called from the toolchain. The functions will still be called, whether or not the 'Activate Vectorwrite' checkbox is on, when vectorwrite is run directly. - -==Settings== -===Add Loops=== -Default is on. - -If 'Add Loops' is selected, the loops will be added in yellow to the the scalable vector graphics output. - -===Add Paths=== -Default is on. - -If 'Add Paths' is selected, the paths will be added in pink to the the scalable vector graphics output. - -===Add Perimeters=== -Default is on. - -If 'Add Perimeters' is selected, the perimeters will be added to the the scalable vector graphics output. The outer perimeters will be red and the inner perimeters will be orange. - -===Layers=== -====Layers From==== -Default is zero. - -The "Layers From" is the index of the bottom layer that will be displayed. If the layer from is the default zero, the display will start from the lowest layer. If the the layer from index is negative, then the display will start from the layer from index below the top layer. - -====Layers To==== -Default is a huge number, which will be limited to the highest index layer. - -The "Layers To" is the index of the top layer that will be displayed. If the layer to index is a huge number like the default, the display will go to the top of the model, at least until we model habitats:) If the layer to index is negative, then the display will go to the layer to index below the top layer. The layer from until layer to index is a python slice. - -===SVG Viewer=== -Default is webbrowser. - -If the 'SVG Viewer' is set to the default 'webbrowser', the scalable vector graphics file will be sent to the default browser to be opened. If the 'SVG Viewer' is set to a program name, the scalable vector graphics file will be sent to that program to be opened. - -==Examples== -Below are examples of vectorwrite being used. These examples are run in a terminal in the folder which contains Screw Holder_penultimate.gcode and vectorwrite.py. - -> python vectorwrite.py -This brings up the vectorwrite dialog. - -> python vectorwrite.py Screw Holder_penultimate.gcode -The vectorwrite file is saved as Screw_Holder_penultimate_vectorwrite.svg - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from fabmetheus_utilities import svg_writer -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import cStringIO -import os -import sys -import time - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__credits__ = 'Nophead ' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewRepository(): - """Get new repository.""" - return VectorwriteRepository() - -def getWindowAnalyzeFile(fileName): - """Write scalable vector graphics for a gcode file.""" - gcodeText = archive.getFileText(fileName) - return getWindowAnalyzeFileGivenText(fileName, gcodeText) - -def getWindowAnalyzeFileGivenText( fileName, gcodeText, repository=None): - """Write scalable vector graphics for a gcode file given the settings.""" - if gcodeText == '': - return None - if repository is None: - repository = settings.getReadRepository( VectorwriteRepository() ) - startTime = time.time() - vectorwriteGcode = VectorwriteSkein().getCarvedSVG( fileName, gcodeText, repository ) - if vectorwriteGcode == '': - return None - suffixFileName = fileName[ : fileName.rfind('.') ] + '_vectorwrite.svg' - suffixDirectoryName = os.path.dirname(suffixFileName) - suffixReplacedBaseName = os.path.basename(suffixFileName).replace(' ', '_') - suffixFileName = os.path.join( suffixDirectoryName, suffixReplacedBaseName ) - archive.writeFileText( suffixFileName, vectorwriteGcode ) - print('The vectorwrite file is saved as ' + archive.getSummarizedFileName(suffixFileName) ) - print('It took %s to vectorwrite the file.' % euclidean.getDurationString( time.time() - startTime ) ) - settings.openSVGPage( suffixFileName, repository.svgViewer.value ) - -def writeOutput(fileName, fileNamePenultimate, fileNameSuffix, filePenultimateWritten, gcodeText=''): - """Write scalable vector graphics for a skeinforge gcode file, if activate vectorwrite is selected.""" - repository = settings.getReadRepository( VectorwriteRepository() ) - if not repository.activateVectorwrite.value: - return - gcodeText = archive.getTextIfEmpty( fileNameSuffix, gcodeText ) - getWindowAnalyzeFileGivenText( fileNameSuffix, gcodeText, repository ) - - -class SVGWriterVectorwrite( svg_writer.SVGWriter ): - """A class to vectorwrite a carving.""" - def addPaths( self, colorName, paths, transformString ): - """Add paths to the output.""" - pathString = '' - for path in paths: - pathString += self.getSVGStringForPath(path) + ' ' - if len( pathString ) < 1: - return - pathXMLElementCopy = self.pathXMLElement.getCopy('', self.pathXMLElement.parent ) - pathCopyDictionary = pathXMLElementCopy.attributeDictionary - pathCopyDictionary['d'] = pathString[ : - 1 ] - pathCopyDictionary['fill'] = 'none' - pathCopyDictionary['stroke'] = colorName - pathCopyDictionary['transform'] = transformString - - def addRotatedLoopLayerToOutput( self, layerIndex, threadLayer ): - """Add rotated boundary layer to the output.""" - self.addLayerBegin( layerIndex, threadLayer ) - transformString = self.getTransformString() - self.pathDictionary['d'] = self.getSVGStringForLoops( threadLayer.boundaryLoops ) - self.pathDictionary['transform'] = transformString - self.addPaths('#fa0', threadLayer.innerPerimeters, transformString ) #orange - self.addPaths('#ff0', threadLayer.loops, transformString ) #yellow - self.addPaths('#f00', threadLayer.outerPerimeters, transformString ) #red - self.addPaths('#f5c', threadLayer.paths, transformString ) #light violetred - - -class ThreadLayer: - """Threads with a z.""" - def __init__( self, z ): - self.boundaryLoops = [] - self.innerPerimeters = [] - self.loops = [] - self.outerPerimeters = [] - self.paths = [] - self.z = z - - def __repr__(self): - """Get the string representation of this loop layer.""" - return str(self.__dict__) - - def getTotalNumberOfThreads(self): - """Get the total number of loops, paths and perimeters.""" - return len(self.boundaryLoops) + len(self.innerPerimeters) + len(self.loops) + len(self.outerPerimeters) + len(self.paths) - - def maximize(self, vector3): - """Maximize the vector3 over the loops, paths and perimeters.""" - pointComplex = vector3.dropAxis() - pointComplex = euclidean.getMaximum(euclidean.getMaximumByComplexPaths(self.boundaryLoops), pointComplex) - pointComplex = euclidean.getMaximum(euclidean.getMaximumByComplexPaths(self.innerPerimeters), pointComplex) - pointComplex = euclidean.getMaximum(euclidean.getMaximumByComplexPaths(self.loops), pointComplex) - pointComplex = euclidean.getMaximum(euclidean.getMaximumByComplexPaths(self.outerPerimeters), pointComplex) - pointComplex = euclidean.getMaximum(euclidean.getMaximumByComplexPaths(self.paths), pointComplex) - vector3.setToXYZ(pointComplex.real, pointComplex.imag, max(self.z, vector3.z)) - - def minimize(self, vector3): - """Minimize the vector3 over the loops, paths and perimeters.""" - pointComplex = vector3.dropAxis() - pointComplex = euclidean.getMinimum(euclidean.getMinimumByComplexPaths(self.boundaryLoops), pointComplex) - pointComplex = euclidean.getMinimum(euclidean.getMinimumByComplexPaths(self.innerPerimeters), pointComplex) - pointComplex = euclidean.getMinimum(euclidean.getMinimumByComplexPaths(self.loops), pointComplex) - pointComplex = euclidean.getMinimum(euclidean.getMinimumByComplexPaths(self.outerPerimeters), pointComplex) - pointComplex = euclidean.getMinimum(euclidean.getMinimumByComplexPaths(self.paths), pointComplex) - vector3.setToXYZ(pointComplex.real, pointComplex.imag, min(self.z, vector3.z)) - -class VectorwriteRepository: - """A class to handle the vectorwrite settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.analyze_plugins.vectorwrite.html', self ) - self.activateVectorwrite = settings.BooleanSetting().getFromValue('Activate Vectorwrite', self, False ) - self.fileNameInput = settings.FileNameInput().getFromFileName( [ ('Gcode text files', '*.gcode') ], 'Open File to Write Vector Graphics for', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Vectorwrite') - self.addLoops = settings.BooleanSetting().getFromValue('Add Loops', self, True) - self.addPaths = settings.BooleanSetting().getFromValue('Add Paths', self, True) - self.addPerimeters = settings.BooleanSetting().getFromValue('Add Perimeters', self, True) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Layers -', self ) - self.layersFrom = settings.IntSpin().getFromValue( 0, 'Layers From (index):', self, 20, 0 ) - self.layersTo = settings.IntSpin().getSingleIncrementFromValue( 0, 'Layers To (index):', self, 912345678, 912345678 ) - settings.LabelSeparator().getFromRepository(self) - self.svgViewer = settings.StringSetting().getFromValue('SVG Viewer:', self, 'webbrowser') - settings.LabelSeparator().getFromRepository(self) - self.executeTitle = 'Vectorwrite' - - def execute(self): - """Write button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrGcodeDirectory( self.fileNameInput.value, self.fileNameInput.wasCancelled ) - for fileName in fileNames: - getWindowAnalyzeFile(fileName) - - -class VectorwriteSkein: - """A class to vectorwrite a carving.""" - def __init__(self): - """Initialize.""" - self.layerCount = settings.LayerCount() - - def addRotatedLoopLayer(self, z): - """Add rotated loop layer.""" - self.layerCount.printProgressIncrement('vectorwrite') - self.threadLayer = ThreadLayer(z) - self.threadLayers.append(self.threadLayer) - - def addToLoops(self): - """Add the thread to the loops.""" - self.isLoop = False - if len(self.thread) < 1: - return - if self.repository.addLoops.value: - self.threadLayer.loops.append(self.thread) - self.thread = [] - - def addToPerimeters(self): - """Add the thread to the perimeters.""" - self.isPerimeter = False - if len(self.thread) < 1: - return - if self.repository.addPerimeters.value: - if self.isOuter: - self.threadLayer.outerPerimeters.append(self.thread) - else: - self.threadLayer.innerPerimeters.append(self.thread) - self.thread = [] - - def getCarveLayerThickness(self): - """Get the layer thickness.""" - return self.layerThickness - - def getCarvedSVG(self, fileName, gcodeText, repository): - """Parse gnu triangulated surface text and store the vectorwrite gcode.""" - cornerMaximum = Vector3(-987654321.0, -987654321.0, -987654321.0) - cornerMinimum = Vector3(987654321.0, 987654321.0, 987654321.0) - self.boundaryLoop = None - self.extruderActive = False - self.isLoop = False - self.isOuter = False - self.isPerimeter = False - self.lines = archive.getTextLines(gcodeText) - self.oldLocation = None - self.thread = [] - self.threadLayers = [] - self.repository = repository - self.parseInitialization() - for line in self.lines[self.lineIndex :]: - self.parseLine(line) - self.removeEmptyLayers() - for threadLayer in self.threadLayers: - threadLayer.maximize(cornerMaximum) - threadLayer.minimize(cornerMinimum) - halfLayerThickness = 0.5 * self.layerThickness - cornerMaximum.z += halfLayerThickness - cornerMinimum.z -= halfLayerThickness - svgWriter = SVGWriterVectorwrite( - True, cornerMaximum, cornerMinimum, self.decimalPlacesCarried, self.layerThickness, self.perimeterWidth) - return svgWriter.getReplacedSVGTemplate(fileName, 'vectorwrite', self.threadLayers) - - def removeEmptyLayers(self): - """Remove empty layers.""" - for threadLayerIndex, threadLayer in enumerate(self.threadLayers): - if threadLayer.getTotalNumberOfThreads() > 0: - self.threadLayers = self.threadLayers[threadLayerIndex :] - return - - def linearMove( self, splitLine ): - """Get statistics for a linear move.""" - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - if self.extruderActive: - if len(self.thread) == 0: - self.thread = [ self.oldLocation.dropAxis() ] - self.thread.append(location.dropAxis()) - self.oldLocation = location - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == '(': - self.decimalPlacesCarried = int(splitLine[1]) - elif firstWord == '(': - self.layerThickness = float(splitLine[1]) - elif firstWord == '()': - return - elif firstWord == '(': - self.perimeterWidth = float(splitLine[1]) - - def parseLine(self, line): - """Parse a gcode line and add it to the outset skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - self.linearMove(splitLine) - elif firstWord == 'M101': - self.extruderActive = True - elif firstWord == 'M103': - self.extruderActive = False - if self.isLoop: - self.addToLoops() - return - if self.isPerimeter: - self.addToPerimeters() - return - if self.repository.addPaths.value: - self.threadLayer.paths.append(self.thread) - self.thread = [] - elif firstWord == '()': - self.boundaryLoop = None - elif firstWord == '(': - location = gcodec.getLocationFromSplitLine(None, splitLine) - if self.boundaryLoop is None: - self.boundaryLoop = [] - self.threadLayer.boundaryLoops.append( self.boundaryLoop ) - self.boundaryLoop.append(location.dropAxis()) - elif firstWord == '(': - self.addRotatedLoopLayer(float(splitLine[1])) - elif firstWord == '()': - self.addToLoops() - elif firstWord == '(': - self.isLoop = True - elif firstWord == '(': - self.isPerimeter = True - self.isOuter = ( splitLine[1] == 'outer') - elif firstWord == '()': - self.addToPerimeters() - - -def main(): - """Display the vectorwrite dialog.""" - if len(sys.argv) > 1: - getWindowAnalyzeFile(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft.py deleted file mode 100644 index 8aa5210..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft.py +++ /dev/null @@ -1,128 +0,0 @@ -""" -This page is in the table of contents. -Craft is a script to access the plugins which craft a gcode file. - -The plugin buttons which are commonly used are bolded and the ones which are rarely used have normal font weight. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import os -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addSubmenus( menu, pluginFileName, pluginFolderPath, pluginPath ): - """Add a tool plugin menu.""" - submenu = settings.Tkinter.Menu( menu, tearoff = 0 ) - menu.add_cascade( label = pluginFileName.capitalize(), menu = submenu ) - settings.ToolDialog().addPluginToMenu( submenu, pluginPath ) - submenu.add_separator() - submenuFileNames = archive.getPluginFileNamesFromDirectoryPath( pluginFolderPath ) - for submenuFileName in submenuFileNames: - settings.ToolDialog().addPluginToMenu( submenu, os.path.join( pluginFolderPath, submenuFileName ) ) - -def addToCraftMenu( menu ): - """Add a craft plugin menu.""" - settings.ToolDialog().addPluginToMenu( menu, archive.getUntilDot( os.path.abspath(__file__) ) ) - menu.add_separator() - directoryPath = skeinforge_craft.getPluginsDirectoryPath() - directoryFolders = settings.getFolders(directoryPath) - pluginFileNames = skeinforge_craft.getPluginFileNames() - for pluginFileName in pluginFileNames: - pluginFolderName = pluginFileName + '_plugins' - pluginPath = os.path.join( directoryPath, pluginFileName ) - if pluginFolderName in directoryFolders: - addSubmenus( menu, pluginFileName, os.path.join( directoryPath, pluginFolderName ), pluginPath ) - else: - settings.ToolDialog().addPluginToMenu( menu, pluginPath ) - -def addToMenu( master, menu, repository, window ): - """Add a tool plugin menu.""" - CraftMenuSaveListener( menu, window ) - -def getNewRepository(): - """Get new repository.""" - return skeinforge_craft.CraftRepository() - -def writeOutput(fileName): - """Craft a gcode file.""" - return skeinforge_craft.writeOutput(fileName) - - -class CraftMenuSaveListener: - """A class to update a craft menu.""" - def __init__( self, menu, window ): - """Set the menu.""" - self.menu = menu - addToCraftMenu( menu ) - euclidean.addElementToListDictionaryIfNotThere( self, window, settings.globalProfileSaveListenerListTable ) - - def save(self): - """Profile has been saved and profile menu should be updated.""" - settings.deleteMenuItems( self.menu ) - addToCraftMenu( self.menu ) - - -class CraftRadioButtonsSaveListener: - """A class to update the craft radio buttons.""" - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - euclidean.addElementToListDictionaryIfNotThere( self, self.repository.repositoryDialog, settings.globalProfileSaveListenerListTable ) - self.gridPosition = gridPosition.getCopy() - self.gridPosition.increment() - self.gridPosition.row = gridPosition.rowStart - self.setRadioButtons() - - def getFromRadioPlugins( self, radioPlugins, repository ): - """Initialize.""" - self.name = 'CraftRadioButtonsSaveListener' - self.radioPlugins = radioPlugins - self.repository = repository - repository.displayEntities.append(self) - return self - - def save(self): - """Profile has been saved and craft radio plugins should be updated.""" - self.setRadioButtons() - - def setRadioButtons(self): - """Profile has been saved and craft radio plugins should be updated.""" - craftSequence = skeinforge_profile.getCraftTypePluginModule().getCraftSequence() - gridPosition = self.gridPosition.getCopy() - maximumValue = False - activeRadioPlugins = [] - for radioPlugin in self.radioPlugins: - if radioPlugin.name in craftSequence: - activeRadioPlugins.append( radioPlugin ) - radioPlugin.incrementGridPosition(gridPosition) - maximumValue = max( radioPlugin.value, maximumValue ) - else: - radioPlugin.radiobutton.grid_remove() - if not maximumValue: - selectedRadioPlugin = settings.getSelectedRadioPlugin( self.repository.importantFileNames + [ activeRadioPlugins[0].name ], activeRadioPlugins ).setSelect() - self.repository.pluginFrame.update() - - -def main(): - """Display the craft dialog.""" - if len(sys.argv) > 1: - settings.startMainLoopFromWindow(writeOutput(' '.join(sys.argv[1 :]))) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/cleave.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/cleave.py deleted file mode 100644 index b9885a6..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/cleave.py +++ /dev/null @@ -1,204 +0,0 @@ -""" -This page is in the table of contents. -Cleave is a script to cleave a shape into svg slice layers. - -==Settings== -===Add Layer Template to SVG=== -Default is on. - -When selected, the layer template will be added to the svg output, which adds javascript control boxes. So 'Add Layer Template to SVG' should be selected when the svg will be viewed in a browser. - -When off, no controls will be added, the svg output will only include the fabrication paths. So 'Add Layer Template to SVG' should be deselected when the svg will be used by other software, like Inkscape. - -===Extra Decimal Places=== -Default is two. - -Defines the number of extra decimal places export will output compared to the number of decimal places in the layer thickness. The higher the 'Extra Decimal Places', the more significant figures the output numbers will have. - -===Import Coarseness=== -Default is one. - -When a triangle mesh has holes in it, the triangle mesh slicer switches over to a slow algorithm that spans gaps in the mesh. The higher the 'Import Coarseness' setting, the wider the gaps in the mesh it will span. An import coarseness of one means it will span gaps of the perimeter width. - -===Layer Thickness=== -Default is 0.4 mm. - -Defines the thickness of the layer, this is the most important cleave setting. - -===Layers=== -Cleave slices from bottom to top. To get a single layer, set the "Layers From" to zero and the "Layers To" to one. The layer from until layer to range is a python slice. - -====Layers From==== -Default is zero. - -Defines the index of the bottom layer that will be cleaved. If the layer from is the default zero, the carving will start from the lowest layer. If the 'Layers From' index is negative, then the carving will start from the 'Layers From' index below the top layer. - -====Layers To==== -Default is a huge number, which will be limited to the highest index layer. - -Defines the index of the top layer that will be cleaved. If the 'Layers To' index is a huge number like the default, the carving will go to the top of the model. If the 'Layers To' index is negative, then the carving will go to the 'Layers To' index below the top layer. - -===Mesh Type=== -Default is 'Correct Mesh'. - -====Correct Mesh==== -When selected, the mesh will be accurately cleaved, and if a hole is found, cleave will switch over to the algorithm that spans gaps. - -====Unproven Mesh==== -When selected, cleave will use the gap spanning algorithm from the start. The problem with the gap spanning algothm is that it will span gaps, even if there is not actually a gap in the model. - -===Perimeter Width=== -Default is two millimeters. - -Defines the width of the perimeter. - -===SVG Viewer=== -Default is webbrowser. - -If the 'SVG Viewer' is set to the default 'webbrowser', the scalable vector graphics file will be sent to the default browser to be opened. If the 'SVG Viewer' is set to a program name, the scalable vector graphics file will be sent to that program to be opened. - -==Examples== -The following examples cleave the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and cleave.py. - -> python cleave.py -This brings up the cleave dialog. - -> python cleave.py Screw Holder Bottom.stl -The cleave tool is parsing the file: -Screw Holder Bottom.stl -.. -The cleave tool has created the file: -.. Screw Holder Bottom_cleave.svg - -""" - -from __future__ import absolute_import -try: - import psyco - psyco.full() -except: - pass -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from fabmetheus_utilities import svg_writer -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import os -import sys -import time - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, gcodeText = '', repository=None): - """Get cleaved text.""" - if fileName.endswith('.svg'): - gcodeText = archive.getTextIfEmpty(fileName, gcodeText) - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'cleave'): - return gcodeText - carving = svg_writer.getCarving(fileName) - if carving is None: - return '' - if repository is None: - repository = CleaveRepository() - settings.getReadRepository(repository) - return CleaveSkein().getCarvedSVG( carving, fileName, repository ) - -def getNewRepository(): - """Get new repository.""" - return CleaveRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Cleave a GNU Triangulated Surface file.""" - startTime = time.time() - print('File ' + archive.getSummarizedFileName(fileName) + ' is being cleaved.') - repository = CleaveRepository() - settings.getReadRepository(repository) - cleaveGcode = getCraftedText( fileName, '', repository ) - if cleaveGcode == '': - return - suffixFileName = fileName[ : fileName.rfind('.') ] + '_cleave.svg' - suffixDirectoryName = os.path.dirname(suffixFileName) - suffixReplacedBaseName = os.path.basename(suffixFileName).replace(' ', '_') - suffixFileName = os.path.join( suffixDirectoryName, suffixReplacedBaseName ) - archive.writeFileText( suffixFileName, cleaveGcode ) - print('The cleaved file is saved as ' + archive.getSummarizedFileName(suffixFileName) ) - print('It took %s to cleave the file.' % euclidean.getDurationString( time.time() - startTime ) ) - if shouldAnalyze: - settings.openSVGPage( suffixFileName, repository.svgViewer.value ) - - -class CleaveRepository: - """A class to handle the cleave settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.cleave.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getTranslatorFileTypeTuples(), 'Open File to be Cleaved', self, '') - self.addLayerTemplateToSVG = settings.BooleanSetting().getFromValue('Add Layer Template to SVG', self, True) - self.extraDecimalPlaces = settings.FloatSpin().getFromValue(0.0, 'Extra Decimal Places (float):', self, 3.0, 2.0) - self.importCoarseness = settings.FloatSpin().getFromValue( 0.5, 'Import Coarseness (ratio):', self, 2.0, 1.0 ) - self.layerThickness = settings.FloatSpin().getFromValue( 0.1, 'Layer Thickness (mm):', self, 1.0, 0.4 ) - self.layersFrom = settings.IntSpin().getFromValue( 0, 'Layers From (index):', self, 20, 0 ) - self.layersTo = settings.IntSpin().getSingleIncrementFromValue( 0, 'Layers To (index):', self, 912345678, 912345678 ) - self.meshTypeLabel = settings.LabelDisplay().getFromName('Mesh Type: ', self, ) - importLatentStringVar = settings.LatentStringVar() - self.correctMesh = settings.Radio().getFromRadio( importLatentStringVar, 'Correct Mesh', self, True ) - self.unprovenMesh = settings.Radio().getFromRadio( importLatentStringVar, 'Unproven Mesh', self, False ) - self.perimeterWidth = settings.FloatSpin().getFromValue( 0.4, 'Perimeter Width (mm):', self, 4.0, 2.0 ) - self.svgViewer = settings.StringSetting().getFromValue('SVG Viewer:', self, 'webbrowser') - settings.LabelSeparator().getFromRepository(self) - self.executeTitle = 'Cleave' - - def execute(self): - """Cleave button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypes(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class CleaveSkein: - """A class to cleave a carving.""" - def getCarvedSVG( self, carving, fileName, repository ): - """Parse gnu triangulated surface text and store the cleaved gcode.""" - layerThickness = repository.layerThickness.value - perimeterWidth = repository.perimeterWidth.value - carving.setCarveLayerThickness( layerThickness ) - importRadius = 0.5 * repository.importCoarseness.value * abs( perimeterWidth ) - carving.setCarveImportRadius( max( importRadius, 0.01 * layerThickness ) ) - carving.setCarveIsCorrectMesh( repository.correctMesh.value ) - rotatedLoopLayers = carving.getCarveRotatedBoundaryLayers() - if len( rotatedLoopLayers ) < 1: - print('Warning, there are no slices for the model, this could be because the model is too small for the Layer Thickness.') - return '' - layerThickness = carving.getCarveLayerThickness() - decimalPlacesCarried = euclidean.getDecimalPlacesCarried(repository.extraDecimalPlaces.value, layerThickness) - svgWriter = svg_writer.SVGWriter( - repository.addLayerTemplateToSVG.value, - carving.getCarveCornerMaximum(), - carving.getCarveCornerMinimum(), - decimalPlacesCarried, - carving.getCarveLayerThickness(), - perimeterWidth) - truncatedRotatedBoundaryLayers = svg_writer.getTruncatedRotatedBoundaryLayers(repository, rotatedLoopLayers) - return svgWriter.getReplacedSVGTemplate( fileName, 'cleave', truncatedRotatedBoundaryLayers, carving.getFabmetheusXML()) - - -def main(): - """Display the cleave dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/coil.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/coil.py deleted file mode 100644 index fac23ac..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/coil.py +++ /dev/null @@ -1,252 +0,0 @@ -""" -This page is in the table of contents. -Coil is a script to coil wire or filament around an object. - -==Operation== -The default 'Activate Coil' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Minimum Tool Distance=== -Default is twenty millimeters. - -Defines the minimum distance between the wire dispenser and the object. The 'Minimum Tool Distance' should be set to the maximum radius of the wire dispenser, times at least 1.3 to get a reasonable safety margin. - -==Examples== -The following examples coil the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and coil.py. - -> python coil.py -This brings up the coil dialog. - -> python coil.py Screw Holder Bottom.stl -The coil tool is parsing the file: -Screw Holder Bottom.stl -.. -The coil tool has created the file: -Screw Holder Bottom_coil.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import os -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, gcodeText = '', repository=None): - """Coil the file or gcodeText.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, gcodeText), repository ) - -def getCraftedTextFromText(gcodeText, repository=None): - """Coil a gcode linear move gcodeText.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'coil'): - return gcodeText - if repository is None: - repository = settings.getReadRepository( CoilRepository() ) - if not repository.activateCoil.value: - return gcodeText - return CoilSkein().getCraftedGcode(gcodeText, repository) - -def getNewRepository(): - """Get new repository.""" - return CoilRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Coil a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'coil', shouldAnalyze) - - -class CoilRepository: - """A class to handle the coil settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.coil.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Coil', self, '') - self.activateCoil = settings.BooleanSetting().getFromValue('Activate Coil', self, True ) - self.minimumToolDistance = settings.FloatSpin().getFromValue( 10.0, 'Minimum Tool Distance (millimeters):', self, 50.0, 20.0 ) - self.executeTitle = 'Coil' - - def execute(self): - """Coil button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - - -class CoilSkein: - """A class to coil a skein of extrusions.""" - def __init__(self): - self.boundaryLayers = [] - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.lineIndex = 0 - self.lines = None - self.oldLocationComplex = complex() - self.perimeterWidth = 0.6 - self.shutdownLines = [] - - def addCoilLayer( self, boundaryLayers, radius, z ): - """Add a coil layer.""" - self.distanceFeedRate.addLine('( %s )' % z ) # Indicate that a new layer is starting. - self.distanceFeedRate.addLine('()') - thread = [] - for boundaryLayerIndex in xrange(1, len(boundaryLayers) - 1): - boundaryLayer = boundaryLayers[boundaryLayerIndex] - boundaryLayerBegin = boundaryLayers[boundaryLayerIndex - 1] - boundaryLayerEnd = boundaryLayers[boundaryLayerIndex + 1] - beginLocation = Vector3(0.0, 0.0, 0.5 * (boundaryLayerBegin.z + boundaryLayer.z)) - outsetLoop = intercircle.getLargestInsetLoopFromLoop(boundaryLayer.loops[0], - radius) - self.addCoilToThread(beginLocation, 0.5 * (boundaryLayer.z + boundaryLayerEnd.z), outsetLoop, thread) - self.addGcodeFromThread(thread) - self.distanceFeedRate.addLine('()') - self.distanceFeedRate.addLine('()') - - def addCoilLayers(self): - """Add the coil layers.""" - numberOfLayersFloat = round( self.perimeterWidth / self.layerThickness ) - numberOfLayers = int( numberOfLayersFloat ) - halfLayerThickness = 0.5 * self.layerThickness - startOutset = self.repository.minimumToolDistance.value + halfLayerThickness - startZ = self.boundaryLayers[0].z + halfLayerThickness - zRange = self.boundaryLayers[-1].z - self.boundaryLayers[0].z - zIncrement = 0.0 - if zRange >= 0.0: - zIncrement = zRange / numberOfLayersFloat - for layerIndex in xrange( numberOfLayers ): - settings.printProgressByNumber(layerIndex, numberOfLayers, 'coil') - boundaryLayers = self.boundaryLayers - if layerIndex % 2 == 1: - boundaryLayers = self.boundaryReverseLayers - radius = startOutset + layerIndex * self.layerThickness - z = startZ + layerIndex * zIncrement - self.addCoilLayer( boundaryLayers, radius, z ) - - def addCoilToThread(self, beginLocation, endZ, loop, thread): - """Add a coil to the thread.""" - if len(loop) < 1: - return - loop = euclidean.getLoopStartingNearest(self.halfPerimeterWidth, self.oldLocationComplex, loop) - length = euclidean.getLoopLength(loop) - if length <= 0.0: - return - oldPoint = loop[0] - pathLength = 0.0 - for point in loop[1 :]: - pathLength += abs(point - oldPoint) - along = pathLength / length - z = (1.0 - along) * beginLocation.z + along * endZ - location = Vector3(point.real, point.imag, z) - thread.append(location) - oldPoint = point - self.oldLocationComplex = loop[-1] - - def addGcodeFromThread( self, thread ): - """Add a thread to the output.""" - if len(thread) > 0: - firstLocation = thread[0] - self.distanceFeedRate.addGcodeMovementZ( firstLocation.dropAxis(), firstLocation.z ) - else: - print( "zero length vertex positions array which was skipped over, this should never happen" ) - if len(thread) < 2: - print( "thread of only one point in addGcodeFromThread in coil, this should never happen" ) - print(thread) - return - self.distanceFeedRate.addLine('M101') # Turn extruder on. - for location in thread[1 :]: - self.distanceFeedRate.addGcodeMovementZ( location.dropAxis(), location.z ) - self.distanceFeedRate.addLine('M103') # Turn extruder off. - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the coil gcode.""" - self.repository = repository - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - self.parseBoundaries() - self.parseUntilLayer() - self.addCoilLayers() - self.distanceFeedRate.addLines( self.shutdownLines ) - return self.distanceFeedRate.output.getvalue() - - def parseBoundaries(self): - """Parse the boundaries and add them to the boundary layers.""" - boundaryLoop = None - boundaryLayer = None - for line in self.lines[self.lineIndex :]: - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if len( self.shutdownLines ) > 0: - self.shutdownLines.append(line) - if firstWord == '()': - boundaryLoop = None - elif firstWord == '(': - location = gcodec.getLocationFromSplitLine(None, splitLine) - if boundaryLoop is None: - boundaryLoop = [] - boundaryLayer.loops.append(boundaryLoop) - boundaryLoop.append(location.dropAxis()) - elif firstWord == '(': - boundaryLayer = euclidean.LoopLayer(float(splitLine[1])) - self.boundaryLayers.append(boundaryLayer) - elif firstWord == '()': - self.shutdownLines = [ line ] - for boundaryLayer in self.boundaryLayers: - if not euclidean.isWiddershins( boundaryLayer.loops[0] ): - boundaryLayer.loops[0].reverse() - self.boundaryReverseLayers = self.boundaryLayers[:] - self.boundaryReverseLayers.reverse() - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( coil )') - return - elif firstWord == '(': - self.layerThickness = float(splitLine[1]) - elif firstWord == '(': - self.perimeterWidth = float(splitLine[1]) - self.halfPerimeterWidth = 0.5 * self.perimeterWidth - self.distanceFeedRate.addLine(line) - - def parseUntilLayer(self): - """Parse until the layer line and add it to the coil skein.""" - for self.lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '(': - return - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the coil dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/drill.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/drill.py deleted file mode 100644 index dba8062..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/drill.py +++ /dev/null @@ -1,258 +0,0 @@ -""" -This page is in the table of contents. -Drill is a script to drill down small holes. - -==Operation== -The default 'Activate Drill' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Drilling Margin=== -The drill script will move the tool from the top of the hole plus the 'Drilling Margin on Top', to the bottom of the hole minus the 'Drilling Margin on Bottom'. - -===Drilling Margin on Top=== -Default is three millimeters. - -===Drilling Margin on Bottom=== -Default is one millimeter. - -==Examples== -The following examples drill the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and drill.py. - -> python drill.py -This brings up the drill dialog. - -> python drill.py Screw Holder Bottom.stl -The drill tool is parsing the file: -Screw Holder Bottom.stl -.. -The drill tool has created the file: -.. Screw Holder Bottom_drill.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - -def getCraftedText( fileName, text, repository=None): - """Drill a gcode linear move file or text.""" - return getCraftedTextFromText(archive.getTextIfEmpty(fileName, text), repository) - -def getCraftedTextFromText(gcodeText, repository=None): - """Drill a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'drill'): - return gcodeText - if repository is None: - repository = settings.getReadRepository( DrillRepository() ) - if not repository.activateDrill.value: - return gcodeText - return DrillSkein().getCraftedGcode(gcodeText, repository) - -def getNewRepository(): - """Get new repository.""" - return DrillRepository() - -def getPolygonCenter( polygon ): - """Get the centroid of a polygon.""" - pointSum = complex() - areaSum = 0.0 - for pointIndex in xrange( len( polygon ) ): - pointBegin = polygon[pointIndex] - pointEnd = polygon[ (pointIndex + 1) % len( polygon ) ] - area = pointBegin.real * pointEnd.imag - pointBegin.imag * pointEnd.real - areaSum += area - pointSum += complex( pointBegin.real + pointEnd.real, pointBegin.imag + pointEnd.imag ) * area - return pointSum / 3.0 / areaSum - -def writeOutput(fileName, shouldAnalyze=True): - """Drill a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'drill', shouldAnalyze) - - -class ThreadLayer: - """A layer of loops and paths.""" - def __init__( self, z ): - """Thread layer constructor.""" - self.points = [] - self.z = z - - def __repr__(self): - """Get the string representation of this thread layer.""" - return '%s, %s' % ( self.z, self.points ) - - -class DrillRepository: - """A class to handle the drill settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.drill.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Drill', self, '') - self.activateDrill = settings.BooleanSetting().getFromValue('Activate Drill', self, True ) - self.drillingMarginOnBottom = settings.FloatSpin().getFromValue( 0.0, 'Drilling Margin on Bottom (millimeters):', self, 5.0, 1.0 ) - self.drillingMarginOnTop = settings.FloatSpin().getFromValue( 0.0, 'Drilling Margin on Top (millimeters):', self, 20.0, 3.0 ) - self.executeTitle = 'Drill' - - def execute(self): - """Drill button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class DrillSkein: - """A class to drill a skein of extrusions.""" - def __init__(self): - self.boundary = None - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.extruderActive = False - self.halfLayerThickness = 0.4 - self.isDrilled = False - self.lineIndex = 0 - self.lines = None - self.maximumDistance = 0.06 - self.oldLocation = None - self.threadLayer = None - self.threadLayers = [] - - def addDrillHoles(self): - """Parse a gcode line.""" - self.isDrilled = True - if len( self.threadLayers ) < 1: - return - topThreadLayer = self.threadLayers[0] - drillPoints = topThreadLayer.points - for drillPoint in drillPoints: - zTop = topThreadLayer.z + self.halfLayerThickness + self.repository.drillingMarginOnTop.value - drillingCenterDepth = self.getDrillingCenterDepth( topThreadLayer.z, drillPoint ) - zBottom = drillingCenterDepth - self.halfLayerThickness - self.repository.drillingMarginOnBottom.value - self.addGcodeFromVerticalThread( drillPoint, zTop, zBottom ) - - def addGcodeFromVerticalThread( self, point, zBegin, zEnd ): - """Add a thread to the output.""" - self.distanceFeedRate.addGcodeMovementZ( point, zBegin ) - self.distanceFeedRate.addLine('M101') # Turn extruder on. - self.distanceFeedRate.addGcodeMovementZ( point, zEnd ) - self.distanceFeedRate.addLine('M103') # Turn extruder off. - - def addThreadLayerIfNone(self): - """Add a thread layer if it is none.""" - if self.threadLayer is not None: - return - self.threadLayer = ThreadLayer( self.layerZ ) - self.threadLayers.append( self.threadLayer ) - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the drill gcode.""" - self.lines = archive.getTextLines(gcodeText) - self.repository = repository - self.parseInitialization() - for line in self.lines[self.lineIndex :]: - self.parseSurroundingLoop(line) - for line in self.lines[self.lineIndex :]: - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getDrillingCenterDepth( self, drillingCenterDepth, drillPoint ): - """Get the drilling center depth.""" - for threadLayer in self.threadLayers[1 :]: - if self.isPointClose( drillPoint, threadLayer.points ): - drillingCenterDepth = threadLayer.z - else: - return drillingCenterDepth - return drillingCenterDepth - - def isPointClose( self, drillPoint, points ): - """Determine if a point on the thread layer is close.""" - for point in points: - if abs( point - drillPoint ) < self.maximumDistance: - return True - return False - - def linearMove( self, splitLine ): - """Add a linear move to the loop.""" - self.addThreadLayerIfNone() - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - if self.extruderActive: - self.boundary = None - self.oldLocation = location - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( drill )') - return - elif firstWord == '(': - self.halfLayerThickness = 0.5 * float(splitLine[1]) - elif firstWord == '(': - self.maximumDistance = 0.1 * float(splitLine[1]) - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - self.distanceFeedRate.addLine(line) - if firstWord == '(': - if not self.isDrilled: - self.addDrillHoles() - - def parseSurroundingLoop(self, line): - """Parse a surrounding loop.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - self.linearMove(splitLine) - if firstWord == 'M101': - self.extruderActive = True - elif firstWord == 'M103': - self.extruderActive = False - elif firstWord == '(': - location = gcodec.getLocationFromSplitLine(None, splitLine) - if self.boundary is None: - self.boundary = [] - self.boundary.append(location.dropAxis()) - elif firstWord == '(': - self.layerZ = float(splitLine[1]) - self.threadLayer = None - elif firstWord == '()': - self.addThreadLayerIfNone() - elif firstWord == '()': - if self.boundary is not None: - self.threadLayer.points.append( getPolygonCenter( self.boundary ) ) - self.boundary = None - - -def main(): - """Display the drill dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/feed.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/feed.py deleted file mode 100644 index 4cc4350..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/feed.py +++ /dev/null @@ -1,176 +0,0 @@ -""" -This page is in the table of contents. -The feed script sets the maximum feed rate, operating feed rate & travel feed rate. - -==Operation== -The default 'Activate Feed' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Feed Rate=== -Default is 16 millimeters/second. - -Defines the feed rate for the shape. - -===Maximum Z Drill Feed Rate=== -Default is 0.1 millimeters/second. - -If your firmware limits the z feed rate, you do not need to set this setting. - -Defines the maximum feed that the tool head will move in the z direction while the tool is on. - -===Travel Feed Rate=== -Default is 16 millimeters/second. - -Defines the feed rate when the cutter is off. The travel feed rate could be set as high as the cutter can be moved, it does not have to be limited by the maximum cutter rate. - -==Examples== -The following examples feed the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and feed.py. - -> python feed.py -This brings up the feed dialog. - -> python feed.py Screw Holder Bottom.stl -The feed tool is parsing the file: -Screw Holder Bottom.stl -.. -The feed tool has created the file: -.. Screw Holder Bottom_feed.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText(fileName, gcodeText='', repository=None): - """Feed the file or text.""" - return getCraftedTextFromText( archive.getTextIfEmpty( fileName, gcodeText ), repository ) - -def getCraftedTextFromText(gcodeText, repository=None): - """Feed a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty(gcodeText, 'feed'): - return gcodeText - if repository is None: - repository = settings.getReadRepository(FeedRepository()) - if not repository.activateFeed.value: - return gcodeText - return FeedSkein().getCraftedGcode(gcodeText, repository) - -def getNewRepository(): - """Get new repository.""" - return FeedRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Feed a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'feed', shouldAnalyze) - - -class FeedRepository: - """A class to handle the feed settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.feed.html', self) - self.fileNameInput = settings.FileNameInput().getFromFileName(fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Feed', self, '') - self.activateFeed = settings.BooleanSetting().getFromValue('Activate Feed:', self, True) - self.feedRatePerSecond = settings.FloatSpin().getFromValue(2.0, 'Feed Rate (mm/s):', self, 50.0, 16.0) - self.maximumZDrillFeedRatePerSecond = settings.FloatSpin().getFromValue(0.02, 'Maximum Z Drill Feed Rate (mm/s):', self, 0.5, 0.1) - self.travelFeedRatePerSecond = settings.FloatSpin().getFromValue(2.0, 'Travel Feed Rate (mm/s):', self, 50.0, 16.0) - self.executeTitle = 'Feed' - - def execute(self): - """Feed button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class FeedSkein: - """A class to feed a skein of cuttings.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.feedRatePerSecond = 16.0 - self.isExtruderActive = False - self.lineIndex = 0 - self.lines = None - self.oldFlowrateString = None - self.oldLocation = None - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the feed gcode.""" - self.repository = repository - self.feedRatePerSecond = repository.feedRatePerSecond.value - self.travelFeedRateMinute = 60.0 * self.repository.travelFeedRatePerSecond.value - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - for line in self.lines[self.lineIndex :]: - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getFeededLine(self, line, splitLine): - """Get gcode line with feed rate.""" - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - self.oldLocation = location - feedRateMinute = 60.0 * self.feedRatePerSecond - if not self.isExtruderActive: - feedRateMinute = self.travelFeedRateMinute - return self.distanceFeedRate.getLineWithFeedRate(feedRateMinute, line, splitLine) - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( feed )') - return - elif firstWord == '(': - self.absolutePerimeterWidth = abs(float(splitLine[1])) - self.distanceFeedRate.addTagBracketedLine('maximumZDrillFeedRatePerSecond', self.repository.maximumZDrillFeedRatePerSecond.value) - self.distanceFeedRate.addTagBracketedLine('operatingFeedRatePerSecond', self.feedRatePerSecond) - self.distanceFeedRate.addTagBracketedLine('travelFeedRatePerSecond', self.repository.travelFeedRatePerSecond.value) - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the feed skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - line = self.getFeededLine(line, splitLine) - elif firstWord == 'M101': - self.isExtruderActive = True - elif firstWord == 'M103': - self.isExtruderActive = False - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the feed dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor(getNewRepository()) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/fillet.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/fillet.py deleted file mode 100644 index ae59a6a..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/fillet.py +++ /dev/null @@ -1,393 +0,0 @@ -""" -This page is in the table of contents. -Fillet rounds the corners slightly in a variety of ways. This is to reduce corner blobbing and sudden extruder acceleration. - -The fillet manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Fillet - -==Operation== -The default 'Activate Fillet' checkbox is off. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Fillet Procedure Choice=== -Default is 'Bevel''. - -====Arc Point==== -When selected, the corners will be filleted with an arc using the gcode point form. - -====Arc Radius==== -When selected, the corners will be filleted with an arc using the gcode radius form. - -====Arc Segment==== -When selected, the corners will be filleted with an arc composed of several segments. - -====Bevel==== -When selected, the corners will be beveled. - -===Corner Feed Rate over Operating Feed Rate=== -Default is one. - -Defines the ratio of the feed rate in corners over the operating feed rate. With a high value the extruder will move quickly in corners, accelerating quickly and leaving a thin extrusion. With a low value, the extruder will move slowly in corners, accelerating gently and leaving a thick extrusion. - -===Fillet Radius over Perimeter Width=== -Default is 0.35. - -Defines the width of the fillet. - -===Reversal Slowdown over Perimeter Width=== -Default is 0.5. - -Defines how far before a path reversal the extruder will slow down. Some tools, like nozzle wipe, double back the path of the extruder and this option will add a slowdown point in that path so there won't be a sudden jerk at the end of the path. If the value is less than 0.1 a slowdown will not be added. - -===Use Intermediate Feed Rate in Corners=== -Default is on. - -When selected, the feed rate entering the corner will be the average of the old feed rate and the new feed rate. - -==Examples== -The following examples fillet the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and fillet.py. - -> python fillet.py -This brings up the fillet dialog. - -> python fillet.py Screw Holder Bottom.stl -The fillet tool is parsing the file: -Screw Holder Bottom.stl -.. -The fillet tool has created the file: -.. Screw Holder Bottom_fillet.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, gcodeText, repository = None ): - """Fillet a gcode linear move file or text.""" - return getCraftedTextFromText( archive.getTextIfEmpty( fileName, gcodeText ), repository ) - -def getCraftedTextFromText( gcodeText, repository = None ): - """Fillet a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'fillet'): - return gcodeText - if repository is None: - repository = settings.getReadRepository( FilletRepository() ) - if not repository.activateFillet.value: - return gcodeText - if repository.arcPoint.value: - return ArcPointSkein().getCraftedGcode( repository, gcodeText ) - elif repository.arcRadius.value: - return ArcRadiusSkein().getCraftedGcode( repository, gcodeText ) - elif repository.arcSegment.value: - return ArcSegmentSkein().getCraftedGcode( repository, gcodeText ) - elif repository.bevel.value: - return BevelSkein().getCraftedGcode( repository, gcodeText ) - return gcodeText - -def getNewRepository(): - """Get new repository.""" - return FilletRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Fillet a gcode linear move file. Depending on the settings, either arcPoint, arcRadius, arcSegment, bevel or do nothing.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'fillet', shouldAnalyze) - - -class BevelSkein: - """A class to bevel a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.extruderActive = False - self.feedRateMinute = 960.0 - self.filletRadius = 0.2 - self.lineIndex = 0 - self.lines = None - self.oldFeedRateMinute = None - self.oldLocation = None - self.shouldAddLine = True - - def addLinearMovePoint( self, feedRateMinute, point ): - """Add a gcode linear move, feedRate and newline to the output.""" - self.distanceFeedRate.addLine( self.distanceFeedRate.getLinearGcodeMovementWithFeedRate( feedRateMinute, point.dropAxis(), point.z ) ) - - def getCornerFeedRate(self): - """Get the corner feed rate, which may be based on the intermediate feed rate.""" - feedRateMinute = self.feedRateMinute - if self.repository.useIntermediateFeedRateInCorners.value: - if self.oldFeedRateMinute is not None: - feedRateMinute = 0.5 * ( self.oldFeedRateMinute + self.feedRateMinute ) - return feedRateMinute * self.cornerFeedRateOverOperatingFeedRate - - def getCraftedGcode( self, repository, gcodeText ): - """Parse gcode text and store the bevel gcode.""" - self.cornerFeedRateOverOperatingFeedRate = repository.cornerFeedRateOverOperatingFeedRate.value - self.lines = archive.getTextLines(gcodeText) - self.repository = repository - self.parseInitialization( repository ) - for self.lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[self.lineIndex] - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getExtruderOffReversalPoint( self, afterSegment, afterSegmentComplex, beforeSegment, beforeSegmentComplex, location ): - """If the extruder is off and the path is reversing, add intermediate slow points.""" - if self.repository.reversalSlowdownDistanceOverPerimeterWidth.value < 0.1: - return None - if self.extruderActive: - return None - reversalBufferSlowdownDistance = self.reversalSlowdownDistance * 2.0 - afterSegmentComplexLength = abs( afterSegmentComplex ) - if afterSegmentComplexLength < reversalBufferSlowdownDistance: - return None - beforeSegmentComplexLength = abs( beforeSegmentComplex ) - if beforeSegmentComplexLength < reversalBufferSlowdownDistance: - return None - afterSegmentComplexNormalized = afterSegmentComplex / afterSegmentComplexLength - beforeSegmentComplexNormalized = beforeSegmentComplex / beforeSegmentComplexLength - if euclidean.getDotProduct( afterSegmentComplexNormalized, beforeSegmentComplexNormalized ) < 0.95: - return None - slowdownFeedRate = self.feedRateMinute * 0.5 - self.shouldAddLine = False - beforePoint = euclidean.getPointPlusSegmentWithLength( self.reversalSlowdownDistance * abs( beforeSegment ) / beforeSegmentComplexLength, location, beforeSegment ) - self.addLinearMovePoint( self.feedRateMinute, beforePoint ) - self.addLinearMovePoint( slowdownFeedRate, location ) - afterPoint = euclidean.getPointPlusSegmentWithLength( self.reversalSlowdownDistance * abs( afterSegment ) / afterSegmentComplexLength, location, afterSegment ) - self.addLinearMovePoint( slowdownFeedRate, afterPoint ) - return afterPoint - - def getNextLocation(self): - """Get the next linear move. Return none is none is found.""" - for afterIndex in xrange( self.lineIndex + 1, len(self.lines) ): - line = self.lines[ afterIndex ] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if gcodec.getFirstWord(splitLine) == 'G1': - nextLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - return nextLocation - return None - - def linearMove( self, splitLine ): - """Bevel a linear move.""" - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) - if self.oldLocation is not None: - nextLocation = self.getNextLocation() - if nextLocation is not None: - location = self.splitPointGetAfter( location, nextLocation ) - self.oldLocation = location - self.oldFeedRateMinute = self.feedRateMinute - - def parseInitialization( self, repository ): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( fillet )') - return - elif firstWord == '(': - perimeterWidth = abs(float(splitLine[1])) - self.curveSection = 0.7 * perimeterWidth - self.filletRadius = perimeterWidth * repository.filletRadiusOverPerimeterWidth.value - self.minimumRadius = 0.1 * perimeterWidth - self.reversalSlowdownDistance = perimeterWidth * repository.reversalSlowdownDistanceOverPerimeterWidth.value - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the bevel gcode.""" - self.shouldAddLine = True - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - self.linearMove(splitLine) - elif firstWord == 'M101': - self.extruderActive = True - elif firstWord == 'M103': - self.extruderActive = False - if self.shouldAddLine: - self.distanceFeedRate.addLine(line) - - def splitPointGetAfter( self, location, nextLocation ): - """Bevel a point and return the end of the bevel. should get complex for radius""" - if self.filletRadius < 2.0 * self.minimumRadius: - return location - afterSegment = nextLocation - location - afterSegmentComplex = afterSegment.dropAxis() - afterSegmentComplexLength = abs( afterSegmentComplex ) - thirdAfterSegmentLength = 0.333 * afterSegmentComplexLength - if thirdAfterSegmentLength < self.minimumRadius: - return location - beforeSegment = self.oldLocation - location - beforeSegmentComplex = beforeSegment.dropAxis() - beforeSegmentComplexLength = abs( beforeSegmentComplex ) - thirdBeforeSegmentLength = 0.333 * beforeSegmentComplexLength - if thirdBeforeSegmentLength < self.minimumRadius: - return location - extruderOffReversalPoint = self.getExtruderOffReversalPoint( afterSegment, afterSegmentComplex, beforeSegment, beforeSegmentComplex, location ) - if extruderOffReversalPoint is not None: - return extruderOffReversalPoint - bevelRadius = min( thirdAfterSegmentLength, self.filletRadius ) - bevelRadius = min( thirdBeforeSegmentLength, bevelRadius ) - self.shouldAddLine = False - beforePoint = euclidean.getPointPlusSegmentWithLength( bevelRadius * abs( beforeSegment ) / beforeSegmentComplexLength, location, beforeSegment ) - self.addLinearMovePoint( self.feedRateMinute, beforePoint ) - afterPoint = euclidean.getPointPlusSegmentWithLength( bevelRadius * abs( afterSegment ) / afterSegmentComplexLength, location, afterSegment ) - self.addLinearMovePoint( self.getCornerFeedRate(), afterPoint ) - return afterPoint - - -class ArcSegmentSkein( BevelSkein ): - """A class to arc segment a skein of extrusions.""" - def addArc( self, afterCenterDifferenceAngle, afterPoint, beforeCenterSegment, beforePoint, center ): - """Add arc segments to the filleted skein.""" - absoluteDifferenceAngle = abs( afterCenterDifferenceAngle ) -# steps = int( math.ceil( absoluteDifferenceAngle * 1.5 ) ) - steps = int( math.ceil( min( absoluteDifferenceAngle * 1.5, absoluteDifferenceAngle * abs( beforeCenterSegment ) / self.curveSection ) ) ) - stepPlaneAngle = euclidean.getWiddershinsUnitPolar( afterCenterDifferenceAngle / steps ) - for step in xrange( 1, steps ): - beforeCenterSegment = euclidean.getRoundZAxisByPlaneAngle( stepPlaneAngle, beforeCenterSegment ) - arcPoint = center + beforeCenterSegment - self.addLinearMovePoint( self.getCornerFeedRate(), arcPoint ) - self.addLinearMovePoint( self.getCornerFeedRate(), afterPoint ) - - def splitPointGetAfter( self, location, nextLocation ): - """Fillet a point into arc segments and return the end of the last segment.""" - if self.filletRadius < 2.0 * self.minimumRadius: - return location - afterSegment = nextLocation - location - afterSegmentComplex = afterSegment.dropAxis() - thirdAfterSegmentLength = 0.333 * abs( afterSegmentComplex ) - if thirdAfterSegmentLength < self.minimumRadius: - return location - beforeSegment = self.oldLocation - location - beforeSegmentComplex = beforeSegment.dropAxis() - thirdBeforeSegmentLength = 0.333 * abs( beforeSegmentComplex ) - if thirdBeforeSegmentLength < self.minimumRadius: - return location - extruderOffReversalPoint = self.getExtruderOffReversalPoint( afterSegment, afterSegmentComplex, beforeSegment, beforeSegmentComplex, location ) - if extruderOffReversalPoint is not None: - return extruderOffReversalPoint - bevelRadius = min( thirdAfterSegmentLength, self.filletRadius ) - bevelRadius = min( thirdBeforeSegmentLength, bevelRadius ) - self.shouldAddLine = False - beforePoint = euclidean.getPointPlusSegmentWithLength( bevelRadius * abs( beforeSegment ) / abs( beforeSegmentComplex ), location, beforeSegment ) - self.addLinearMovePoint( self.feedRateMinute, beforePoint ) - afterPoint = euclidean.getPointPlusSegmentWithLength( bevelRadius * abs( afterSegment ) / abs( afterSegmentComplex ), location, afterSegment ) - afterPointComplex = afterPoint.dropAxis() - beforePointComplex = beforePoint.dropAxis() - locationComplex = location.dropAxis() - midpoint = 0.5 * ( afterPoint + beforePoint ) - midpointComplex = midpoint.dropAxis() - midpointMinusLocationComplex = midpointComplex - locationComplex - midpointLocationLength = abs( midpointMinusLocationComplex ) - if midpointLocationLength < 0.01 * self.filletRadius: - self.addLinearMovePoint( self.getCornerFeedRate(), afterPoint ) - return afterPoint - midpointAfterPointLength = abs( midpointComplex - afterPointComplex ) - midpointCenterLength = midpointAfterPointLength * midpointAfterPointLength / midpointLocationLength - radius = math.sqrt( midpointCenterLength * midpointCenterLength + midpointAfterPointLength * midpointAfterPointLength ) - centerComplex = midpointComplex + midpointMinusLocationComplex * midpointCenterLength / midpointLocationLength - center = Vector3( centerComplex.real, centerComplex.imag, midpoint.z ) - afterCenterComplex = afterPointComplex - centerComplex - beforeCenter = beforePoint - center - angleDifference = euclidean.getAngleDifferenceByComplex( afterCenterComplex, beforeCenter.dropAxis() ) - self.addArc( angleDifference, afterPoint, beforeCenter, beforePoint, center ) - return afterPoint - - -class ArcPointSkein( ArcSegmentSkein ): - """A class to arc point a skein of extrusions.""" - def addArc( self, afterCenterDifferenceAngle, afterPoint, beforeCenterSegment, beforePoint, center ): - """Add an arc point to the filleted skein.""" - if afterCenterDifferenceAngle == 0.0: - return - afterPointMinusBefore = afterPoint - beforePoint - centerMinusBefore = center - beforePoint - firstWord = 'G3' - if afterCenterDifferenceAngle < 0.0: - firstWord = 'G2' - centerMinusBeforeComplex = centerMinusBefore.dropAxis() - if abs( centerMinusBeforeComplex ) <= 0.0: - return - radius = abs( centerMinusBefore ) - arcDistanceZ = complex( abs( afterCenterDifferenceAngle ) * radius, afterPointMinusBefore.z ) - distance = abs( arcDistanceZ ) - if distance <= 0.0: - return - line = self.distanceFeedRate.getFirstWordMovement( firstWord, afterPointMinusBefore ) + self.getRelativeCenter( centerMinusBeforeComplex ) - cornerFeedRate = self.getCornerFeedRate() - if cornerFeedRate is not None: - line += ' F' + self.distanceFeedRate.getRounded(cornerFeedRate) - self.distanceFeedRate.addLine(line) - - def getRelativeCenter( self, centerMinusBeforeComplex ): - """Get the relative center.""" - return ' I%s J%s' % ( self.distanceFeedRate.getRounded( centerMinusBeforeComplex.real ), self.distanceFeedRate.getRounded( centerMinusBeforeComplex.imag ) ) - - -class ArcRadiusSkein( ArcPointSkein ): - """A class to arc radius a skein of extrusions.""" - def getRelativeCenter( self, centerMinusBeforeComplex ): - """Get the relative center.""" - radius = abs( centerMinusBeforeComplex ) - return ' R' + ( self.distanceFeedRate.getRounded(radius) ) - - -class FilletRepository: - """A class to handle the fillet settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.fillet.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File to be Filleted', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Fillet') - self.activateFillet = settings.BooleanSetting().getFromValue('Activate Fillet', self, False ) - self.filletProcedureChoiceLabel = settings.LabelDisplay().getFromName('Fillet Procedure Choice: ', self ) - filletLatentStringVar = settings.LatentStringVar() - self.arcPoint = settings.Radio().getFromRadio( filletLatentStringVar, 'Arc Point', self, False ) - self.arcRadius = settings.Radio().getFromRadio( filletLatentStringVar, 'Arc Radius', self, False ) - self.arcSegment = settings.Radio().getFromRadio( filletLatentStringVar, 'Arc Segment', self, False ) - self.bevel = settings.Radio().getFromRadio( filletLatentStringVar, 'Bevel', self, True ) - self.cornerFeedRateOverOperatingFeedRate = settings.FloatSpin().getFromValue( 0.8, 'Corner Feed Rate over Operating Feed Rate (ratio):', self, 1.2, 1.0 ) - self.filletRadiusOverPerimeterWidth = settings.FloatSpin().getFromValue( 0.25, 'Fillet Radius over Perimeter Width (ratio):', self, 0.65, 0.35 ) - self.reversalSlowdownDistanceOverPerimeterWidth = settings.FloatSpin().getFromValue( 0.3, 'Reversal Slowdown Distance over Perimeter Width (ratio):', self, 0.7, 0.5 ) - self.useIntermediateFeedRateInCorners = settings.BooleanSetting().getFromValue('Use Intermediate Feed Rate in Corners', self, True ) - self.executeTitle = 'Fillet' - - def execute(self): - """Fillet button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -def main(): - """Display the fillet dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/flow.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/flow.py deleted file mode 100644 index 1207ac4..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/flow.py +++ /dev/null @@ -1,145 +0,0 @@ -""" -This page is in the table of contents. -The flow script sets the flow rate by writing the M108 gcode. - -==Operation== -The default 'Activate Flow' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Flow Rate=== -Default is 210. - -Defines the flow rate which will be written following the M108 command. The flow rate is usually a PWM setting, but could be anything, like the rpm of the tool or the duty cycle of the tool. - -==Examples== -The following examples flow the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and flow.py. - -> python flow.py -This brings up the flow dialog. - -> python flow.py Screw Holder Bottom.stl -The flow tool is parsing the file: -Screw Holder Bottom.stl -.. -The flow tool has created the file: -.. Screw Holder Bottom_flow.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, text='', flowRepository = None ): - """Flow the file or text.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, text), flowRepository ) - -def getCraftedTextFromText( gcodeText, flowRepository = None ): - """Flow a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'flow'): - return gcodeText - if flowRepository is None: - flowRepository = settings.getReadRepository( FlowRepository() ) - if not flowRepository.activateFlow.value: - return gcodeText - return FlowSkein().getCraftedGcode( gcodeText, flowRepository ) - -def getNewRepository(): - """Get new repository.""" - return FlowRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Flow a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'flow', shouldAnalyze) - - -class FlowRepository: - """A class to handle the flow settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.flow.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Flow', self, '') - self.activateFlow = settings.BooleanSetting().getFromValue('Activate Flow:', self, True ) - self.flowRate = settings.FloatSpin().getFromValue( 50.0, 'Flow Rate (arbitrary units):', self, 250.0, 210.0 ) - self.executeTitle = 'Flow' - - def execute(self): - """Flow button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class FlowSkein: - """A class to flow a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.lineIndex = 0 - self.lines = None - self.oldFlowRateString = None - self.oldLocation = None - - def addFlowRateLineIfNecessary(self): - """Add flow rate line.""" - flowRateString = euclidean.getRoundedToThreePlaces( self.flowRepository.flowRate.value ) - if flowRateString != self.oldFlowRateString: - self.distanceFeedRate.addLine('M108 S' + flowRateString ) - self.oldFlowRateString = flowRateString - - def getCraftedGcode( self, gcodeText, flowRepository ): - """Parse gcode text and store the flow gcode.""" - self.flowRepository = flowRepository - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - for line in self.lines[self.lineIndex :]: - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( flow )') - return - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the flow skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1' or firstWord == '(': - self.addFlowRateLineIfNecessary() - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the flow dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/hop.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/hop.py deleted file mode 100644 index 9f2a2ec..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/hop.py +++ /dev/null @@ -1,217 +0,0 @@ -""" -This page is in the table of contents. -Hop is a script to raise the extruder when it is not extruding. - -The hop manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Hop - -==Operation== -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. - -==Settings== -===Hop Over Layer Thickness=== -Default is one. - -Defines the ratio of the hop height over the layer thickness, this is the most important hop setting. - -===Minimum Hop Angle=== -Default is 20 degrees. - -Defines the minimum angle that the path of the extruder will be raised. An angle of ninety means that the extruder will go straight up as soon as it is not extruding and a low angle means the extruder path will gradually rise to the hop height. - -==Examples== -The following examples hop the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and hop.py. - -> python hop.py -This brings up the hop dialog. - -> python hop.py Screw Holder Bottom.stl -The hop tool is parsing the file: -Screw Holder Bottom.stl -.. -The hop tool has created the file: -.. Screw Holder Bottom_hop.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, text, hopRepository = None ): - """Hop a gcode linear move text.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, text), hopRepository ) - -def getCraftedTextFromText( gcodeText, hopRepository = None ): - """Hop a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'hop'): - return gcodeText - if hopRepository is None: - hopRepository = settings.getReadRepository( HopRepository() ) - if not hopRepository.activateHop.value: - return gcodeText - return HopSkein().getCraftedGcode( gcodeText, hopRepository ) - -def getNewRepository(): - """Get new repository.""" - return HopRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Hop a gcode linear move file. Chain hop the gcode if it is not already hopped.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'hop', shouldAnalyze) - - -class HopRepository: - """A class to handle the hop settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.hop.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Hop', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Hop') - self.activateHop = settings.BooleanSetting().getFromValue('Activate Hop', self, False ) - self.hopOverLayerThickness = settings.FloatSpin().getFromValue( 0.5, 'Hop Over Layer Thickness (ratio):', self, 1.5, 1.0 ) - self.minimumHopAngle = settings.FloatSpin().getFromValue( 20.0, 'Minimum Hop Angle (degrees):', self, 60.0, 30.0 ) - self.executeTitle = 'Hop' - - def execute(self): - """Hop button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class HopSkein: - """A class to hop a skein of extrusions.""" - def __init__(self): - """Initialize""" - self.isAlteration = False - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.extruderActive = False - self.feedRateMinute = 961.0 - self.hopHeight = 0.4 - self.hopDistance = self.hopHeight - self.justDeactivated = False - self.lineIndex = 0 - self.lines = None - self.oldLocation = None - - def getCraftedGcode( self, gcodeText, hopRepository ): - """Parse gcode text and store the hop gcode.""" - self.lines = archive.getTextLines(gcodeText) - self.minimumSlope = math.tan( math.radians( hopRepository.minimumHopAngle.value ) ) - self.parseInitialization( hopRepository ) - for self.lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[self.lineIndex] - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getHopLine(self, line): - """Get hopped gcode line.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) - if self.extruderActive or self.isAlteration: - return line - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - highestZ = location.z - if self.oldLocation is not None: - highestZ = max( highestZ, self.oldLocation.z ) - highestZHop = highestZ + self.hopHeight - locationComplex = location.dropAxis() - if self.justDeactivated: - oldLocationComplex = self.oldLocation.dropAxis() - distance = abs( locationComplex - oldLocationComplex ) - if distance < self.minimumDistance: - if self.isNextTravel(): - return self.distanceFeedRate.getLineWithZ( line, splitLine, highestZHop ) - alongRatio = min( 0.41666666, self.hopDistance / distance ) - oneMinusAlong = 1.0 - alongRatio - closeLocation = oldLocationComplex * oneMinusAlong + locationComplex * alongRatio - self.distanceFeedRate.addLine( self.distanceFeedRate.getLineWithZ( line, splitLine, highestZHop ) ) - if self.isNextTravel(): - return self.distanceFeedRate.getLineWithZ( line, splitLine, highestZHop ) - farLocation = oldLocationComplex * alongRatio + locationComplex * oneMinusAlong - self.distanceFeedRate.addGcodeMovementZWithFeedRate( self.feedRateMinute, farLocation, highestZHop ) - return line - if self.isNextTravel(): - return self.distanceFeedRate.getLineWithZ( line, splitLine, highestZHop ) - return line - - def isNextTravel(self): - """Determine if there is another linear travel before the thread ends.""" - for afterIndex in xrange( self.lineIndex + 1, len(self.lines) ): - line = self.lines[ afterIndex ] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = ""; - if len(splitLine) > 0: - firstWord = splitLine[0] - if firstWord == 'G1': - return True - if firstWord == 'M101': - return False - return False - - def parseInitialization( self, hopRepository ): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '(': - layerThickness = float(splitLine[1]) - self.hopHeight = hopRepository.hopOverLayerThickness.value * layerThickness - self.hopDistance = self.hopHeight / self.minimumSlope - self.minimumDistance = 0.5 * layerThickness - elif firstWord == '()': - self.distanceFeedRate.addLine('( hop )') - return - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the bevel gcode.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - line = self.getHopLine(line) - self.oldLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - self.justDeactivated = False - elif firstWord == 'M101': - self.extruderActive = True - elif firstWord == 'M103': - self.extruderActive = False - self.justDeactivated = True - elif firstWord == '()': - self.isAlteration = True - elif firstWord == '()': - self.isAlteration = False - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the hop dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/lift.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/lift.py deleted file mode 100644 index 6ca07d8..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/lift.py +++ /dev/null @@ -1,195 +0,0 @@ -""" -This page is in the table of contents. -Lift will change the altitude of the cutting tool when it is on so that it will cut through the slab at the correct altitude. It will also lift the gcode when the tool is off so that the cutting tool will clear the top of the slab. - -==Operation== -The default 'Activate Lift' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Cutting Lift over Layer Step=== -Default is minus 0.5, because the end mill is the more common tool. - -Defines the ratio of the amount the cutting tool will be lifted over the layer step. If whittle is off the layer step will be the layer thickness, if it is on, it will be the layer step from the whittle gcode. If the cutting tool is like an end mill, where the cutting happens until the end of the tool, then the 'Cutting Lift over Layer Step' should be minus 0.5, so that the end mill cuts to the bottom of the slab. If the cutting tool is like a laser, where the cutting happens around the focal point. the 'Cutting Lift over Layer Step' should be zero, so that the cutting action will be focused in the middle of the slab. - -===Clearance above Top=== -Default is 5 millimeters. - -Defines the distance above the top of the slab the cutting tool will be lifted when will tool is off so that the cutting tool will clear the top of the slab. - -==Examples== -The following examples lift the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and lift.py. - -> python lift.py -This brings up the lift dialog. - -> python lift.py Screw Holder Bottom.stl -The lift tool is parsing the file: -Screw Holder Bottom.stl -.. -The lift tool has created the file: -.. Screw Holder Bottom_lift.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, text='', liftRepository = None ): - """Lift the preface file or text.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, text), liftRepository ) - -def getCraftedTextFromText( gcodeText, liftRepository = None ): - """Lift the preface gcode text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'lift'): - return gcodeText - if liftRepository is None: - liftRepository = settings.getReadRepository( LiftRepository() ) - if not liftRepository.activateLift.value: - return gcodeText - return LiftSkein().getCraftedGcode( liftRepository, gcodeText ) - -def getNewRepository(): - """Get new repository.""" - return LiftRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Lift the carving of a gcode file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'lift', shouldAnalyze) - - -class LiftRepository: - """A class to handle the lift settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.lift.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File to be Lifted', self, '') - self.activateLift = settings.BooleanSetting().getFromValue('Activate Lift:', self, True ) - self.cuttingLiftOverLayerStep = settings.FloatSpin().getFromValue( - 1.0, 'Cutting Lift over Layer Step (ratio):', self, 1.0, - 0.5 ) - self.clearanceAboveTop = settings.FloatSpin().getFromValue( 0.0, 'Clearance above Top (mm):', self, 10.0, 5.0 ) - self.executeTitle = 'Lift' - - def execute(self): - """Lift button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class LiftSkein: - """A class to lift a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.extruderActive = False - self.layerStep = None - self.layerThickness = 0.3333333333 - self.lineIndex = 0 - self.maximumZ = - 912345678.0 - self.oldLocation = None - self.previousActiveMovementLine = None - self.previousInactiveMovementLine = None - - def addPreviousInactiveMovementLineIfNecessary(self): - """Add the previous inactive movement line if necessary.""" - if self.previousInactiveMovementLine is not None: - self.distanceFeedRate.addLine( self.previousInactiveMovementLine ) - self.previousInactiveMovementLine = None - - def getCraftedGcode( self, liftRepository, gcodeText ): - """Parse gcode text and store the lift gcode.""" - self.liftRepository = liftRepository - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - self.oldLocation = None - if self.layerStep is None: - self.layerStep = self.layerThickness - self.cuttingLift = self.layerStep * liftRepository.cuttingLiftOverLayerStep.value - self.setMaximumZ() - self.travelZ = self.maximumZ + 0.5 * self.layerStep + liftRepository.clearanceAboveTop.value - for line in self.lines[self.lineIndex :]: - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getLinearMove( self, line, location, splitLine ): - """Get the linear move.""" - if self.extruderActive: - z = location.z + self.cuttingLift - return self.distanceFeedRate.getLineWithZ( line, splitLine, z ) - if self.previousActiveMovementLine is not None: - previousActiveMovementLineSplit = self.previousActiveMovementLine.split() - self.distanceFeedRate.addLine( self.distanceFeedRate.getLineWithZ( self.previousActiveMovementLine, previousActiveMovementLineSplit, self.travelZ ) ) - self.previousActiveMovementLine = None - self.distanceFeedRate.addLine( self.distanceFeedRate.getLineWithZ( line, splitLine, self.travelZ ) ) - self.previousInactiveMovementLine = line - return '' - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex].lstrip() - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addTagBracketedLine('procedureName', 'lift') - return - elif firstWord == '(': - self.layerThickness = float(splitLine[1]) - elif firstWord == '(': - self.layerStep = float(splitLine[1]) - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the lift skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - line = self.getLinearMove( line, location, splitLine ) - self.previousActiveMovementLine = line - self.oldLocation = location - elif firstWord == 'M101': - self.addPreviousInactiveMovementLineIfNecessary() - self.extruderActive = True - elif firstWord == 'M103': - self.extruderActive = False - self.distanceFeedRate.addLine(line) - - def setMaximumZ(self): - """Set maximum z.""" - localOldLocation = None - for line in self.lines[self.lineIndex :]: - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine( localOldLocation, splitLine ) - self.maximumZ = max( self.maximumZ, location.z ) - localOldLocation = location - - -def main(): - """Display the lift dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/mill.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/mill.py deleted file mode 100644 index 3aa59bd..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/mill.py +++ /dev/null @@ -1,380 +0,0 @@ -""" -This page is in the table of contents. -Mill is a script to mill the outlines. - -==Operation== -The default 'Activate Mill' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Add Loops=== -====Add Inner Loops==== -Default is on. - -When selected, the inner milling loops will be added. - -====Add Outer Loops==== -Default is on. - -When selected, the outer milling loops will be added. - -===Cross Hatch=== -Default is on. - -When selected, there will be alternating horizontal and vertical milling paths, if it is off there will only be horizontal milling paths. - -===Loop Outset=== -====Loop Inner Outset over Perimeter Width==== -Default is 0.5. - -Defines the ratio of the amount the inner milling loop will be outset over the perimeter width. - -====Loop Outer Outset over Perimeter Width==== -Default is one. - -Defines the ratio of the amount the outer milling loop will be outset over the perimeter width. The 'Loop Outer Outset over Perimeter Width' ratio should be greater than the 'Loop Inner Outset over Perimeter Width' ratio. - -===Mill Width over Perimeter Width=== -Default is one. - -Defines the ratio of the mill line width over the perimeter width. If the ratio is one, all the material will be milled. The greater the 'Mill Width over Perimeter Width' the farther apart the mill lines will be and so less of the material will be directly milled, the remaining material might still be removed in chips if the ratio is not much greater than one. - -==Examples== -The following examples mill the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and mill.py. - -> python mill.py -This brings up the mill dialog. - -> python mill.py Screw Holder Bottom.stl -The mill tool is parsing the file: -Screw Holder Bottom.stl -.. -The mill tool has created the file: -Screw Holder Bottom_mill.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import os -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, gcodeText = '', repository=None): - """Mill the file or gcodeText.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, gcodeText), repository ) - -def getCraftedTextFromText(gcodeText, repository=None): - """Mill a gcode linear move gcodeText.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'mill'): - return gcodeText - if repository is None: - repository = settings.getReadRepository( MillRepository() ) - if not repository.activateMill.value: - return gcodeText - return MillSkein().getCraftedGcode(gcodeText, repository) - -def getNewRepository(): - """Get new repository.""" - return MillRepository() - -def getPointsFromSegmentTable(segmentTable): - """Get the points from the segment table.""" - points = [] - segmentTableKeys = segmentTable.keys() - segmentTableKeys.sort() - for segmentTableKey in segmentTableKeys: - for segment in segmentTable[segmentTableKey]: - for endpoint in segment: - points.append(endpoint.point) - return points - -def isPointOfTableInLoop( loop, pointTable ): - """Determine if a point in the point table is in the loop.""" - for point in loop: - if point in pointTable: - return True - return False - -def writeOutput(fileName, shouldAnalyze=True): - """Mill a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'mill', shouldAnalyze) - - -class Average: - """A class to hold values and get the average.""" - def __init__(self): - self.reset() - - def addValue( self, value ): - """Add a value to the total and the number of values.""" - self.numberOfValues += 1 - self.total += value - - def getAverage(self): - """Get the average.""" - if self.numberOfValues == 0: - print('should never happen, self.numberOfValues in Average is zero') - return 0.0 - return self.total / float( self.numberOfValues ) - - def reset(self): - """Set the number of values and the total to the default.""" - self.numberOfValues = 0 - self.total = 0.0 - - -class MillRepository: - """A class to handle the mill settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.mill.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Mill', self, '') - self.activateMill = settings.BooleanSetting().getFromValue('Activate Mill', self, True ) - settings.LabelDisplay().getFromName('- Add Loops -', self ) - self.addInnerLoops = settings.BooleanSetting().getFromValue('Add Inner Loops', self, True ) - self.addOuterLoops = settings.BooleanSetting().getFromValue('Add Outer Loops', self, True ) - self.crossHatch = settings.BooleanSetting().getFromValue('Cross Hatch', self, True ) - settings.LabelDisplay().getFromName('- Loop Outset -', self ) - self.loopInnerOutsetOverPerimeterWidth = settings.FloatSpin().getFromValue( 0.3, 'Loop Inner Outset over Perimeter Width (ratio):', self, 0.7, 0.5 ) - self.loopOuterOutsetOverPerimeterWidth = settings.FloatSpin().getFromValue( 0.8, 'Loop Outer Outset over Perimeter Width (ratio):', self, 1.4, 1.0 ) - self.millWidthOverPerimeterWidth = settings.FloatSpin().getFromValue( 0.8, 'Mill Width over Perimeter Width (ratio):', self, 1.8, 1.0 ) - self.executeTitle = 'Mill' - - def execute(self): - """Mill button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - - -class MillSkein: - """A class to mill a skein of extrusions.""" - def __init__(self): - self.aroundPixelTable = {} - self.average = Average() - self.boundaryLayers = [] - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.isExtruderActive = False - self.layerCount = settings.LayerCount() - self.layerIndex = 0 - self.lineIndex = 0 - self.lines = None - self.oldLocation = None - self.perimeterWidth = 0.6 - - def addGcodeFromLoops(self, loops, z): - """Add gcode from loops.""" - if self.oldLocation is None: - self.oldLocation = Vector3() - self.oldLocation.z = z - for loop in loops: - self.distanceFeedRate.addGcodeFromThreadZ(loop, z) - euclidean.addToThreadsFromLoop(self.halfPerimeterWidth, 'loop', loop, self.oldLocation, self) - - def addGcodeFromThreadZ( self, thread, z ): - """Add a thread to the output.""" - self.distanceFeedRate.addGcodeFromThreadZ( thread, z ) - - def addMillThreads(self): - """Add the mill threads to the skein.""" - boundaryLayer = self.boundaryLayers[self.layerIndex] - endpoints = euclidean.getEndpointsFromSegmentTable( boundaryLayer.segmentTable ) - if len(endpoints) < 1: - return - paths = euclidean.getPathsFromEndpoints(endpoints, 5.0 * self.millWidth, self.aroundPixelTable, self.aroundWidth) - averageZ = self.average.getAverage() - if self.repository.addInnerLoops.value: - self.addGcodeFromLoops( boundaryLayer.innerLoops, averageZ ) - if self.repository.addOuterLoops.value: - self.addGcodeFromLoops( boundaryLayer.outerLoops, averageZ ) - for path in paths: - simplifiedPath = euclidean.getSimplifiedPath( path, self.millWidth ) - self.distanceFeedRate.addGcodeFromThreadZ( simplifiedPath, averageZ ) - - def addSegmentTableLoops( self, boundaryLayerIndex ): - """Add the segment tables and loops to the boundary.""" - boundaryLayer = self.boundaryLayers[boundaryLayerIndex] - euclidean.subtractXIntersectionsTable(boundaryLayer.outerHorizontalTable, boundaryLayer.innerHorizontalTable) - euclidean.subtractXIntersectionsTable(boundaryLayer.outerVerticalTable, boundaryLayer.innerVerticalTable) - boundaryLayer.horizontalSegmentTable = self.getHorizontalSegmentTableForXIntersectionsTable( - boundaryLayer.outerHorizontalTable) - boundaryLayer.verticalSegmentTable = self.getVerticalSegmentTableForXIntersectionsTable( - boundaryLayer.outerVerticalTable) - betweenPoints = getPointsFromSegmentTable(boundaryLayer.horizontalSegmentTable) - betweenPoints += getPointsFromSegmentTable(boundaryLayer.verticalSegmentTable) - innerPoints = euclidean.getPointsByHorizontalDictionary(self.millWidth, boundaryLayer.innerHorizontalTable) - innerPoints += euclidean.getPointsByVerticalDictionary(self.millWidth, boundaryLayer.innerVerticalTable) - innerPointTable = {} - for innerPoint in innerPoints: - innerPointTable[innerPoint] = None - boundaryLayer.innerLoops = [] - boundaryLayer.outerLoops = [] - millRadius = 0.75 * self.millWidth - loops = triangle_mesh.getDescendingAreaOrientedLoops(betweenPoints, betweenPoints, millRadius) - for loop in loops: - if isPointOfTableInLoop(loop, innerPointTable): - boundaryLayer.innerLoops.append(loop) - else: - boundaryLayer.outerLoops.append(loop) - if self.repository.crossHatch.value and boundaryLayerIndex % 2 == 1: - boundaryLayer.segmentTable = boundaryLayer.verticalSegmentTable - else: - boundaryLayer.segmentTable = boundaryLayer.horizontalSegmentTable - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the mill gcode.""" - self.repository = repository - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - self.parseBoundaries() - for line in self.lines[self.lineIndex :]: - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getHorizontalSegmentTableForXIntersectionsTable( self, xIntersectionsTable ): - """Get the horizontal segment table from the xIntersectionsTable.""" - horizontalSegmentTable = {} - xIntersectionsTableKeys = xIntersectionsTable.keys() - xIntersectionsTableKeys.sort() - for xIntersectionsTableKey in xIntersectionsTableKeys: - xIntersections = xIntersectionsTable[ xIntersectionsTableKey ] - segments = euclidean.getSegmentsFromXIntersections( xIntersections, xIntersectionsTableKey * self.millWidth ) - horizontalSegmentTable[ xIntersectionsTableKey ] = segments - return horizontalSegmentTable - - def getHorizontalXIntersectionsTable(self, loops): - """Get the horizontal x intersections table from the loops.""" - horizontalXIntersectionsTable = {} - euclidean.addXIntersectionsFromLoopsForTable(loops, horizontalXIntersectionsTable, self.millWidth) - return horizontalXIntersectionsTable - - def getVerticalSegmentTableForXIntersectionsTable( self, xIntersectionsTable ): - """Get the vertical segment table from the xIntersectionsTable which has the x and y swapped.""" - verticalSegmentTable = {} - xIntersectionsTableKeys = xIntersectionsTable.keys() - xIntersectionsTableKeys.sort() - for xIntersectionsTableKey in xIntersectionsTableKeys: - xIntersections = xIntersectionsTable[ xIntersectionsTableKey ] - segments = euclidean.getSegmentsFromXIntersections( xIntersections, xIntersectionsTableKey * self.millWidth ) - for segment in segments: - for endpoint in segment: - endpoint.point = complex( endpoint.point.imag, endpoint.point.real ) - verticalSegmentTable[ xIntersectionsTableKey ] = segments - return verticalSegmentTable - - def parseBoundaries(self): - """Parse the boundaries and add them to the boundary layers.""" - boundaryLoop = None - boundaryLayer = None - for line in self.lines[self.lineIndex :]: - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == '()': - boundaryLoop = None - elif firstWord == '(': - location = gcodec.getLocationFromSplitLine(None, splitLine) - if boundaryLoop is None: - boundaryLoop = [] - boundaryLayer.loops.append(boundaryLoop) - boundaryLoop.append(location.dropAxis()) - elif firstWord == '(': - boundaryLayer = euclidean.LoopLayer(float(splitLine[1])) - self.boundaryLayers.append(boundaryLayer) - if len(self.boundaryLayers) < 2: - return - for boundaryLayer in self.boundaryLayers: - boundaryLayer.innerOutsetLoops = intercircle.getInsetSeparateLoopsFromLoops( - self.loopInnerOutset, boundaryLayer.loops ) - boundaryLayer.outerOutsetLoops = intercircle.getInsetSeparateLoopsFromLoops( - self.loopOuterOutset, boundaryLayer.loops ) - boundaryLayer.innerHorizontalTable = self.getHorizontalXIntersectionsTable( boundaryLayer.innerOutsetLoops ) - boundaryLayer.outerHorizontalTable = self.getHorizontalXIntersectionsTable( boundaryLayer.outerOutsetLoops ) - boundaryLayer.innerVerticalTable = self.getHorizontalXIntersectionsTable( euclidean.getDiagonalFlippedLoops( boundaryLayer.innerOutsetLoops ) ) - boundaryLayer.outerVerticalTable = self.getHorizontalXIntersectionsTable( euclidean.getDiagonalFlippedLoops( boundaryLayer.outerOutsetLoops ) ) - for boundaryLayerIndex in xrange( len(self.boundaryLayers) - 2, - 1, - 1 ): - boundaryLayer = self.boundaryLayers[ boundaryLayerIndex ] - boundaryLayerBelow = self.boundaryLayers[ boundaryLayerIndex + 1 ] - euclidean.joinXIntersectionsTables( boundaryLayerBelow.outerHorizontalTable, boundaryLayer.outerHorizontalTable ) - euclidean.joinXIntersectionsTables( boundaryLayerBelow.outerVerticalTable, boundaryLayer.outerVerticalTable ) - for boundaryLayerIndex in xrange( 1, len(self.boundaryLayers) ): - boundaryLayer = self.boundaryLayers[ boundaryLayerIndex ] - boundaryLayerAbove = self.boundaryLayers[ boundaryLayerIndex - 1 ] - euclidean.joinXIntersectionsTables( boundaryLayerAbove.innerHorizontalTable, boundaryLayer.innerHorizontalTable ) - euclidean.joinXIntersectionsTables( boundaryLayerAbove.innerVerticalTable, boundaryLayer.innerVerticalTable ) - for boundaryLayerIndex in xrange( len(self.boundaryLayers) ): - self.addSegmentTableLoops(boundaryLayerIndex) - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( mill )') - return - elif firstWord == '(': - self.perimeterWidth = float(splitLine[1]) - self.aroundWidth = 0.1 * self.perimeterWidth - self.halfPerimeterWidth = 0.5 * self.perimeterWidth - self.millWidth = self.perimeterWidth * self.repository.millWidthOverPerimeterWidth.value - self.loopInnerOutset = self.halfPerimeterWidth + self.perimeterWidth * self.repository.loopInnerOutsetOverPerimeterWidth.value - self.loopOuterOutset = self.halfPerimeterWidth + self.perimeterWidth * self.repository.loopOuterOutsetOverPerimeterWidth.value - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the mill skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - if self.isExtruderActive: - self.average.addValue(location.z) - if self.oldLocation is not None: - euclidean.addValueSegmentToPixelTable( self.oldLocation.dropAxis(), location.dropAxis(), self.aroundPixelTable, None, self.aroundWidth ) - self.oldLocation = location - elif firstWord == 'M101': - self.isExtruderActive = True - elif firstWord == 'M103': - self.isExtruderActive = False - elif firstWord == '(': - self.layerCount.printProgressIncrement('mill') - self.aroundPixelTable = {} - self.average.reset() - elif firstWord == '()': - if len(self.boundaryLayers) > self.layerIndex: - self.addMillThreads() - self.layerIndex += 1 - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the mill dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/oozebane.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/oozebane.py deleted file mode 100644 index feccf6e..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/oozebane.py +++ /dev/null @@ -1,581 +0,0 @@ -""" -This page is in the table of contents. -Oozebane is a script to turn off the extruder before the end of a thread and turn it on before the beginning. - -The oozebane manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Oozebane - -After oozebane turns the extruder on, it slows the feed rate down where the thread starts. Then it speeds it up in steps so in theory the thread will remain at roughly the same thickness from the beginning. - -==Operation== -The default 'Activate Oozebane' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===After Startup Distance=== -Default is 1.2. - -When oozebane reaches the point where the extruder would of turned on, it slows down so that the thread will be thick at that point. Afterwards it speeds the extruder back up to operating speed. The speed up distance is the "After Startup Distance". - -===Early Shutdown Distance=== -Default is 1.2. - -Defines the distance before the end of the thread that the extruder will be turned off. It is the most important oozebane setting. A higher distance means the extruder will turn off sooner and the end of the line will be thinner. - -===Early Startup Maximum Distance=== -Default is 1.2. - -Defines the maximum distance before the thread starts that the extruder will be turned on - -===Early Startup Distance Constant=== -Default is twenty. - -The longer the extruder has been off, the earlier the extruder will turn back on, the ratio is one minus one over e to the power of the distance the extruder has been off over the "Early Startup Distance Constant". - -===First Early Startup Distance=== -Default is twenty five. - -Defines the distance before the first thread starts that the extruder will be turned off. This value should be high because, according to Marius, the extruder takes a second or two to extrude when starting for the first time. - -===Minimum Distance for Early Shutdown=== -Default is zero. - -Defines the minimum distance that the extruder has to be off after the thread end for the early shutdown feature to activate. - -===Minimum Distance for Early Startup=== -Default is zero. - -Defines the minimum distance that the extruder has to be off before the thread begins for the early start up feature to activate. - -===Slowdown Startup Steps=== -Default is three. - -When oozebane turns the extruder off, it slows the feed rate down in steps so in theory the thread will remain at roughly the same thickness until the end. The "Slowdown Startup Steps" setting is the number of steps, the more steps the smaller the size of the step that the feed rate will be decreased and the larger the size of the resulting gcode file. - -==Examples== -The following examples oozebane the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and oozebane.py. - -> python oozebane.py -This brings up the oozebane dialog. - -> python oozebane.py Screw Holder Bottom.stl -The oozebane tool is parsing the file: -Screw Holder Bottom.stl -.. -The oozebane tool has created the file: -.. Screw Holder Bottom_oozebane.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, text, oozebaneRepository = None ): - """Oozebane a gcode linear move file or text.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, text), oozebaneRepository ) - -def getCraftedTextFromText( gcodeText, oozebaneRepository = None ): - """Oozebane a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'oozebane'): - return gcodeText - if oozebaneRepository is None: - oozebaneRepository = settings.getReadRepository( OozebaneRepository() ) - if not oozebaneRepository.activateOozebane.value: - return gcodeText - return OozebaneSkein().getCraftedGcode( gcodeText, oozebaneRepository ) - -def getNewRepository(): - """Get new repository.""" - return OozebaneRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Oozebane a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'oozebane', shouldAnalyze) - - -class OozebaneRepository: - """A class to handle the oozebane settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.oozebane.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Oozebane', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Oozebane') - self.activateOozebane = settings.BooleanSetting().getFromValue('Activate Oozebane', self, False ) - self.afterStartupDistance = settings.FloatSpin().getFromValue( 0.7, 'After Startup Distance (millimeters):', self, 1.7, 1.2 ) - self.earlyShutdownDistance = settings.FloatSpin().getFromValue( 0.7, 'Early Shutdown Distance (millimeters):', self, 1.7, 1.2 ) - self.earlyStartupDistanceConstant = settings.FloatSpin().getFromValue( 10.0, 'Early Startup Distance Constant (millimeters):', self, 30.0, 20.0 ) - self.earlyStartupMaximumDistance = settings.FloatSpin().getFromValue( 0.7, 'Early Startup Maximum Distance (millimeters):', self, 1.7, 1.2 ) - self.firstEarlyStartupDistance = settings.FloatSpin().getFromValue( 5.0, 'First Early Startup Distance (millimeters):', self, 45.0, 25.0 ) - self.minimumDistanceForEarlyStartup = settings.FloatSpin().getFromValue( 0.0, 'Minimum Distance for Early Startup (millimeters):', self, 10.0, 0.0 ) - self.minimumDistanceForEarlyShutdown = settings.FloatSpin().getFromValue( 0.0, 'Minimum Distance for Early Shutdown (millimeters):', self, 10.0, 0.0 ) - self.slowdownStartupSteps = settings.IntSpin().getFromValue( 2, 'Slowdown Startup Steps (positive integer):', self, 5, 3 ) - self.executeTitle = 'Oozebane' - - def execute(self): - """Oozebane button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class OozebaneSkein: - """A class to oozebane a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.distanceFromThreadEndToThreadBeginning = None - self.earlyStartupDistance = None - self.extruderInactiveLongEnough = True - self.feedRateMinute = 961.0 - self.isExtruderActive = False - self.isFirstExtrusion = True - self.isShutdownEarly = False - self.isStartupEarly = False - self.lineIndex = 0 - self.lines = None - self.oldLocation = None - self.operatingFeedRateMinute = 959.0 - self.shutdownStepIndex = 999999999 - self.startupStepIndex = 999999999 - - def addAfterStartupLine( self, splitLine ): - """Add the after startup lines.""" - distanceAfterThreadBeginning = self.getDistanceAfterThreadBeginning() - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - segment = self.oldLocation - location - segmentLength = segment.magnitude() - distanceBack = distanceAfterThreadBeginning - self.afterStartupDistances[ self.startupStepIndex ] - if segmentLength > 0.0: - locationBack = location + segment * distanceBack / segmentLength - feedRate = self.operatingFeedRateMinute * self.afterStartupFlowRates[ self.startupStepIndex ] - if not self.isCloseToEither( locationBack, location, self.oldLocation ): - self.distanceFeedRate.addLine( self.getLinearMoveWithFeedRate( feedRate, locationBack ) ) - self.startupStepIndex += 1 - - def addLineSetShutdowns(self, line): - """Add a line and set the shutdown variables.""" - self.distanceFeedRate.addLine(line) - self.isShutdownEarly = True - - def getActiveFeedRateRatio(self): - """Get the feed rate of the first active move over the operating feed rate.""" - isSearchExtruderActive = self.isExtruderActive - for afterIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[ afterIndex ] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1': - if isSearchExtruderActive: - return gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) / self.operatingFeedRateMinute - elif firstWord == 'M101': - isSearchExtruderActive = True - print('active feed rate ratio was not found in oozebane.') - return 1.0 - - def getAddAfterStartupLines(self, line): - """Get and / or add after the startup lines.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - while self.isDistanceAfterThreadBeginningGreater(): - self.addAfterStartupLine(splitLine) - if self.startupStepIndex >= len( self.afterStartupDistances ): - self.startupStepIndex = len( self.afterStartupDistances ) + 999999999999 - return self.getLinearMoveWithFeedRateSplitLine( self.operatingFeedRateMinute, splitLine ) - feedRate = self.operatingFeedRateMinute * self.getStartupFlowRateMultiplier( self.getDistanceAfterThreadBeginning() / self.afterStartupDistance, len( self.afterStartupDistances ) ) - return self.getLinearMoveWithFeedRateSplitLine( feedRate, splitLine ) - - def getAddBeforeStartupLines(self, line): - """Get and / or add before the startup lines.""" - distanceThreadBeginning = self.getDistanceToThreadBeginning() - if distanceThreadBeginning is None: - return line - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - self.extruderInactiveLongEnough = False - self.isStartupEarly = True - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - segment = self.oldLocation - location - segmentLength = segment.magnitude() - distanceBack = self.earlyStartupDistance - distanceThreadBeginning - if segmentLength <= 0.0: - print('This should never happen, segmentLength is zero in getAddBeforeStartupLines in oozebane.') - print(line) - self.extruderInactiveLongEnough = True - self.isStartupEarly = False - return line - locationBack = location + segment * distanceBack / segmentLength - self.distanceFeedRate.addLine( self.getLinearMoveWithFeedRate( gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) , locationBack ) ) - self.distanceFeedRate.addLine('M101') - if self.isCloseToEither( locationBack, location, self.oldLocation ): - return '' - return self.getLinearMoveWithFeedRate( self.operatingFeedRateMinute, location ) - - def getAddShutSlowDownLine(self, line): - """Add the shutdown and slowdown lines.""" - if self.shutdownStepIndex >= len( self.earlyShutdownDistances ): - self.shutdownStepIndex = len( self.earlyShutdownDistances ) + 99999999 - return False - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - distanceThreadEnd = self.getDistanceToExtruderOffCommand( self.earlyShutdownDistances[ self.shutdownStepIndex ] ) - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - if distanceThreadEnd is None: - distanceThreadEnd = self.getDistanceToExtruderOffCommand( self.earlyShutdownDistances[0] ) - if distanceThreadEnd is not None: - shutdownFlowRateMultiplier = self.getShutdownFlowRateMultiplier( 1.0 - distanceThreadEnd / self.earlyShutdownDistance, len( self.earlyShutdownDistances ) ) - line = self.getLinearMoveWithFeedRate( self.feedRateMinute * shutdownFlowRateMultiplier, location ) - self.distanceFeedRate.addLine(line) - return False - segment = self.oldLocation - location - segmentLength = segment.magnitude() - distanceBack = self.earlyShutdownDistances[ self.shutdownStepIndex ] - distanceThreadEnd - locationBack = location - if segmentLength > 0.0: - locationBack = location + segment * distanceBack / segmentLength - if self.shutdownStepIndex == 0: - if not self.isCloseToEither( locationBack, location, self.oldLocation ): - line = self.getLinearMoveWithFeedRate( self.feedRateMinute, locationBack ) - self.distanceFeedRate.addLine(line) - self.addLineSetShutdowns('M103') - return True - if self.isClose( locationBack, self.oldLocation ): - return True - feedRate = self.feedRateMinute * self.earlyShutdownFlowRates[ self.shutdownStepIndex ] - line = self.getLinearMoveWithFeedRate( feedRate, locationBack ) - if self.isClose( locationBack, location ): - line = self.getLinearMoveWithFeedRate( feedRate, location ) - self.distanceFeedRate.addLine(line) - return True - - def getAddShutSlowDownLines(self, line): - """Get and / or add the shutdown and slowdown lines.""" - while self.getAddShutSlowDownLine(line): - self.shutdownStepIndex += 1 - return '' - - def getCraftedGcode( self, gcodeText, oozebaneRepository ): - """Parse gcode text and store the oozebane gcode.""" - self.lines = archive.getTextLines(gcodeText) - self.oozebaneRepository = oozebaneRepository - self.parseInitialization( oozebaneRepository ) - for self.lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[self.lineIndex] - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getDistanceAfterThreadBeginning(self): - """Get the distance after the beginning of the thread.""" - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - lastThreadLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - totalDistance = 0.0 - extruderOnReached = False - for beforeIndex in xrange( self.lineIndex - 1, 3, - 1 ): - line = self.lines[ beforeIndex ] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine( lastThreadLocation, splitLine ) - totalDistance += location.distance( lastThreadLocation ) - lastThreadLocation = location - if extruderOnReached: - return totalDistance - elif firstWord == 'M101': - extruderOnReached = True - return None - - def getDistanceToExtruderOffCommand( self, remainingDistance ): - """Get the distance to the word.""" - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - lastThreadLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - totalDistance = 0.0 - for afterIndex in xrange( self.lineIndex + 1, len(self.lines) ): - line = self.lines[ afterIndex ] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine( lastThreadLocation, splitLine ) - totalDistance += location.distance( lastThreadLocation ) - lastThreadLocation = location - if totalDistance >= remainingDistance: - return None - elif firstWord == 'M103': - return totalDistance - return None - - def getDistanceToThreadBeginning(self): - """Get the distance to the beginning of the thread.""" - if self.earlyStartupDistance is None: - return None - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - lastThreadLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - totalDistance = 0.0 - for afterIndex in xrange( self.lineIndex + 1, len(self.lines) ): - line = self.lines[ afterIndex ] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine( lastThreadLocation, splitLine ) - totalDistance += location.distance( lastThreadLocation ) - lastThreadLocation = location - if totalDistance >= self.earlyStartupDistance: - return None - elif firstWord == 'M101': - return totalDistance - return None - - def getDistanceToThreadBeginningAfterThreadEnd( self, remainingDistance ): - """Get the distance to the thread beginning after the end of this thread.""" - extruderOnReached = False - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - lastThreadLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - threadEndReached = False - totalDistance = 0.0 - for afterIndex in xrange( self.lineIndex + 1, len(self.lines) ): - line = self.lines[ afterIndex ] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine( lastThreadLocation, splitLine ) - if threadEndReached: - totalDistance += location.distance( lastThreadLocation ) - if totalDistance >= remainingDistance: - return None - if extruderOnReached: - return totalDistance - lastThreadLocation = location - elif firstWord == 'M101': - extruderOnReached = True - elif firstWord == 'M103': - threadEndReached = True - return None - - def getDistanceToThreadEnd(self): - """Get the distance to the end of the thread.""" - if self.shutdownStepIndex >= len( self.earlyShutdownDistances ): - return None - return self.getDistanceToExtruderOffCommand( self.earlyShutdownDistances[ self.shutdownStepIndex ] ) - - def getLinearMoveWithFeedRate( self, feedRate, location ): - """Get a linear move line with the feed rate.""" - return self.distanceFeedRate.getLinearGcodeMovementWithFeedRate( feedRate, location.dropAxis(), location.z ) - - def getLinearMoveWithFeedRateSplitLine( self, feedRate, splitLine ): - """Get a linear move line with the feed rate and split line.""" - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - return self.getLinearMoveWithFeedRate( feedRate, location ) - - def getOozebaneLine(self, line): - """Get oozebaned gcode line.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) - if self.oldLocation is None: - return line - if self.startupStepIndex < len( self.afterStartupDistances ): - return self.getAddAfterStartupLines(line) - if self.extruderInactiveLongEnough: - return self.getAddBeforeStartupLines(line) - if self.shutdownStepIndex < len( self.earlyShutdownDistances ): - return self.getAddShutSlowDownLines(line) - if self.isStartupEarly: - return self.getLinearMoveWithFeedRateSplitLine( self.operatingFeedRateMinute, splitLine ) - return line - - def getShutdownFlowRateMultiplier( self, along, numberOfDistances ): - """Get the shut down flow rate multipler.""" - if numberOfDistances <= 0: - return 1.0 - return 1.0 - 0.5 / float( numberOfDistances ) - along * float( numberOfDistances - 1 ) / float( numberOfDistances ) - - def getStartupFlowRateMultiplier( self, along, numberOfDistances ): - """Get the startup flow rate multipler.""" - if numberOfDistances <= 0: - return 1.0 - return min( 1.0, 0.5 / float( numberOfDistances ) + along ) - - def isClose( self, location, otherLocation ): - """Determine if the location is close to the other location.""" - return location.distanceSquared( otherLocation ) < self.closeSquared - - def isCloseToEither( self, location, otherLocationFirst, otherLocationSecond ): - """Determine if the location is close to the other locations.""" - if self.isClose( location, otherLocationFirst ): - return True - return self.isClose( location, otherLocationSecond ) - - def isDistanceAfterThreadBeginningGreater(self): - """Determine if the distance after the thread beginning is greater than the step index after startup distance.""" - if self.startupStepIndex >= len( self.afterStartupDistances ): - return False - return self.getDistanceAfterThreadBeginning() > self.afterStartupDistances[ self.startupStepIndex ] - - def parseInitialization( self, oozebaneRepository ): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( oozebane )') - return - elif firstWord == '(': - self.operatingFeedRateMinute = 60.0 * float(splitLine[1]) - self.feedRateMinute = self.operatingFeedRateMinute - elif firstWord == '(': - self.perimeterWidth = float(splitLine[1]) - self.setExtrusionWidth( oozebaneRepository ) - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the bevel gcode.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - self.setEarlyStartupDistance(splitLine) - line = self.getOozebaneLine(line) - self.oldLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - elif firstWord == 'M101': - self.isExtruderActive = True - self.extruderInactiveLongEnough = False - if self.getDistanceToExtruderOffCommand( self.earlyShutdownDistance ) is None: - self.setEarlyShutdown() - if self.getDistanceToExtruderOffCommand( 1.03 * ( self.earlyShutdownDistance + self.afterStartupDistance ) ) is None: - afterStartupRatio = 1.0 - if self.minimumDistanceForEarlyStartup > 0.0: - if self.distanceFromThreadEndToThreadBeginning is not None: - afterStartupRatio = self.distanceFromThreadEndToThreadBeginning / self.minimumDistanceForEarlyStartup - self.setAfterStartupFlowRates( afterStartupRatio ) - self.startupStepIndex = 9999999999 - if len( self.afterStartupDistances ) > 0: - self.startupStepIndex = 0 - if self.isStartupEarly: - self.isStartupEarly = False - return - elif firstWord == 'M103': - self.isExtruderActive = False - self.shutdownStepIndex = 999999999 - if self.getDistanceToThreadBeginning() is None: - self.extruderInactiveLongEnough = True - self.distanceFromThreadEndToThreadBeginning = None - self.earlyStartupDistance = None - if self.isShutdownEarly: - self.isShutdownEarly = False - return - self.distanceFeedRate.addLine(line) - - def setAfterStartupFlowRates( self, afterStartupRatio ): - """Set the after startup flow rates.""" - afterStartupRatio = min( 1.0, afterStartupRatio ) - afterStartupRatio = max( 0.0, afterStartupRatio ) - self.afterStartupDistance = afterStartupRatio * self.getActiveFeedRateRatio() * self.oozebaneRepository.afterStartupDistance.value - self.afterStartupDistances = [] - self.afterStartupFlowRate = 1.0 - self.afterStartupFlowRates = [] - afterStartupSteps = int( math.floor( afterStartupRatio * float( self.oozebaneRepository.slowdownStartupSteps.value ) ) ) - if afterStartupSteps < 1: - return - if afterStartupSteps < 2: - afterStartupSteps = 2 - for stepIndex in xrange( afterStartupSteps ): - afterWay = ( stepIndex + 1 ) / float( afterStartupSteps ) - afterMiddleWay = self.getStartupFlowRateMultiplier( stepIndex / float( afterStartupSteps ), afterStartupSteps ) - self.afterStartupDistances.append( afterWay * self.afterStartupDistance ) - if stepIndex == 0: - self.afterStartupFlowRate = afterMiddleWay - else: - self.afterStartupFlowRates.append( afterMiddleWay ) - if afterStartupSteps > 0: - self.afterStartupFlowRates.append(1.0) - - def setEarlyStartupDistance( self, splitLine ): - """Set the early startup distance.""" - if self.earlyStartupDistance is not None: - return - self.distanceFromThreadEndToThreadBeginning = 0.0 - lastThreadLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - if self.oldLocation is not None: - self.distanceFromThreadEndToThreadBeginning = lastThreadLocation.distance( self.oldLocation ) - for afterIndex in xrange( self.lineIndex + 1, len(self.lines) ): - line = self.lines[ afterIndex ] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine( lastThreadLocation, splitLine ) - self.distanceFromThreadEndToThreadBeginning += location.distance( lastThreadLocation ) - lastThreadLocation = location - elif firstWord == 'M101': - distanceConstantRatio = self.distanceFromThreadEndToThreadBeginning / self.earlyStartupDistanceConstant - earlyStartupOperatingDistance = self.earlyStartupMaximumDistance * ( 1.0 - math.exp( - distanceConstantRatio ) ) - if self.isFirstExtrusion: - earlyStartupOperatingDistance = self.oozebaneRepository.firstEarlyStartupDistance.value - self.isFirstExtrusion = False - self.earlyStartupDistance = earlyStartupOperatingDistance * self.getActiveFeedRateRatio() - return - - def setExtrusionWidth( self, oozebaneRepository ): - """Set the extrusion width.""" - self.closeSquared = 0.01 * self.perimeterWidth * self.perimeterWidth - self.earlyStartupMaximumDistance = oozebaneRepository.earlyStartupMaximumDistance.value - self.earlyStartupDistanceConstant = oozebaneRepository.earlyStartupDistanceConstant.value - self.minimumDistanceForEarlyStartup = oozebaneRepository.minimumDistanceForEarlyStartup.value - self.minimumDistanceForEarlyShutdown = oozebaneRepository.minimumDistanceForEarlyShutdown.value - self.setEarlyShutdownFlowRates(1.0) - self.setAfterStartupFlowRates(1.0) - - def setEarlyShutdown(self): - """Set the early shutdown variables.""" - distanceToThreadBeginning = self.getDistanceToThreadBeginningAfterThreadEnd( self.minimumDistanceForEarlyShutdown ) - earlyShutdownRatio = 1.0 - if distanceToThreadBeginning is not None: - if self.minimumDistanceForEarlyShutdown > 0.0: - earlyShutdownRatio = distanceToThreadBeginning / self.minimumDistanceForEarlyShutdown - self.setEarlyShutdownFlowRates( earlyShutdownRatio ) - if len( self.earlyShutdownDistances ) > 0: - self.shutdownStepIndex = 0 - - def setEarlyShutdownFlowRates( self, earlyShutdownRatio ): - """Set the extrusion width.""" - earlyShutdownRatio = min( 1.0, earlyShutdownRatio ) - earlyShutdownRatio = max( 0.0, earlyShutdownRatio ) - self.earlyShutdownDistance = earlyShutdownRatio * self.getActiveFeedRateRatio() * self.oozebaneRepository.earlyShutdownDistance.value - self.earlyShutdownDistances = [] - self.earlyShutdownFlowRates = [] - earlyShutdownSteps = int( math.floor( earlyShutdownRatio * float( self.oozebaneRepository.slowdownStartupSteps.value ) ) ) - if earlyShutdownSteps < 2: - earlyShutdownSteps = 0 - earlyShutdownStepsMinusOne = float( earlyShutdownSteps ) - 1.0 - for stepIndex in xrange( earlyShutdownSteps ): - downMiddleWay = self.getShutdownFlowRateMultiplier( stepIndex / earlyShutdownStepsMinusOne, earlyShutdownSteps ) - downWay = 1.0 - stepIndex / earlyShutdownStepsMinusOne - self.earlyShutdownFlowRates.append( downMiddleWay ) - self.earlyShutdownDistances.append( downWay * self.earlyShutdownDistance ) - - -def main(): - """Display the oozebane dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/outset.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/outset.py deleted file mode 100644 index 4fd3bef..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/outset.py +++ /dev/null @@ -1,168 +0,0 @@ -""" -This page is in the table of contents. -Outset outsets the perimeters of the slices of a gcode file. The outside perimeters will be outset by half the perimeter width, and the inside perimeters will be inset by half the perimeter width. Outset is needed for subtractive machining, like cutting or milling. - -==Operation== -The default 'Activate Outset' checkbox is on. When it is on, the gcode will be outset, when it is off, the gcode will not be changed. - -==Examples== -The following examples outset the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and outset.py. - -> python outset.py -This brings up the outset dialog. - -> python outset.py Screw Holder Bottom.stl -The outset tool is parsing the file: -Screw Holder Bottom.stl -.. -The outset tool has created the file: -.. Screw Holder Bottom_outset.gcode - -""" - -from __future__ import absolute_import -try: - import psyco - psyco.full() -except: - pass -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, text='', repository=None): - """Outset the preface file or text.""" - return getCraftedTextFromText(archive.getTextIfEmpty(fileName, text), repository) - -def getCraftedTextFromText(gcodeText, repository=None): - """Outset the preface gcode text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'outset'): - return gcodeText - if repository is None: - repository = settings.getReadRepository( OutsetRepository() ) - if not repository.activateOutset.value: - return gcodeText - return OutsetSkein().getCraftedGcode(gcodeText, repository) - -def getNewRepository(): - """Get new repository.""" - return OutsetRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Outset the carving of a gcode file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'outset', shouldAnalyze) - - -class OutsetRepository: - """A class to handle the outset settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.outset.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Outset', self, '') - self.activateOutset = settings.BooleanSetting().getFromValue('Activate Outset:', self, True ) - self.executeTitle = 'Outset' - - def execute(self): - """Outset button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class OutsetSkein: - """A class to outset a skein of extrusions.""" - def __init__(self): - self.boundary = None - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.layerCount = settings.LayerCount() - self.lineIndex = 0 - self.rotatedLoopLayer = None - - def addGcodeFromRemainingLoop( self, loop, radius, z ): - """Add the remainder of the loop.""" - boundary = intercircle.getLargestInsetLoopFromLoopRegardless( loop, radius ) - euclidean.addSurroundingLoopBeginning( self.distanceFeedRate, boundary, z ) - self.distanceFeedRate.addPerimeterBlock(loop, z) - self.distanceFeedRate.addLine('()') - self.distanceFeedRate.addLine('()') - - def addOutset(self, rotatedLoopLayer): - """Add outset to the layer.""" - extrudateLoops = intercircle.getInsetLoopsFromLoops(-self.absoluteHalfPerimeterWidth, rotatedLoopLayer.loops) - triangle_mesh.sortLoopsInOrderOfArea(False, extrudateLoops) - for extrudateLoop in extrudateLoops: - self.addGcodeFromRemainingLoop(extrudateLoop, self.absoluteHalfPerimeterWidth, rotatedLoopLayer.z) - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the bevel gcode.""" - self.repository = repository - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - for lineIndex in xrange(self.lineIndex, len(self.lines)): - self.parseLine( lineIndex ) - return self.distanceFeedRate.output.getvalue() - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex].lstrip() - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addTagBracketedLine('procedureName', 'outset') - return - elif firstWord == '(': - self.absoluteHalfPerimeterWidth = 0.5 * abs(float(splitLine[1])) - self.distanceFeedRate.addLine(line) - - def parseLine( self, lineIndex ): - """Parse a gcode line and add it to the outset skein.""" - line = self.lines[lineIndex].lstrip() - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == '(': - location = gcodec.getLocationFromSplitLine(None, splitLine) - self.boundary.append(location.dropAxis()) - elif firstWord == '(': - self.layerCount.printProgressIncrement('outset') - self.rotatedLoopLayer = euclidean.RotatedLoopLayer(float(splitLine[1])) - self.distanceFeedRate.addLine(line) - elif firstWord == '()': - self.addOutset( self.rotatedLoopLayer ) - self.rotatedLoopLayer = None - elif firstWord == '()': - self.boundary = [] - self.rotatedLoopLayer.loops.append( self.boundary ) - if self.rotatedLoopLayer is None: - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the outset dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/splodge.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/splodge.py deleted file mode 100644 index 6646b2f..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/splodge.py +++ /dev/null @@ -1,327 +0,0 @@ -""" -This page is in the table of contents. -Splodge turns the extruder on just before the start of a thread. This is to give the extrusion a bit anchoring at the beginning. - -The splodge manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Splodge - -==Operation== -The default 'Activate Splodge' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Initial=== -====Initial Lift over Extra Thickness==== -Default is one. - -Defines the amount the extruder will be lifted over the extra thickness of the initial splodge thread. The higher the ratio, the more the extruder will be lifted over the splodge, if the ratio is too low the extruder might plow through the splodge extrusion. - -====Initial Splodge Feed Rate==== -Default is one millimeter per second. - -Defines the feed rate at which the initial extra extrusion will be added. With the default feed rate, the splodge will be added slower so it will be thicker than the regular extrusion. - -====Initial Splodge Quantity Length==== -Default is thirty millimeters. - -Defines the quantity length of extra extrusion at the operating feed rate that will be added to the initial thread. If a splodge quantity length is smaller than 0.1 times the perimeter width, no splodge of that type will be added. - -===Operating=== -====Operating Lift over Extra Thickness==== -Default is one. - -Defines the amount the extruder will be lifted over the extra thickness of the operating splodge thread. - -====Operating Splodge Feed Rate==== -Default is one millimeter per second. - -Defines the feed rate at which the next extra extrusions will be added. - -====Operating Splodge Quantity Length==== -Default is thirty millimeters. - -Defines the quantity length of extra extrusion at the operating feed rate that will be added for the next threads. - -==Examples== -The following examples splodge the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and splodge.py. - -> python splodge.py -This brings up the splodge dialog. - -> python splodge.py Screw Holder Bottom.stl -The splodge tool is parsing the file: -Screw Holder Bottom.stl -.. -The splodge tool has created the file: -.. Screw Holder Bottom_splodge.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, text, splodgeRepository = None ): - """Splodge a gcode linear move file or text.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, text), splodgeRepository ) - -def getCraftedTextFromText( gcodeText, splodgeRepository = None ): - """Splodge a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'splodge'): - return gcodeText - if splodgeRepository is None: - splodgeRepository = settings.getReadRepository( SplodgeRepository() ) - if not splodgeRepository.activateSplodge.value: - return gcodeText - return SplodgeSkein().getCraftedGcode( gcodeText, splodgeRepository ) - -def getNewRepository(): - """Get new repository.""" - return SplodgeRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Splodge a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'splodge', shouldAnalyze) - - -class SplodgeRepository: - """A class to handle the splodge settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.splodge.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Splodge', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Splodge') - self.activateSplodge = settings.BooleanSetting().getFromValue('Activate Splodge', self, False ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Initial -', self ) - self.initialLiftOverExtraThickness = settings.FloatSpin().getFromValue( 0.5, 'Initial Lift over Extra Thickness (ratio):', self, 1.5, 1.0 ) - self.initialSplodgeFeedRate = settings.FloatSpin().getFromValue( 0.4, 'Initial Splodge Feed Rate (mm/s):', self, 2.4, 1.0 ) - self.initialSplodgeQuantityLength = settings.FloatSpin().getFromValue( 10.0, 'Initial Splodge Quantity Length (millimeters):', self, 90.0, 30.0 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Operating -', self ) - self.operatingLiftOverExtraThickness = settings.FloatSpin().getFromValue( 0.5, 'Operating Lift over Extra Thickness (ratio):', self, 1.5, 1.0 ) - self.operatingSplodgeFeedRate = settings.FloatSpin().getFromValue( 0.4, 'Operating Splodge Feed Rate (mm/s):', self, 2.4, 1.0 ) - self.operatingSplodgeQuantityLength = settings.FloatSpin().getFromValue( 0.4, 'Operating Splodge Quantity Length (millimeters):', self, 2.4, 1.0 ) - settings.LabelSeparator().getFromRepository(self) - self.executeTitle = 'Splodge' - - def execute(self): - """Splodge button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class SplodgeSkein: - """A class to splodge a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.feedRateMinute = 961.0 - self.isExtruderActive = False - self.hasInitialSplodgeBeenAdded = False - self.isLastExtruderCommandActivate = False - self.lastLineOutput = None - self.lineIndex = 0 - self.lines = None - self.oldLocation = None - self.operatingFeedRatePerSecond = 15.0 - - def addLineUnlessIdentical(self, line): - """Add a line, unless it is identical to the last line.""" - if line == self.lastLineOutput: - return - self.lastLineOutput = line - self.distanceFeedRate.addLine(line) - - def addLineUnlessIdenticalReactivate(self, line): - """Add a line, unless it is identical to the last line or another M101.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'M101': - if not self.isLastExtruderCommandActivate: - self.addLineUnlessIdentical(line) - self.isLastExtruderCommandActivate = True - return - if firstWord == 'M103': - self.isLastExtruderCommandActivate = False - self.addLineUnlessIdentical(line) - - def getCraftedGcode( self, gcodeText, splodgeRepository ): - """Parse gcode text and store the splodge gcode.""" - self.lines = archive.getTextLines(gcodeText) - self.setRotations() - self.splodgeRepository = splodgeRepository - self.parseInitialization( splodgeRepository ) - self.boundingRectangle = gcodec.BoundingRectangle().getFromGcodeLines( self.lines[self.lineIndex :], 0.5 * self.perimeterWidth ) - self.initialSplodgeFeedRateMinute = 60.0 * splodgeRepository.initialSplodgeFeedRate.value - self.initialStartupDistance = splodgeRepository.initialSplodgeQuantityLength.value * splodgeRepository.initialSplodgeFeedRate.value / self.operatingFeedRatePerSecond - self.operatingSplodgeFeedRateMinute = 60.0 * splodgeRepository.operatingSplodgeFeedRate.value - self.operatingStartupDistance = splodgeRepository.operatingSplodgeQuantityLength.value * splodgeRepository.operatingSplodgeFeedRate.value / self.operatingFeedRatePerSecond - for self.lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[self.lineIndex] - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getInitialSplodgeLine( self, line, location ): - """Add the initial splodge line.""" - if not self.isJustBeforeExtrusion(): - return line - self.hasInitialSplodgeBeenAdded = True - if self.splodgeRepository.initialSplodgeQuantityLength.value < self.minimumQuantityLength: - return line - return self.getSplodgeLineGivenDistance( self.initialSplodgeFeedRateMinute, line, self.splodgeRepository.initialLiftOverExtraThickness.value, location, self.initialStartupDistance ) - - def getNextActiveLocationComplex(self): - """Get the next active line.""" - isActive = False - for lineIndex in xrange( self.lineIndex + 1, len(self.lines) ): - line = self.lines[lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'M101': - isActive = True - if firstWord == 'G1' and isActive: - return gcodec.getLocationFromSplitLine(self.oldLocation, splitLine).dropAxis() - return None - - def getOperatingSplodgeLine( self, line, location ): - """Get the operating splodge line.""" - if not self.isJustBeforeExtrusion(): - return line - if self.splodgeRepository.operatingSplodgeQuantityLength.value < self.minimumQuantityLength: - return line - return self.getSplodgeLineGivenDistance( self.operatingSplodgeFeedRateMinute, line, self.splodgeRepository.operatingLiftOverExtraThickness.value, location, self.operatingStartupDistance ) - - def getSplodgeLine(self, line, location, splitLine): - """Get splodged gcode line.""" - self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) - if self.hasInitialSplodgeBeenAdded: - return self.getOperatingSplodgeLine(line, location) - return self.getInitialSplodgeLine(line, location) - - def getSplodgeLineGivenDistance( self, feedRateMinute, line, liftOverExtraThickness, location, startupDistance ): - """Add the splodge line.""" - locationComplex = location.dropAxis() - relativeStartComplex = None - nextLocationComplex = self.getNextActiveLocationComplex() - if nextLocationComplex is not None: - if nextLocationComplex != locationComplex: - relativeStartComplex = locationComplex - nextLocationComplex - if relativeStartComplex is None: - relativeStartComplex = complex( 19.9, 9.9 ) - if self.oldLocation is not None: - oldLocationComplex = self.oldLocation.dropAxis() - if oldLocationComplex != locationComplex: - relativeStartComplex = oldLocationComplex - locationComplex - relativeStartComplex *= startupDistance / abs( relativeStartComplex ) - startComplex = self.getStartInsideBoundingRectangle( locationComplex, relativeStartComplex ) - feedRateMultiplier = feedRateMinute / self.operatingFeedRatePerSecond / 60.0 - splodgeLayerThickness = self.layerThickness / math.sqrt( feedRateMultiplier ) - extraLayerThickness = splodgeLayerThickness - self.layerThickness - lift = extraLayerThickness * liftOverExtraThickness - startLine = self.distanceFeedRate.getLinearGcodeMovementWithFeedRate( self.feedRateMinute, startComplex, location.z + lift ) - self.addLineUnlessIdenticalReactivate( startLine ) - self.addLineUnlessIdenticalReactivate('M101') - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - lineLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - self.distanceFeedRate.addGcodeMovementZWithFeedRate( feedRateMinute, locationComplex, lineLocation.z + lift ) - return '' - - def getStartInsideBoundingRectangle( self, locationComplex, relativeStartComplex ): - """Get a start inside the bounding rectangle.""" - startComplex = locationComplex + relativeStartComplex - if self.boundingRectangle.isPointInside( startComplex ): - return startComplex - for rotation in self.rotations: - rotatedRelativeStartComplex = relativeStartComplex * rotation - startComplex = locationComplex + rotatedRelativeStartComplex - if self.boundingRectangle.isPointInside( startComplex ): - return startComplex - return startComplex - - def isJustBeforeExtrusion(self): - """Determine if activate command is before linear move command.""" - for lineIndex in xrange(self.lineIndex + 1, len(self.lines)): - line = self.lines[lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1' or firstWord == 'M103': - return False - if firstWord == 'M101': - return True - return False - - def parseInitialization( self, splodgeRepository ): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.addLineUnlessIdenticalReactivate('( splodge )') - return - elif firstWord == '(': - self.layerThickness = float(splitLine[1]) - elif firstWord == '(': - self.operatingFeedRatePerSecond = float(splitLine[1]) - elif firstWord == '(': - self.perimeterWidth = float(splitLine[1]) - self.minimumQuantityLength = 0.1 * self.perimeterWidth - self.addLineUnlessIdenticalReactivate(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the bevel gcode.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - line = self.getSplodgeLine(line, location, splitLine) - self.oldLocation = location - elif firstWord == 'M101': - self.isExtruderActive = True - elif firstWord == 'M103': - self.isExtruderActive = False - self.addLineUnlessIdenticalReactivate(line) - - def setRotations(self): - """Set the rotations.""" - self.rootHalf = math.sqrt( 0.5 ) - self.rotations = [] - self.rotations.append( complex( self.rootHalf, self.rootHalf ) ) - self.rotations.append( complex( self.rootHalf, - self.rootHalf ) ) - self.rotations.append( complex( 0.0, 1.0 ) ) - self.rotations.append( complex(0.0, -1.0) ) - self.rotations.append( complex( - self.rootHalf, self.rootHalf ) ) - self.rotations.append( complex( - self.rootHalf, - self.rootHalf ) ) - - -def main(): - """Display the splodge dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/tower.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/tower.py deleted file mode 100644 index e2eea69..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/tower.py +++ /dev/null @@ -1,380 +0,0 @@ -""" -This page is in the table of contents. -Tower commands the fabricator to extrude a disconnected region for a few layers, then go to another disconnected region and extrude there. Its purpose is to reduce the number of stringers between a shape and reduce extruder travel. - -The tower manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Tower - -==Operation== -The default 'Activate Tower' checkbox is off. The default is off because tower could result in the extruder colliding with an already extruded part of the shape and because extruding in one region for more than one layer could result in the shape melting. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Maximum Tower Height=== -Default is five. - -Defines the maximum number of layers that the extruder will extrude in one region before going to another. This is the most important value for tower. - -===Extruder Possible Collision Cone Angle=== -Default is sixty degrees. - -Tower works by looking for islands in each layer and if it finds another island in the layer above, it goes to the next layer above instead of going across to other regions on the original layer. It checks for collision with shapes already extruded within a cone from the nozzle tip. The 'Extruder Possible Collision Cone Angle' setting is the angle of that cone. Realistic values for the cone angle range between zero and ninety. The higher the angle, the less likely a collision with the rest of the shape is, generally the extruder will stay in the region for only a few layers before a collision is detected with the wide cone. - -===Tower Start Layer=== -Default is one. - -Defines the layer index which the script starts extruding towers, after the last raft layer which does not have support material. It is best to not tower at least the first layer because the temperature of the first layer is sometimes different than that of the other layers. - -==Examples== -The following examples tower the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and tower.py. - -> python tower.py -This brings up the tower dialog. - -> python tower.py Screw Holder Bottom.stl -The tower tool is parsing the file: -Screw Holder Bottom.stl -.. -The tower tool has created the file: -.. Screw Holder Bottom_tower.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - -def getCraftedText( fileName, text, towerRepository = None ): - """Tower a gcode linear move file or text.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, text), towerRepository ) - -def getCraftedTextFromText( gcodeText, towerRepository = None ): - """Tower a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'tower'): - return gcodeText - if towerRepository is None: - towerRepository = settings.getReadRepository( TowerRepository() ) - if not towerRepository.activateTower.value: - return gcodeText - return TowerSkein().getCraftedGcode( gcodeText, towerRepository ) - -def getNewRepository(): - """Get new repository.""" - return TowerRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Tower a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'tower', shouldAnalyze) - - -class Island: - """A class to hold the boundary and lines.""" - def __init__(self): - self.boundary = [] - self.boundingLoop = None - self.lines = [] - - def addToBoundary( self, splitLine ): - """Add to the boundary if it is not complete.""" - if self.boundingLoop is None: - location = gcodec.getLocationFromSplitLine(None, splitLine) - self.boundary.append(location.dropAxis()) - self.z = location.z - - def createBoundingLoop(self): - """Create the bounding loop if it is not already created.""" - if self.boundingLoop is None: - self.boundingLoop = intercircle.BoundingLoop().getFromLoop( self.boundary ) - - -class ThreadLayer: - """A layer of loops and paths.""" - def __init__(self): - """Thread layer constructor.""" - self.afterExtrusionLines = [] - self.beforeExtrusionLines = [] - self.islands = [] - - def __repr__(self): - """Get the string representation of this thread layer.""" - return '%s' % self.islands - - -class TowerRepository: - """A class to handle the tower settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.tower.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Tower', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Tower') - self.activateTower = settings.BooleanSetting().getFromValue('Activate Tower', self, False ) - self.extruderPossibleCollisionConeAngle = settings.FloatSpin().getFromValue( 40.0, 'Extruder Possible Collision Cone Angle (degrees):', self, 80.0, 60.0 ) - self.maximumTowerHeight = settings.IntSpin().getFromValue( 2, 'Maximum Tower Height (layers):', self, 10, 5 ) - self.towerStartLayer = settings.IntSpin().getFromValue( 1, 'Tower Start Layer (integer):', self, 5, 1 ) - self.executeTitle = 'Tower' - - def execute(self): - """Tower button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class TowerSkein: - """A class to tower a skein of extrusions.""" - def __init__(self): - self.afterExtrusionLines = [] - self.beforeExtrusionLines = [] - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.highestZ = - 987654321.0 - self.island = None - self.layerIndex = 0 - self.lineIndex = 0 - self.lines = None - self.minimumBelow = 0.1 - self.oldLayerIndex = None - self.oldLocation = None - self.oldOrderedLocation = Vector3() - self.perimeterWidth = 0.6 - self.shutdownLineIndex = sys.maxint - self.nestedRingCount = 0 - self.threadLayer = None - self.threadLayers = [] - self.travelFeedRateMinute = None - - def addEntireLayer( self, threadLayer ): - """Add entire thread layer.""" - self.distanceFeedRate.addLines( threadLayer.beforeExtrusionLines ) - for island in threadLayer.islands: - self.distanceFeedRate.addLines( island.lines ) - self.distanceFeedRate.addLines( threadLayer.afterExtrusionLines ) - - def addHighThread(self, location): - """Add thread with a high move if necessary to clear the previous extrusion.""" - if self.oldLocation is not None: - if self.oldLocation.z + self.minimumBelow < self.highestZ: - self.distanceFeedRate.addGcodeMovementZWithFeedRate( self.travelFeedRateMinute, self.oldLocation.dropAxis(), self.highestZ ) - if location.z + self.minimumBelow < self.highestZ: - self.distanceFeedRate.addGcodeMovementZWithFeedRate( self.travelFeedRateMinute, location.dropAxis(), self.highestZ ) - - def addThreadLayerIfNone(self): - """Add a thread layer if it is none.""" - if self.threadLayer is not None: - return - self.threadLayer = ThreadLayer() - self.threadLayers.append( self.threadLayer ) - self.threadLayer.beforeExtrusionLines = self.beforeExtrusionLines - self.beforeExtrusionLines = [] - - def addTowers(self): - """Add towers.""" - bottomLayerIndex = self.getBottomLayerIndex() - if bottomLayerIndex is None: - return - removedIsland = self.getRemovedIslandAddLayerLinesIfDifferent( self.threadLayers[ bottomLayerIndex ].islands, bottomLayerIndex ) - while 1: - self.climbTower( removedIsland ) - bottomLayerIndex = self.getBottomLayerIndex() - if bottomLayerIndex is None: - return - removedIsland = self.getRemovedIslandAddLayerLinesIfDifferent( self.threadLayers[ bottomLayerIndex ].islands, bottomLayerIndex ) - - def climbTower( self, removedIsland ): - """Climb up the island to any islands directly above.""" - outsetDistance = 1.5 * self.perimeterWidth - for step in xrange( self.towerRepository.maximumTowerHeight.value ): - aboveIndex = self.oldLayerIndex + 1 - if aboveIndex >= len( self.threadLayers ): - return - outsetRemovedLoop = removedIsland.boundingLoop.getOutsetBoundingLoop( outsetDistance ) - islandsWithin = [] - for island in self.threadLayers[ aboveIndex ].islands: - if self.isInsideRemovedOutsideCone( island, outsetRemovedLoop, aboveIndex ): - islandsWithin.append( island ) - if len( islandsWithin ) < 1: - return - removedIsland = self.getRemovedIslandAddLayerLinesIfDifferent( islandsWithin, aboveIndex ) - self.threadLayers[ aboveIndex ].islands.remove( removedIsland ) - - def getBottomLayerIndex(self): - """Get the index of the first island layer which has islands.""" - for islandLayerIndex in xrange( len( self.threadLayers ) ): - if len( self.threadLayers[ islandLayerIndex ].islands ) > 0: - return islandLayerIndex - return None - - def getCraftedGcode( self, gcodeText, towerRepository ): - """Parse gcode text and store the tower gcode.""" - self.lines = archive.getTextLines(gcodeText) - self.towerRepository = towerRepository - self.parseInitialization() - self.parseIfWordUntilWord('(') - self.parseIfWordUntilWord('()') - for lineIndex in xrange(self.lineIndex, len(self.lines)): - self.parseLine( lineIndex ) - concatenateEndIndex = min( len( self.threadLayers ), towerRepository.towerStartLayer.value ) - for threadLayer in self.threadLayers[ : concatenateEndIndex ]: - self.addEntireLayer( threadLayer ) - self.threadLayers = self.threadLayers[ concatenateEndIndex : ] - self.addTowers() - self.distanceFeedRate.addLines( self.lines[ self.shutdownLineIndex : ] ) - return self.distanceFeedRate.output.getvalue() - - def getRemovedIslandAddLayerLinesIfDifferent( self, islands, layerIndex ): - """Add gcode lines for the layer if it is different than the old bottom layer index.""" - threadLayer = None - if layerIndex != self.oldLayerIndex: - self.oldLayerIndex = layerIndex - threadLayer = self.threadLayers[layerIndex] - self.distanceFeedRate.addLines( threadLayer.beforeExtrusionLines ) - removedIsland = self.getTransferClosestSurroundingLoopLines( self.oldOrderedLocation, islands ) - if threadLayer is not None: - self.distanceFeedRate.addLines( threadLayer.afterExtrusionLines ) - return removedIsland - - def getTransferClosestSurroundingLoopLines( self, oldOrderedLocation, remainingNestedRings ): - """Get and transfer the closest remaining surrounding loop.""" - if len( remainingNestedRings ) > 0: - oldOrderedLocation.z = remainingNestedRings[0].z - closestDistance = 999999999987654321.0 - closestSurroundingLoop = None - for remainingSurroundingLoop in remainingNestedRings: - distance = euclidean.getNearestDistanceIndex( oldOrderedLocation.dropAxis(), remainingSurroundingLoop.boundary ).distance - if distance < closestDistance: - closestDistance = distance - closestSurroundingLoop = remainingSurroundingLoop - remainingNestedRings.remove( closestSurroundingLoop ) - hasTravelledHighRoad = False - for line in closestSurroundingLoop.lines: - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - if not hasTravelledHighRoad: - hasTravelledHighRoad = True - self.addHighThread( location ) - if location.z > self.highestZ: - self.highestZ = location.z - self.oldLocation = location - self.distanceFeedRate.addLine(line) - return closestSurroundingLoop - - def isInsideRemovedOutsideCone( self, island, removedBoundingLoop, untilLayerIndex ): - """Determine if the island is entirely inside the removed bounding loop and outside the collision cone of the remaining islands.""" - if not island.boundingLoop.isEntirelyInsideAnother( removedBoundingLoop ): - return False - bottomLayerIndex = self.getBottomLayerIndex() - coneAngleTangent = math.tan( math.radians( self.towerRepository.extruderPossibleCollisionConeAngle.value ) ) - for layerIndex in xrange( bottomLayerIndex, untilLayerIndex ): - islands = self.threadLayers[layerIndex].islands - outsetDistance = self.perimeterWidth * ( untilLayerIndex - layerIndex ) * coneAngleTangent + 0.5 * self.perimeterWidth - for belowIsland in self.threadLayers[layerIndex].islands: - outsetIslandLoop = belowIsland.boundingLoop.getOutsetBoundingLoop( outsetDistance ) - if island.boundingLoop.isOverlappingAnother( outsetIslandLoop ): - return False - return True - - def parseIfWordUntilWord(self, word): - """Parse gcode if there is a word until the word is reached.""" - for self.lineIndex in xrange(self.lineIndex, gcodec.getFirstWordIndexReverse(word, self.lines, self.lineIndex)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.addLine(line) - if firstWord == 'G1': - self.oldLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - if self.oldLocation.z > self.highestZ: - self.highestZ = self.oldLocation.z - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( tower )') - elif firstWord == '(': - return - elif firstWord == '(': - self.minimumBelow = 0.1 * float(splitLine[1]) - elif firstWord == '(': - self.perimeterWidth = float(splitLine[1]) - elif firstWord == '(': - self.travelFeedRateMinute = 60.0 * float(splitLine[1]) - self.distanceFeedRate.addLine(line) - - def parseLine( self, lineIndex ): - """Parse a gcode line.""" - line = self.lines[lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - self.afterExtrusionLines.append(line) - if firstWord == 'M103': - self.afterExtrusionLines = [] - elif firstWord == '()': - self.island.createBoundingLoop() - elif firstWord == '(': - self.island.addToBoundary(splitLine) - elif firstWord == '()': - self.shutdownLineIndex = lineIndex - elif firstWord == '(': - self.beforeExtrusionLines = [ line ] - self.island = None - self.nestedRingCount = 0 - self.threadLayer = None - return - elif firstWord == '()': - if self.threadLayer is not None: - self.threadLayer.afterExtrusionLines = self.afterExtrusionLines - self.afterExtrusionLines = [] - elif firstWord == '()': - self.afterExtrusionLines = [] - elif firstWord == '()': - self.nestedRingCount += 1 - if self.island is None: - self.island = Island() - self.addThreadLayerIfNone() - self.threadLayer.islands.append( self.island ) - elif firstWord == '()': - self.afterExtrusionLines = [] - if self.island is not None: - self.island.lines.append(line) - if firstWord == '()': - self.afterExtrusionLines = [] - self.nestedRingCount -= 1 - if self.nestedRingCount == 0: - self.island = None - if len( self.beforeExtrusionLines ) > 0: - self.beforeExtrusionLines.append(line) - - -def main(): - """Display the tower dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/unpause.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/unpause.py deleted file mode 100644 index 38f8491..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/unpause.py +++ /dev/null @@ -1,193 +0,0 @@ -""" -This page is in the table of contents. -The unpause script is based on the Shane Hathaway's patch to speed up a line segment to compensate for the delay of the microprocessor. The description is at: -http://shane.willowrise.com/archives/delay-compensation-in-firmware/ - -The unpause manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Unpause - -==Operation== -The default 'Activate Unpause' checkbox is off. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Delay=== -Default is 28 milliseconds, which Shane found for the Arduino. - -Defines the delay on the microprocessor that will be at least partially compensated for. - -===Maximum Speed=== -Default is 1.3. - -Defines the maximum amount that the feed rate will be sped up to, compared to the original feed rate. - -==Examples== -The following examples unpause the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and unpause.py. - -> python unpause.py -This brings up the unpause dialog. - -> python unpause.py Screw Holder Bottom.stl -The unpause tool is parsing the file: -Screw Holder Bottom.stl -.. -The unpause tool has created the file: -.. Screw Holder Bottom_unpause.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, gcodeText, repository=None): - """Unpause a gcode linear move file or text.""" - return getCraftedTextFromText( archive.getTextIfEmpty( fileName, gcodeText ), repository ) - -def getCraftedTextFromText(gcodeText, repository=None): - """Unpause a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'unpause'): - return gcodeText - if repository is None: - repository = settings.getReadRepository( UnpauseRepository() ) - if not repository.activateUnpause.value: - return gcodeText - return UnpauseSkein().getCraftedGcode(gcodeText, repository) - -def getNewRepository(): - """Get new repository.""" - return UnpauseRepository() - -def getSelectedPlugin(repository): - """Get the selected plugin.""" - for plugin in repository.unpausePlugins: - if plugin.value: - return plugin - return None - -def writeOutput(fileName, shouldAnalyze=True): - """Unpause a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'unpause', shouldAnalyze) - - -class UnpauseRepository: - """A class to handle the unpause settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.unpause.html', self) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Unpause', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Unpause') - self.activateUnpause = settings.BooleanSetting().getFromValue('Activate Unpause', self, False ) - self.delay = settings.FloatSpin().getFromValue( 2.0, 'Delay (milliseconds):', self, 42.0, 28.0 ) - self.maximumSpeed = settings.FloatSpin().getFromValue( 1.1, 'Maximum Speed (ratio):', self, 1.9, 1.3 ) - self.executeTitle = 'Unpause' - - def execute(self): - """Unpause button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class UnpauseSkein: - """A class to unpause a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.feedRateMinute = 959.0 - self.lineIndex = 0 - self.lines = None - self.oldLocation = None - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the unpause gcode.""" - self.delaySecond = repository.delay.value * 0.001 - self.maximumSpeed = repository.maximumSpeed.value - self.minimumSpeedUpReciprocal = 1.0 / self.maximumSpeed - self.repository = repository - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - for self.lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[self.lineIndex] - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getUnpausedArcMovement( self, line, splitLine ): - """Get an unpaused arc movement.""" - self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) - if self.oldLocation is None: - return line - relativeLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - self.oldLocation += relativeLocation - distance = gcodec.getArcDistance(relativeLocation, splitLine) - return self.getUnpausedMovement(distance, line, splitLine) - - def getUnpausedLinearMovement( self, line, splitLine ): - """Get an unpaused linear movement.""" - self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - if self.oldLocation is None: - self.oldLocation = location - return line - distance = abs(self.oldLocation - location) - self.oldLocation = location - return self.getUnpausedMovement(distance, line, splitLine) - - def getUnpausedMovement(self, distance, line, splitLine): - """Get an unpaused movement.""" - if distance <= 0.0: - return line - resultantReciprocal = 1.0 - self.delaySecond / distance * self.feedRateMinute / 60.0 - resultantReciprocal = max(self.minimumSpeedUpReciprocal, resultantReciprocal) - return self.distanceFeedRate.getLineWithFeedRate(self.feedRateMinute / resultantReciprocal, line, splitLine) - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( unpause )') - return - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - line = self.getUnpausedLinearMovement( line, splitLine ) - if firstWord == 'G2' or firstWord == 'G3': - line = self.getUnpausedArcMovement( line, splitLine ) - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the unpause dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/whittle.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/whittle.py deleted file mode 100644 index 31591a2..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/whittle.py +++ /dev/null @@ -1,172 +0,0 @@ -""" -This page is in the table of contents. -Whittle will convert each polygon of a gcode file into a helix which has a vertical step down on each rotation. - -==Operation== -The default 'Activate Whittle' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. If the cutting tool can cut the slab in one cut, the 'Activate Whittle' checkbox should be off, the default is off. - -==Settings== -===Maximum Vertical Step'=== -Default is 0.1 mm. - -Defines the maximum distance that the helix will step down on each rotation. The number of steps in the helix will be the layer thickness divided by the 'Maximum Vertical Step', rounded up. The amount the helix will step down is the layer thickness divided by the number of steps. The thinner the 'Maximum Vertical Step', the more times the cutting tool will circle around on its way to the bottom of the slab. - -==Examples== -The following examples whittle the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and whittle.py. - -> python whittle.py -This brings up the whittle dialog. - -> python whittle.py Screw Holder Bottom.stl -The whittle tool is parsing the file: -Screw Holder Bottom.stl -.. -The whittle tool has created the file: -.. Screw Holder Bottom_whittle.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, text='', whittleRepository = None ): - """Whittle the preface file or text.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, text), whittleRepository ) - -def getCraftedTextFromText( gcodeText, whittleRepository = None ): - """Whittle the preface gcode text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'whittle'): - return gcodeText - if whittleRepository is None: - whittleRepository = settings.getReadRepository( WhittleRepository() ) - if not whittleRepository.activateWhittle.value: - return gcodeText - return WhittleSkein().getCraftedGcode( whittleRepository, gcodeText ) - -def getNewRepository(): - """Get new repository.""" - return WhittleRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Whittle the carving of a gcode file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'whittle', shouldAnalyze) - - -class WhittleRepository: - """A class to handle the whittle settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.whittle.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File to be Whittled', self, '') - self.activateWhittle = settings.BooleanSetting().getFromValue('Activate Whittle:', self, False ) - self.maximumVerticalStep = settings.FloatSpin().getFromValue( 0.02, 'Maximum Vertical Step (mm):', self, 0.42, 0.1 ) - self.executeTitle = 'Whittle' - - def execute(self): - """Whittle button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class WhittleSkein: - """A class to whittle a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.layerThickness = 0.3333333333 - self.lineIndex = 0 - self.movementLines = [] - self.oldLocation = None - - def getCraftedGcode( self, whittleRepository, gcodeText ): - """Parse gcode text and store the whittle gcode.""" - self.whittleRepository = whittleRepository - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - for line in self.lines[self.lineIndex :]: - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getLinearMove( self, line, splitLine ): - """Get the linear move.""" - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - self.movementLines.append(line) - z = location.z + self.layerDeltas[0] - self.oldLocation = location - return self.distanceFeedRate.getLineWithZ( line, splitLine, z ) - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex].lstrip() - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addTagBracketedLine('procedureName', 'whittle') - return - elif firstWord == '(': - self.setLayerThinknessVerticalDeltas(splitLine) - self.distanceFeedRate.addTagBracketedLine('layerStep', self.layerStep ) - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the whittle skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - line = self.getLinearMove( line, splitLine ) - elif firstWord == 'M103': - self.repeatLines() - self.distanceFeedRate.addLine(line) - - def repeatLines(self): - """Repeat the lines at decreasing altitude.""" - for layerDelta in self.layerDeltas[1 :]: - for movementLine in self.movementLines: - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(movementLine) - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - z = location.z + layerDelta - self.distanceFeedRate.addLine( self.distanceFeedRate.getLineWithZ( movementLine, splitLine, z ) ) - self.movementLines = [] - - def setLayerThinknessVerticalDeltas( self, splitLine ): - """Set the layer thickness and the vertical deltas.""" - self.layerThickness = float(splitLine[1]) - numberOfSteps = int( math.ceil( self.layerThickness / self.whittleRepository.maximumVerticalStep.value ) ) - self.layerStep = self.layerThickness / float( numberOfSteps ) - self.layerDeltas = [] - halfDeltaMinusHalfTop = 0.5 * self.layerStep * ( 1.0 - numberOfSteps ) - for layerDeltaIndex in xrange( numberOfSteps - 1, - 1, - 1 ): - layerDelta = layerDeltaIndex * self.layerStep + halfDeltaMinusHalfTop - self.layerDeltas.append( layerDelta ) - - -def main(): - """Display the whittle dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/widen.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/widen.py deleted file mode 100644 index b51b5fd..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/Obsolete/widen.py +++ /dev/null @@ -1,225 +0,0 @@ -#! /usr/bin/env python -""" -This page is in the table of contents. -Widen will widen the outside perimeters away from the inside perimeters, so that the outsides will be at least two perimeter widths away from the insides and therefore the outside filaments will not overlap the inside filaments. - -For example, if a mug has a very thin wall, widen would widen the outside of the mug so that the wall of the mug would be two perimeter widths wide, and the outside wall filament would not overlap the inside filament. - -For another example, if the outside of the object runs right next to a hole, widen would widen the wall around the hole so that the wall would bulge out around the hole, and the outside filament would not overlap the hole filament. - -The widen manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Widen - -==Operation== -The default 'Activate Widen' checkbox is off. When it is on, widen will work, when it is off, widen will not be called. - -==Examples== -The following examples widen the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and widen.py. - -> python widen.py -This brings up the widen dialog. - -> python widen.py Screw Holder Bottom.stl -The widen tool is parsing the file: -Screw Holder Bottom.stl -.. -The widen tool has created the file: -.. Screw Holder Bottom_widen.gcode - -""" - -from __future__ import absolute_import -try: - import psyco - psyco.full() -except: - pass -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.geometry.geometry_utilities import boolean_solid -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import os -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/28/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText(fileName, text='', repository=None): - """Widen the preface file or text.""" - return getCraftedTextFromText(archive.getTextIfEmpty(fileName, text), repository) - -def getCraftedTextFromText(gcodeText, repository=None): - """Widen the preface gcode text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'widen'): - return gcodeText - if repository is None: - repository = settings.getReadRepository( WidenRepository() ) - if not repository.activateWiden.value: - return gcodeText - return WidenSkein().getCraftedGcode(gcodeText, repository) - -def getIntersectingWithinLoops(loop, loopList, outsetLoop): - """Get the loops which are intersecting or which it is within.""" - intersectingWithinLoops = [] - for otherLoop in loopList: - if getIsIntersectingWithinLoop(loop, otherLoop, outsetLoop): - intersectingWithinLoops.append(otherLoop) - return intersectingWithinLoops - -def getIsIntersectingWithinLoop(loop, otherLoop, outsetLoop): - """Determine if the loop is intersecting or is within the other loop.""" - if euclidean.isLoopIntersectingLoop(loop, otherLoop): - return True - return euclidean.isPathInsideLoop(otherLoop, loop) != euclidean.isPathInsideLoop(otherLoop, outsetLoop) - -def getIsPointInsideALoop(loops, point): - """Determine if a point is inside a loop of a loop list.""" - for loop in loops: - if euclidean.isPointInsideLoop(loop, point): - return True - return False - -def getNewRepository(): - """Get new repository.""" - return WidenRepository() - -def getWidenedLoop(loop, loopList, outsetLoop, radius): - """Get the widened loop.""" - intersectingWithinLoops = getIntersectingWithinLoops(loop, loopList, outsetLoop) - if len(intersectingWithinLoops) < 1: - return loop - loopsUnified = boolean_solid.getLoopsUnified(radius, [[loop], intersectingWithinLoops]) - if len(loopsUnified) < 1: - return loop - return euclidean.getLargestLoop(loopsUnified) - -def writeOutput(fileName, shouldAnalyze=True): - """Widen the carving of a gcode file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'widen', shouldAnalyze) - - -class WidenRepository: - """A class to handle the widen settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.widen.html', self) - self.fileNameInput = settings.FileNameInput().getFromFileName( - fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Widen', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute( - 'http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Widen') - self.activateWiden = settings.BooleanSetting().getFromValue('Activate Widen:', self, False) - self.executeTitle = 'Widen' - - def execute(self): - """Widen button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode( - self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class WidenSkein: - """A class to widen a skein of extrusions.""" - def __init__(self): - self.boundary = None - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.layerCount = settings.LayerCount() - self.lineIndex = 0 - self.rotatedLoopLayer = None - - def addWiden(self, rotatedLoopLayer): - """Add widen to the layer.""" - triangle_mesh.sortLoopsInOrderOfArea(False, rotatedLoopLayer.loops) - widdershinsLoops = [] - clockwiseInsetLoops = [] - for loopIndex in xrange(len(rotatedLoopLayer.loops)): - loop = rotatedLoopLayer.loops[loopIndex] - if euclidean.isWiddershins(loop): - otherLoops = rotatedLoopLayer.loops[: loopIndex] + rotatedLoopLayer.loops[loopIndex + 1 :] - leftPoint = euclidean.getLeftPoint(loop) - if getIsPointInsideALoop(otherLoops, leftPoint): - self.distanceFeedRate.addGcodeFromLoop(loop, rotatedLoopLayer.z) - else: - widdershinsLoops.append(loop) - else: -# clockwiseInsetLoop = intercircle.getLargestInsetLoopFromLoop(loop, self.doublePerimeterWidth) -# clockwiseInsetLoop.reverse() -# clockwiseInsetLoops.append(clockwiseInsetLoop) - clockwiseInsetLoops += intercircle.getInsetLoopsFromLoop(loop, self.doublePerimeterWidth) - self.distanceFeedRate.addGcodeFromLoop(loop, rotatedLoopLayer.z) - for widdershinsLoop in widdershinsLoops: - outsetLoop = intercircle.getLargestInsetLoopFromLoop(widdershinsLoop, -self.doublePerimeterWidth) - widenedLoop = getWidenedLoop(widdershinsLoop, clockwiseInsetLoops, outsetLoop, self.perimeterWidth) - self.distanceFeedRate.addGcodeFromLoop(widenedLoop, rotatedLoopLayer.z) - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the widen gcode.""" - self.repository = repository - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - for line in self.lines[self.lineIndex :]: - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addTagBracketedLine('procedureName', 'widen') - elif firstWord == '()': - self.distanceFeedRate.addLine(line) - return - elif firstWord == '(': - self.perimeterWidth = float(splitLine[1]) - self.doublePerimeterWidth = 2.0 * self.perimeterWidth - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the widen skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == '(': - location = gcodec.getLocationFromSplitLine(None, splitLine) - self.boundary.append(location.dropAxis()) - elif firstWord == '(': - self.layerCount.printProgressIncrement('widen') - self.rotatedLoopLayer = euclidean.RotatedLoopLayer(float(splitLine[1])) - self.distanceFeedRate.addLine(line) - elif firstWord == '()': - self.addWiden( self.rotatedLoopLayer ) - self.rotatedLoopLayer = None - elif firstWord == '()': - self.boundary = [] - self.rotatedLoopLayer.loops.append( self.boundary ) - if self.rotatedLoopLayer is None or firstWord == '(': - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the widen dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor(getNewRepository()) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/__init__.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/__init__.py deleted file mode 100644 index 1121e8a..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/bottom.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/bottom.py deleted file mode 100644 index 080950f..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/bottom.py +++ /dev/null @@ -1,153 +0,0 @@ -#! /usr/bin/env python -""" -This page is in the table of contents. -Bottom sets the bottom of the carving to the defined altitude. - -==Operation== -The default 'Activate Bottom' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Additional Height over Layer Thickness=== -Default is half. - -The layers will start at the altitude plus the 'Additional Height over Layer Thickness' times the layer thickness. The default value of half means that the bottom layer is at the height of the bottom slice, because each slice is made through the middle of each layer. Raft expects the layers to start at an additional half layer thickness. You should only change 'Additional Height over Layer Thickness' if you are manipulating the skeinforge output with your own program which does not use the raft tool. - -===Altitude=== -Default is zero. - -Defines the altitude of the bottom of the model. The bottom slice has a z of the altitude plus the 'Additional Height over Layer Thickness' times the layer thickness. - -===SVG Viewer=== -Default is webbrowser. - -If the 'SVG Viewer' is set to the default 'webbrowser', the scalable vector graphics file will be sent to the default browser to be opened. If the 'SVG Viewer' is set to a program name, the scalable vector graphics file will be sent to that program to be opened. - -==Examples== -The following examples bottom the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and bottom.py. - -> python bottom.py -This brings up the bottom dialog. - -> python bottom.py Screw Holder Bottom.stl -The bottom tool is parsing the file: -Screw Holder Bottom.stl -.. -The bottom tool has created the file: -.. Screw Holder Bottom_bottom.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.svg_reader import SVGReader -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities.xml_simple_reader import XMLSimpleReader -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from fabmetheus_utilities import svg_writer -from fabmetheus_utilities import xml_simple_writer -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText(fileName, svgText='', repository=None): - """Bottom and convert an svg file or svgText.""" - return getCraftedTextFromText(fileName, archive.getTextIfEmpty(fileName, svgText), repository) - -def getCraftedTextFromText(fileName, svgText, repository=None): - """Bottom and convert an svgText.""" - if gcodec.isProcedureDoneOrFileIsEmpty(svgText, 'bottom'): - return svgText - if repository is None: - repository = settings.getReadRepository(BottomRepository()) - if not repository.activateBottom.value: - return svgText - return BottomSkein().getCraftedGcode(fileName, repository, svgText) - -def getNewRepository(): - """Get new repository.""" - return BottomRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Bottom the carving.""" - skeinforge_craft.writeSVGTextWithNounMessage(fileName, BottomRepository(), shouldAnalyze) - - -class BottomRepository: - """A class to handle the bottom settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository( - 'skeinforge_application.skeinforge_plugins.craft_plugins.bottom.html', self) - self.fileNameInput = settings.FileNameInput().getFromFileName( - fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Bottom', self, '') - self.activateBottom = settings.BooleanSetting().getFromValue('Activate Bottom... and dont change anything else here!!!', self, True) - self.additionalHeightOverLayerThickness = settings.FloatSpin().getFromValue( - 0.0, 'Additional Height (ratio):', self, 1.0, 0.5) - self.altitude = settings.FloatSpin().getFromValue(-1.0, 'Altitude (mm):', self, 1.0, 0.0) - self.svgViewer = settings.StringSetting().getFromValue('SVG Viewer:', self, 'webbrowser') - self.executeTitle = 'Bottom' - - def execute(self): - """Bottom button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class BottomSkein: - """A class to bottom a skein of extrusions.""" - def getCraftedGcode(self, fileName, repository, svgText): - """Parse svgText and store the bottom svgText.""" - svgReader = SVGReader() - svgReader.parseSVG('', svgText) - if svgReader.sliceDictionary is None: - print('Warning, nothing will be done because the sliceDictionary could not be found getCraftedGcode in preface.') - return '' - decimalPlacesCarried = int(svgReader.sliceDictionary['decimalPlacesCarried']) - layerThickness = float(svgReader.sliceDictionary['layerThickness']) - perimeterWidth = float(svgReader.sliceDictionary['perimeterWidth']) - rotatedLoopLayers = svgReader.rotatedLoopLayers - zMinimum = 987654321.0 - for rotatedLoopLayer in rotatedLoopLayers: - zMinimum = min(rotatedLoopLayer.z, zMinimum) - deltaZ = repository.altitude.value + repository.additionalHeightOverLayerThickness.value * layerThickness - zMinimum - for rotatedLoopLayer in rotatedLoopLayers: - rotatedLoopLayer.z += deltaZ - cornerMaximum = Vector3(-912345678.0, -912345678.0, -912345678.0) - cornerMinimum = Vector3(912345678.0, 912345678.0, 912345678.0) - svg_writer.setSVGCarvingCorners(cornerMaximum, cornerMinimum, layerThickness, rotatedLoopLayers) - svgWriter = svg_writer.SVGWriter( - True, - cornerMaximum, - cornerMinimum, - decimalPlacesCarried, - layerThickness, - perimeterWidth) - commentElement = svg_writer.getCommentElement(svgReader.root) - procedureNameString = svgReader.sliceDictionary['procedureName'] + ',bottom' - return svgWriter.getReplacedSVGTemplate(fileName, procedureNameString, rotatedLoopLayers, commentElement) - - -def main(): - """Display the bottom dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/carve.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/carve.py deleted file mode 100644 index c3ed071..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/carve.py +++ /dev/null @@ -1,225 +0,0 @@ -""" -This page is in the table of contents. -Carve is a script to carve a shape into svg slice layers. - -The carve manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Carve - -On the Arcol Blog a method of deriving the layer thickness is posted. That article "Machine Calibrating" is at: -http://blog.arcol.hu/?p=157 - -==Settings== -===Add Layer Template to SVG=== -Default is on. - -When selected, the layer template will be added to the svg output, which adds javascript control boxes. So 'Add Layer Template to SVG' should be selected when the svg will be viewed in a browser. - -When off, no controls will be added, the svg output will only include the fabrication paths. So 'Add Layer Template to SVG' should be deselected when the svg will be used by other software, like Inkscape. - -===Extra Decimal Places=== -Default is two. - -Defines the number of extra decimal places export will output compared to the number of decimal places in the layer thickness. The higher the 'Extra Decimal Places', the more significant figures the output numbers will have. - -===Import Coarseness=== -Default is one. - -When a triangle mesh has holes in it, the triangle mesh slicer switches over to a slow algorithm that spans gaps in the mesh. The higher the 'Import Coarseness' setting, the wider the gaps in the mesh it will span. An import coarseness of one means it will span gaps of the perimeter width. - -===Infill in Direction of Bridge=== -Default is on. - -When selected, the infill will be in the direction of any bridge across a gap, so that the fill will be able to span a bridge easier. - -===Layer Thickness=== -Default is 0.4 mm. - -Defines the thickness of the extrusion layer at default extruder speed, this is the most important carve setting. - -===Layers=== -Carve slices from bottom to top. To get a single layer, set the "Layers From" to zero and the "Layers To" to one. The 'Layers From' until 'Layers To' range is a python slice. - -====Layers From==== -Default is zero. - -Defines the index of the bottom layer that will be carved. If the 'Layers From' is the default zero, the carving will start from the lowest layer. If the 'Layers From' index is negative, then the carving will start from the 'Layers From' index below the top layer. - -====Layers To==== -Default is a huge number, which will be limited to the highest index layer. - -Defines the index of the top layer that will be carved. If the 'Layers To' index is a huge number like the default, the carving will go to the top of the model. If the 'Layers To' index is negative, then the carving will go to the 'Layers To' index below the top layer. - -===Mesh Type=== -Default is 'Correct Mesh'. - -====Correct Mesh==== -When selected, the mesh will be accurately carved, and if a hole is found, carve will switch over to the algorithm that spans gaps. - -====Unproven Mesh==== -When selected, carve will use the gap spanning algorithm from the start. The problem with the gap spanning algothm is that it will span gaps, even if there is not actually a gap in the model. - -===Perimeter Width over Thickness=== -Default is 1.8. - -Defines the ratio of the extrusion perimeter width to the layer thickness. The higher the value the more the perimeter will be inset, the default is 1.8. A ratio of one means the extrusion is a circle, a typical ratio of 1.8 means the extrusion is a wide oval. These values should be measured from a test extrusion line. - -===SVG Viewer=== -Default is webbrowser. - -If the 'SVG Viewer' is set to the default 'webbrowser', the scalable vector graphics file will be sent to the default browser to be opened. If the 'SVG Viewer' is set to a program name, the scalable vector graphics file will be sent to that program to be opened. - -==Examples== -The following examples carve the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and carve.py. - -> python carve.py -This brings up the carve dialog. - -> python carve.py Screw Holder Bottom.stl -The carve tool is parsing the file: -Screw Holder Bottom.stl -.. -The carve tool has created the file: -.. Screw Holder Bottom_carve.svg - -""" - -from __future__ import absolute_import -try: - import psyco - psyco.full() -except: - pass -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from fabmetheus_utilities import svg_writer -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys -import time - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, gcodeText = '', repository=None): - """Get carved text.""" - if fileName.endswith('.svg'): - gcodeText = archive.getTextIfEmpty(fileName, gcodeText) - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'carve'): - return gcodeText - carving = svg_writer.getCarving(fileName) - if carving is None: - return '' - if repository is None: - repository = CarveRepository() - settings.getReadRepository(repository) - return CarveSkein().getCarvedSVG( carving, fileName, repository ) - -def getNewRepository(): - """Get new repository.""" - return CarveRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Carve a GNU Triangulated Surface file.""" - startTime = time.time() - print("File %s is being carved." % (archive.getSummarizedFileName(fileName))) - repository = CarveRepository() - settings.getReadRepository(repository) - carveGcode = getCraftedText(fileName, '', repository) - if carveGcode == '': - return - suffixFileName = archive.getFilePathWithUnderscoredBasename(fileName, '_carve.svg') - archive.writeFileText(suffixFileName, carveGcode) - print('The carved file is saved as ' + archive.getSummarizedFileName(suffixFileName)) - print('It took %s to carve the file.' % euclidean.getDurationString(time.time() - startTime)) - if shouldAnalyze: - settings.openSVGPage(suffixFileName, repository.svgViewer.value) - - -class CarveRepository: - """A class to handle the carve settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.carve.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getTranslatorFileTypeTuples(), 'Open File for Carve', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Carve') - settings.LabelDisplay().getFromName('- MAIN SETTINGS for Extrusion -', self ) - settings.LabelSeparator().getFromRepository(self) - self.layerThickness = settings.FloatSpin().getFromValue( 0.1, 'Layer Height = Extrusion Thickness (mm):', self, 1.0, 0.4 ) - self.perimeterWidth = settings.FloatSpin().getFromValue( 0.2, 'Extrusion Width (mm):', self, 1.0, 0.6 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Layers to print -', self ) - self.layersFrom = settings.IntSpin().getFromValue( 0, 'Print from Layer No::', self, 3333, 0 ) - self.layersTo = settings.IntSpin().getSingleIncrementFromValue( 0, 'Print up to Layer No:', self, 912345678, 912345678 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Checked for technical parts, unchecked for organic pieces -', self ) - self.infillInDirectionOfBridge = settings.BooleanSetting().getFromValue('Infill in Direction of Bridge', self, True ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Do not touch those below -', self ) - settings.LabelSeparator().getFromRepository(self) - self.meshTypeLabel = settings.LabelDisplay().getFromName('Mesh Type: ', self ) - importLatentStringVar = settings.LatentStringVar() - self.correctMesh = settings.Radio().getFromRadio( importLatentStringVar, 'Correct Mesh', self, True ) - self.unprovenMesh = settings.Radio().getFromRadio( importLatentStringVar, 'Unproven Mesh', self, False ) - self.svgViewer = settings.StringSetting().getFromValue('SVG Viewer:', self, 'webbrowser') - self.addLayerTemplateToSVG = settings.BooleanSetting().getFromValue('Add Layer Template to SVG', self, True) - self.extraDecimalPlaces = settings.FloatSpin().getFromValue(0.0, 'Extra Decimal Places (float):', self, 3.0, 2.0) - self.importCoarseness = settings.FloatSpin().getFromValue( 0.5, 'Import Coarseness (ratio):', self, 2.0, 1.0 ) - - settings.LabelSeparator().getFromRepository(self) - self.executeTitle = 'Carve' - - def execute(self): - """Carve button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypes(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class CarveSkein: - """A class to carve a carving.""" - def getCarvedSVG(self, carving, fileName, repository): - """Parse gnu triangulated surface text and store the carved gcode.""" - layerThickness = repository.layerThickness.value - perimeterWidth = repository.perimeterWidth.value - carving.setCarveInfillInDirectionOfBridge(repository.infillInDirectionOfBridge.value) - carving.setCarveLayerThickness(layerThickness) - importRadius = 0.5 * repository.importCoarseness.value * abs(perimeterWidth) - carving.setCarveImportRadius(max(importRadius, 0.01 * layerThickness)) - carving.setCarveIsCorrectMesh(repository.correctMesh.value) - rotatedLoopLayers = carving.getCarveRotatedBoundaryLayers() - if len(rotatedLoopLayers) < 1: - print('Warning, there are no slices for the model, this could be because the model is too small for the Layer Thickness.') - return '' - layerThickness = carving.getCarveLayerThickness() - decimalPlacesCarried = euclidean.getDecimalPlacesCarried(repository.extraDecimalPlaces.value, layerThickness) - perimeterWidth = repository.perimeterWidth.value - svgWriter = svg_writer.SVGWriter( - repository.addLayerTemplateToSVG.value, - carving.getCarveCornerMaximum(), - carving.getCarveCornerMinimum(), - decimalPlacesCarried, - carving.getCarveLayerThickness(), - perimeterWidth) - truncatedRotatedBoundaryLayers = svg_writer.getTruncatedRotatedBoundaryLayers(repository, rotatedLoopLayers) - return svgWriter.getReplacedSVGTemplate( - fileName, 'carve', truncatedRotatedBoundaryLayers, carving.getFabmetheusXML()) - - -def main(): - """Display the carve dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/chamber.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/chamber.py deleted file mode 100644 index 16a29be..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/chamber.py +++ /dev/null @@ -1,241 +0,0 @@ -""" -This page is in the table of contents. -Some filaments contract too much and to prevent this you have to print the object in a temperature regulated chamber or on a temperature regulated bed. The chamber tool allows you to control the bed and chamber temperature and the holding pressure. The gcodes are also described at: -http://reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes - -The chamber manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Chamber - -==Operation== -The default 'Activate Chamber' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Bed Temperature=== -Default is 60C. - -Defines the print_bed temperature in Celcius by adding an M140 command. - -===Chamber Temperature=== -Default is 30C. - -Defines the chamber temperature in Celcius by adding an M141 command. - -===Holding Force=== -Default is zero. - -Defines the holding pressure of a mechanism, like a vacuum table or electromagnet, to hold the bed surface or object, by adding an M142 command. The holding pressure is in bar. For hardware which only has on/off holding, when the holding pressure is zero, turn off holding, when the holding pressure is greater than zero, turn on holding. - -==Heated Beds== -===Bothacker=== -A resistor heated aluminum plate by Bothacker: -http://bothacker.com - -with an article at: -http://bothacker.com/2009/12/18/heated-build-platform/ - -===Domingo=== -A heated copper build plate by Domingo: -http://casainho-emcrepstrap.blogspot.com/ - -with articles at: -http://casainho-emcrepstrap.blogspot.com/2010/01/first-time-with-pla-testing-it-also-on.html -http://casainho-emcrepstrap.blogspot.com/2010/01/call-for-helpideas-to-develop-heated.html -http://casainho-emcrepstrap.blogspot.com/2010/01/new-heated-build-platform.html -http://casainho-emcrepstrap.blogspot.com/2010/01/no-acrylic-and-instead-kapton-tape-on.html -http://casainho-emcrepstrap.blogspot.com/2010/01/problems-with-heated-build-platform-and.html -http://casainho-emcrepstrap.blogspot.com/2010/01/perfect-build-platform.html -http://casainho-emcrepstrap.blogspot.com/2009/12/almost-no-warp.html -http://casainho-emcrepstrap.blogspot.com/2009/12/heated-base-plate.html - -===Jmil=== -A heated build stage by jmil, over at: -http://www.hive76.org - -with articles at: -http://www.hive76.org/handling-hot-build-surfaces -http://www.hive76.org/heated-build-stage-success - -===Kulitorum=== -Kulitorum has made a heated bed. It is a 5mm Alu sheet with a pattern laid out in kapton tape. The wire is a 0.6mm2 Konstantin wire and it's held in place by small pieces of kapton tape. The description and picture is at: -http://gallery.kulitorum.com/main.php?g2_itemId=283 - -===Metalab=== -A heated base by the Metalab folks: -http://reprap.soup.io - -with information at: -http://reprap.soup.io/?search=heated%20base - -===Nophead=== -A resistor heated aluminum bed by Nophead: -http://hydraraptor.blogspot.com - -with articles at: -http://hydraraptor.blogspot.com/2010/01/will-it-stick.html -http://hydraraptor.blogspot.com/2010/01/hot-metal-and-serendipity.html -http://hydraraptor.blogspot.com/2010/01/new-year-new-plastic.html -http://hydraraptor.blogspot.com/2010/01/hot-bed.html - -===Prusajr=== -A resistive wire heated plexiglass plate by prusajr: -http://prusadjs.cz/ - -with articles at: -http://prusadjs.cz/2010/01/heated-reprap-print-bed-mk2/ -http://prusadjs.cz/2009/11/look-ma-no-warping-heated-reprap-print-bed/ - -===Pumpernickel2=== -A resistor heated aluminum plate by Pumpernickel2: -http://dev.forums.reprap.org/profile.php?14,844 - -with a picture at: -http://dev.forums.reprap.org/file.php?14,file=1228,filename=heatedplate.jpg - -===Zaggo=== -A resistor heated aluminum plate by Zaggo at Pleasant Software: -http://pleasantsoftware.com/developer/3d/ - -with articles at: -ttp://pleasantsoftware.com/developer/3d/2009/12/05/raftless/ -http://pleasantsoftware.com/developer/3d/2009/11/15/living-in-times-of-warp-free-printing/ -http://pleasantsoftware.com/developer/3d/2009/11/12/canned-heat/ - -==Examples== -The following examples chamber the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and chamber.py. - -> python chamber.py -This brings up the chamber dialog. - -> python chamber.py Screw Holder Bottom.stl -The chamber tool is parsing the file: -Screw Holder Bottom.stl -.. -The chamber tool has created the file: -Screw Holder Bottom_chamber.gcode - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText(fileName, text='', repository=None): - """Chamber the file or text.""" - return getCraftedTextFromText(archive.getTextIfEmpty(fileName, text), repository) - -def getCraftedTextFromText(gcodeText, repository=None): - """Chamber a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'chamber'): - return gcodeText - if repository is None: - repository = settings.getReadRepository(ChamberRepository()) - if not repository.activateChamber.value: - return gcodeText - return ChamberSkein().getCraftedGcode(gcodeText, repository) - -def getNewRepository(): - """Get new repository.""" - return ChamberRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Chamber a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'chamber', shouldAnalyze) - - -class ChamberRepository: - """A class to handle the chamber settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.chamber.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Chamber', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Chamber') - self.activateChamber = settings.BooleanSetting().getFromValue('Activate Chamber..if you want below functions to work', self, False ) - settings.LabelSeparator().getFromRepository(self) - self.bedTemperature = settings.FloatSpin().getFromValue( 20.0, 'Heated PrintBed Temperature (Celcius):', self, 130.0, 60.0 ) - settings.LabelSeparator().getFromRepository(self) - self.turnBedHeaterOffAtShutDown = settings.BooleanSetting().getFromValue('Turn print Bed Heater Off at Shut Down', self, True ) - self.turnExtruderHeaterOffAtShutDown = settings.BooleanSetting().getFromValue('Turn Extruder Heater Off at Shut Down', self, True ) - self.executeTitle = 'Chamber' - - def execute(self): - """"Chamber button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - - -class ChamberSkein: - """A class to chamber a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.lineIndex = 0 - self.lines = None - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the chamber gcode.""" - self.repository = repository - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - for line in self.lines[self.lineIndex :]: - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( chamber )') - return - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the chamber skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == '()': - self.distanceFeedRate.addLine(line) - self.distanceFeedRate.addParameter('M140', self.repository.bedTemperature.value ) # Set bed temperature. - - elif firstWord == '()': - self.distanceFeedRate.addLine(line) - if self.repository.turnExtruderHeaterOffAtShutDown.value: - self.distanceFeedRate.addLine('M104 S0') # Turn extruder heater off. - if self.repository.turnBedHeaterOffAtShutDown.value: - self.distanceFeedRate.addLine('M140 S0') # Turn bed heater off. - return - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the chamber dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/clip.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/clip.py deleted file mode 100644 index db0a942..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/clip.py +++ /dev/null @@ -1,352 +0,0 @@ -""" -This page is in the table of contents. -Clip clips the ends of loops to prevent bumps from forming. - -The clip manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Clip - -==Operation== -The default 'Activate Clip' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Clip Over Perimeter Width=== -Default is 0.2. - -Defines the ratio of the amount each end of the loop is clipped over the perimeter width. The total gap will therefore be twice the clip. If the ratio is too high loops will have a gap, if the ratio is too low there will be a bulge at the loop ends. - -===Maximum Connection Distance Over Perimeter Width=== -Default is ten. - -Defines the ratio of the maximum connection distance between loops over the perimeter width. If the ratio is zero, nothing will be done. If it is ratio greater than zero, clip will connect nearby loops, combining them into a spiral. For loop connection, nearby means that the distance between a pair of loops is smaller or equal to the maximum connection distance. - -==Examples== -The following examples clip the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and clip.py. - -> python clip.py -This brings up the clip dialog. - -> python clip.py Screw Holder Bottom.stl -The clip tool is parsing the file: -Screw Holder Bottom.stl -.. -The clip tool has created the file: -.. Screw Holder Bottom_clip.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, text, clipRepository = None ): - """Clip a gcode linear move file or text.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, text), clipRepository ) - -def getCraftedTextFromText( gcodeText, clipRepository = None ): - """Clip a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'clip'): - return gcodeText - if clipRepository is None: - clipRepository = settings.getReadRepository( ClipRepository() ) - if not clipRepository.activateClip.value: - return gcodeText - return ClipSkein().getCraftedGcode( clipRepository, gcodeText ) - -def getNewRepository(): - """Get new repository.""" - return ClipRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Clip a gcode linear move file. Chain clip the gcode if it is not already clipped.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'clip', shouldAnalyze) - - -class ClipRepository: - """A class to handle the clip settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.clip.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Clip', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Clip') - self.activateClip = settings.BooleanSetting().getFromValue('Activate Clip..to clip the extrusion that overlaps when printing perimeters', self, True ) - settings.LabelSeparator().getFromRepository(self) - self.clipOverPerimeterWidth = settings.FloatSpin().getFromValue( 0.5, 'Clip Over Perimeter Width adjuster (decrease for bigger gap):', self, 1.5, 1.0 ) - self.maximumConnectionDistanceOverPerimeterWidth = settings.FloatSpin().getFromValue( 1.0, 'Threshold for connecting inner loops (ratio):', self, 10.0, 2.5 ) - self.executeTitle = 'Clip' - - def execute(self): - """Clip button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class ClipSkein: - """A class to clip a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.extruderActive = False - self.feedRateMinute = None - self.isLoopPerimeter = False - self.layerCount = settings.LayerCount() - self.loopPath = None - self.lineIndex = 0 - self.oldLocation = None - self.oldWiddershins = None - self.travelFeedRateMinute = None - - def addGcodeFromThreadZ( self, thread, z ): - """Add a gcode thread to the output.""" - if len(thread) > 0: - self.distanceFeedRate.addGcodeMovementZWithFeedRate( self.travelFeedRateMinute, thread[0], z ) - else: - print( "zero length vertex positions array which was skipped over, this should never happen" ) - if len(thread) < 2: - print( "thread of only one point in clip, this should never happen" ) - print(thread) - return - self.distanceFeedRate.addLine('M101') - for point in thread[1 :]: - self.distanceFeedRate.addGcodeMovementZWithFeedRate( self.feedRateMinute, point, z ) - - def addSegmentToPixelTables( self, location, maskPixelTable, oldLocation ): - """Add the segment to the layer and mask table.""" -# segmentTable = {} - euclidean.addValueSegmentToPixelTable( oldLocation.dropAxis(), location.dropAxis(), self.layerPixelTable, None, self.layerPixelWidth ) -# euclidean.addValueSegmentToPixelTable( oldLocation.dropAxis(), location.dropAxis(), segmentTable, None, self.layerPixelWidth ) -# euclidean.addPixelTableToPixelTable( segmentTable, self.layerPixelTable ) -# euclidean.addPixelTableToPixelTable( segmentTable, maskPixelTable ) -# self.maskPixelTableTable[ location ] = maskPixelTable -# self.maskPixelTableTable[ oldLocation ] = maskPixelTable - - def addTailoredLoopPath(self, line): - """Add a clipped loop path.""" - if self.clipLength > 0.0: - removeTable = {} - euclidean.addLoopToPixelTable( self.loopPath.path, removeTable, self.layerPixelWidth ) - euclidean.removePixelTableFromPixelTable( removeTable, self.layerPixelTable ) - self.loopPath.path = euclidean.getClippedSimplifiedLoopPath(self.clipLength, self.loopPath.path, self.perimeterWidth) - euclidean.addLoopToPixelTable( self.loopPath.path, self.layerPixelTable, self.layerPixelWidth ) - if self.oldWiddershins is None: - self.addGcodeFromThreadZ( self.loopPath.path, self.loopPath.z ) - else: - if self.oldWiddershins != euclidean.isWiddershins( self.loopPath.path ): - self.loopPath.path.reverse() -# self.addGcodeFromThreadZ( self.loopPath.path, self.loopPath.z ) - for point in self.loopPath.path: - self.distanceFeedRate.addGcodeMovementZWithFeedRate( self.feedRateMinute, point, self.loopPath.z ) - if self.getNextThreadIsACloseLoop( self.loopPath.path ) and self.maximumConnectionDistance > 0.0: - self.oldWiddershins = euclidean.isWiddershins( self.loopPath.path ) - else: - self.oldWiddershins = None - self.distanceFeedRate.addLine(line) - self.loopPath = None - - def getConnectionIsCloseWithoutOverlap( self, location, path ): - """Determine if the connection is close enough and does not overlap another thread.""" - if len(path) < 1: - return False - locationComplex = location.dropAxis() - segment = locationComplex - path[-1] - segmentLength = abs(segment) - if segmentLength <= 0.0: - return True - if segmentLength > self.maximumConnectionDistance: - return False - segment /= segmentLength - distance = self.connectingStepLength - segmentEndLength = segmentLength - self.connectingStepLength - while distance < segmentEndLength: - alongPoint = distance * segment + path[-1] - if not euclidean.getIsInFilledRegion( self.boundaryLoops, alongPoint ): - return False - distance += self.connectingStepLength -# removedLayerPixelTable = self.layerPixelTable.copy() -# if self.oldLocation in self.maskPixelTableTable: -# euclidean.removePixelTableFromPixelTable( self.maskPixelTableTable[ self.oldLocation ], removedLayerPixelTable ) -# euclidean.addPathToPixelTable( path[ : - 2 ], removedLayerPixelTable, None, self.layerPixelWidth ) - segmentTable = {} - euclidean.addSegmentToPixelTable( path[-1], locationComplex, segmentTable, 2.0, 2.0, self.layerPixelWidth ) -# euclidean.addValueSegmentToPixelTable( path[-1], locationComplex, segmentTable, None, self.layerPixelWidth ) -# euclidean.addValueSegmentToPixelTable( path[-1], locationComplex, segmentTable, None, self.layerPixelWidth ) -# maskPixelTable = {} -# if location in self.maskPixelTableTable: -# maskPixelTable = self.maskPixelTableTable[ location ] - if euclidean.isPixelTableIntersecting( self.layerPixelTable, segmentTable, {} ): -# if euclidean.isPixelTableIntersecting( removedLayerPixelTable, segmentTable, {} ): - return False - euclidean.addValueSegmentToPixelTable( path[-1], locationComplex, self.layerPixelTable, None, self.layerPixelWidth ) -# euclidean.addPixelTableToPixelTable( segmentTable, self.layerPixelTable ) - return True - - def getCraftedGcode( self, clipRepository, gcodeText ): - """Parse gcode text and store the clip gcode.""" - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization( clipRepository ) - for self.lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[self.lineIndex] - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getNextThreadIsACloseLoop( self, path ): - """Determine if the next thread is a loop.""" - if self.oldLocation is None: - return False - isLoop = False - location = self.oldLocation - for afterIndex in xrange( self.lineIndex + 1, len(self.lines) ): - line = self.lines[ afterIndex ] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == '(' or firstWord == '(': - isLoop = True - elif firstWord == 'G1': - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - elif firstWord == 'M101': - if not isLoop: - return False - return self.getConnectionIsCloseWithoutOverlap( location, path ) - elif firstWord == '(': - return False - return False - - def isNextExtruderOn(self): - """Determine if there is an extruder on command before a move command.""" - for afterIndex in xrange( self.lineIndex + 1, len(self.lines) ): - line = self.lines[ afterIndex ] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - 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 = euclidean.PathZ(location.z) - if self.loopPath is None: - if self.extruderActive: - self.oldWiddershins = None - else: - self.loopPath.path.append(location.dropAxis()) - self.oldLocation = location - - def parseInitialization( self, clipRepository ): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( clip )') - return - elif firstWord == '(': - self.layerThickness = float(splitLine[1]) - elif firstWord == '(': - self.perimeterWidth = float(splitLine[1]) - absolutePerimeterWidth = abs( self.perimeterWidth ) - self.clipLength = (self.layerThickness - (clipRepository.clipOverPerimeterWidth.value * self.layerThickness * (math.pi/4)))*4 - self.connectingStepLength = 0.5 * absolutePerimeterWidth - self.layerPixelWidth = 0.1 * absolutePerimeterWidth - self.maximumConnectionDistance = clipRepository.maximumConnectionDistanceOverPerimeterWidth.value * absolutePerimeterWidth - elif firstWord == '(': - self.travelFeedRateMinute = 60.0 * float(splitLine[1]) - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the clip skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - self.linearMove(splitLine) - elif firstWord == 'M101': - self.extruderActive = True - elif firstWord == 'M103': - self.extruderActive = False - self.isLoopPerimeter = False - if self.loopPath is not None: - self.addTailoredLoopPath(line) - return - elif firstWord == '(': - self.setLayerPixelTable() - if firstWord == '(' or firstWord == '(': - self.isLoopPerimeter = True - if self.loopPath is None: - self.distanceFeedRate.addLine(line) - - def setLayerPixelTable(self): - """Set the layer pixel table.""" - self.layerCount.printProgressIncrement('clip') - boundaryLoop = None - extruderActive = False - maskPixelTable = {} - self.boundaryLoops = [] - self.maskPixelTableTable = {} - self.lastInactiveLocation = None - self.layerPixelTable = {} - oldLocation = self.oldLocation - for afterIndex in xrange( self.lineIndex + 1, len(self.lines) ): - line = self.lines[ afterIndex ] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine(oldLocation, splitLine) - if extruderActive and oldLocation is not None: - self.addSegmentToPixelTables( location, maskPixelTable, oldLocation ) - if not extruderActive: - self.lastInactiveLocation = location - oldLocation = location - elif firstWord == 'M101': - extruderActive = True - elif firstWord == 'M103': - if extruderActive: - if self.lastInactiveLocation is not None: - self.addSegmentToPixelTables( self.lastInactiveLocation, maskPixelTable, oldLocation ) - extruderActive = False - maskPixelTable = {} - elif firstWord == '()': - boundaryLoop = None - elif firstWord == '(': - if boundaryLoop is None: - boundaryLoop = [] - self.boundaryLoops.append(boundaryLoop) - location = gcodec.getLocationFromSplitLine(None, splitLine) - boundaryLoop.append(location.dropAxis()) - elif firstWord == '()': - return - -def main(): - """Display the clip dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/comb.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/comb.py deleted file mode 100644 index 240c4fb..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/comb.py +++ /dev/null @@ -1,420 +0,0 @@ -""" -This page is in the table of contents. -Comb is a script to comb the extrusion hair of a gcode file. - -The comb manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Comb - -Comb bends the extruder travel paths around holes in the slices, to avoid stringers. It moves the extruder to the inside of perimeters before turning the extruder on so any start up ooze will be inside the shape. - -==Operation== -The default 'Activate Comb' checkbox is off. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Running Jump Space=== -Placeholder. - -==Examples== -The following examples comb the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and comb.py. - -> python comb.py -This brings up the comb dialog. - -> python comb.py Screw Holder Bottom.stl -The comb tool is parsing the file: -Screw Holder Bottom.stl -.. -The comb tool has created the file: -.. Screw Holder Bottom_comb.gcode - -""" - -from __future__ import absolute_import -try: - import psyco - psyco.full() -except: - pass -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, text, combRepository = None ): - """Comb a gcode linear move text.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, text), combRepository ) - -def getCraftedTextFromText( gcodeText, combRepository = None ): - """Comb a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'comb'): - return gcodeText - if combRepository is None: - combRepository = settings.getReadRepository( CombRepository() ) - if not combRepository.activateComb.value: - return gcodeText - return CombSkein().getCraftedGcode( combRepository, gcodeText ) - -def getInsideness(path, loop): - """Get portion of the path which is inside the loop.""" - if len(path) < 2: - return 0.0 - pathLength = euclidean.getPathLength(path) - if pathLength <= 0.0: - return 0.0 - incrementRatio = 0.017 - increment = incrementRatio * pathLength - oldPoint = path[0] - numberOfPointsInside = float(euclidean.isPointInsideLoop(loop, oldPoint)) - for point in path[1 :]: - segment = point - oldPoint - distance = abs(segment) - numberOfPosts = int(math.ceil(distance / increment)) - if numberOfPosts > 0: - segmentIncrement = segment / float(numberOfPosts) - for post in xrange(numberOfPosts): - postPoint = oldPoint + float(post) * segmentIncrement - numberOfPointsInside += float(euclidean.isPointInsideLoop(loop, postPoint)) - oldPoint = point - return incrementRatio * numberOfPointsInside - -def getNewRepository(): - """Get new repository.""" - return CombRepository() - -def getPathsByIntersectedLoop( begin, end, loop ): - """Get both paths along the loop from the point nearest to the begin to the point nearest to the end.""" - nearestBeginDistanceIndex = euclidean.getNearestDistanceIndex( begin, loop ) - nearestEndDistanceIndex = euclidean.getNearestDistanceIndex( end, loop ) - beginIndex = ( nearestBeginDistanceIndex.index + 1 ) % len(loop) - endIndex = ( nearestEndDistanceIndex.index + 1 ) % len(loop) - nearestBegin = euclidean.getNearestPointOnSegment( loop[ nearestBeginDistanceIndex.index ], loop[ beginIndex ], begin ) - nearestEnd = euclidean.getNearestPointOnSegment( loop[ nearestEndDistanceIndex.index ], loop[ endIndex ], end ) - clockwisePath = [ nearestBegin ] - widdershinsPath = [ nearestBegin ] - if nearestBeginDistanceIndex.index != nearestEndDistanceIndex.index: - widdershinsPath += euclidean.getAroundLoop( beginIndex, endIndex, loop ) - clockwisePath += euclidean.getAroundLoop( endIndex, beginIndex, loop )[: : -1] - clockwisePath.append( nearestEnd ) - widdershinsPath.append( nearestEnd ) - return [ clockwisePath, widdershinsPath ] - -def writeOutput(fileName, shouldAnalyze=True): - """Comb a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'comb', shouldAnalyze) - - -class CombRepository: - """A class to handle the comb settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.comb.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Comb', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Comb') - self.activateComb = settings.BooleanSetting().getFromValue('Activate Comb if you cant stop the extruder stringing by retraction \nit will avoid moving over loops so the strings will be there \nbut not visible anymore. \nComb bends the extruder travel paths around holes in the slices, to avoid stringing. \nso any start up ooze will be inside the shape.', self, True ) - self.executeTitle = 'Comb' - - def execute(self): - """Comb button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class CombSkein: - """A class to comb a skein of extrusions.""" - def __init__(self): - """Initialize""" - self.isAlteration = False - self.betweenTable = {} - self.boundaryLoop = None - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.extruderActive = False - self.layer = None - self.layerCount = settings.LayerCount() - self.layerTable = {} - self.layerZ = None - self.lineIndex = 0 - self.lines = None - self.nextLayerZ = None - self.oldLocation = None - self.oldZ = None - self.operatingFeedRatePerMinute = None - self.travelFeedRateMinute = None - - def addGcodePathZ( self, feedRateMinute, path, z ): - """Add a gcode path, without modifying the extruder, to the output.""" - for point in path: - self.distanceFeedRate.addGcodeMovementZWithFeedRate(feedRateMinute, point, z) - - def addIfTravel( self, splitLine ): - """Add travel move around loops if the extruder is off.""" - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - if not self.isAlteration and not self.extruderActive and self.oldLocation is not None: - if len( self.getBoundaries() ) > 0: - highestZ = max( location.z, self.oldLocation.z ) - self.addGcodePathZ( self.travelFeedRateMinute, self.getPathsBetween( self.oldLocation.dropAxis(), location.dropAxis() ), highestZ ) - self.oldLocation = location - - def addToLoop(self, location): - """Add a location to loop.""" - if self.layer is None: - if not self.oldZ in self.layerTable: - self.layerTable[ self.oldZ ] = [] - self.layer = self.layerTable[ self.oldZ ] - if self.boundaryLoop is 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 is not None: - self.boundaryLoop.append(location.dropAxis()) - - def getBetweens(self): - """Set betweens for the layer.""" - if self.layerZ in self.betweenTable: - return self.betweenTable[ self.layerZ ] - if self.layerZ not in self.layerTable: - return [] - self.betweenTable[ self.layerZ ] = [] - for boundaryLoop in self.layerTable[ self.layerZ ]: - self.betweenTable[ self.layerZ ] += intercircle.getInsetLoopsFromLoop(boundaryLoop, self.betweenInset) - return self.betweenTable[ self.layerZ ] - - def getBoundaries(self): - """Get boundaries for the layer.""" - if self.layerZ in self.layerTable: - return self.layerTable[ self.layerZ ] - return [] - - def getCraftedGcode( self, combRepository, gcodeText ): - """Parse gcode text and store the comb gcode.""" - self.combRepository = combRepository - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization( combRepository ) - for lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[lineIndex] - self.parseBoundariesLayers( combRepository, line ) - for lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[lineIndex] - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getIsAsFarAndNotIntersecting( self, begin, end ): - """Determine if the point on the line is at least as far from the loop as the center point.""" - if begin == end: - print('this should never happen but it does not really matter, begin == end in getIsAsFarAndNotIntersecting in comb.') - print(begin) - return True - return not euclidean.isLineIntersectingLoops( self.getBetweens(), begin, end ) - - def getIsRunningJumpPathAdded( self, betweens, end, lastPoint, nearestEndMinusLastSegment, pathAround, penultimatePoint, runningJumpSpace ): - """Add a running jump path if possible, and return if it was added.""" - jumpStartPoint = lastPoint - nearestEndMinusLastSegment * runningJumpSpace - if euclidean.isLineIntersectingLoops( betweens, penultimatePoint, jumpStartPoint ): - return False - pathAround[-1] = jumpStartPoint - return True - - def getPathBetween(self, loop, points): - """Add a path between the perimeter and the fill.""" - paths = getPathsByIntersectedLoop(points[1], points[2], loop) - shortestPath = paths[int(euclidean.getPathLength(paths[1]) < euclidean.getPathLength(paths[0]))] - if len(shortestPath) < 2: - return shortestPath - if abs(points[1] - shortestPath[0]) > abs(points[1] - shortestPath[-1]): - shortestPath.reverse() - loopWiddershins = euclidean.isWiddershins(loop) - pathBetween = [] - for pointIndex in xrange(len(shortestPath)): - center = shortestPath[pointIndex] - centerPerpendicular = None - beginIndex = pointIndex - 1 - if beginIndex >= 0: - begin = shortestPath[beginIndex] - centerPerpendicular = intercircle.getWiddershinsByLength(center, begin, self.combInset) - centerEnd = None - endIndex = pointIndex + 1 - if endIndex < len(shortestPath): - end = shortestPath[endIndex] - centerEnd = intercircle.getWiddershinsByLength(end, center, self.combInset) - if centerPerpendicular is None: - centerPerpendicular = centerEnd - elif centerEnd is not None: - centerPerpendicular = 0.5 * (centerPerpendicular + centerEnd) - between = None - if centerPerpendicular is None: - between = center - if between is None: - centerSideWiddershins = center + centerPerpendicular - if euclidean.isPointInsideLoop(loop, centerSideWiddershins) == loopWiddershins: - between = centerSideWiddershins - if between is None: - centerSideClockwise = center - centerPerpendicular - if euclidean.isPointInsideLoop(loop, centerSideClockwise) == loopWiddershins: - between = centerSideClockwise - if between is None: - between = center - pathBetween.append(between) - return pathBetween - - def getPathsBetween(self, begin, end): - """Insert paths between the perimeter and the fill.""" - aroundBetweenPath = [] - points = [begin] - lineX = [] - switchX = [] - segment = euclidean.getNormalized(end - begin) - segmentYMirror = complex(segment.real, - segment.imag) - beginRotated = segmentYMirror * begin - endRotated = segmentYMirror * end - y = beginRotated.imag - boundaries = self.getBoundaries() - for boundaryIndex in xrange(len(boundaries)): - boundary = boundaries[ boundaryIndex ] - boundaryRotated = euclidean.getPointsRoundZAxis(segmentYMirror, boundary) - euclidean.addXIntersectionIndexesFromLoopY(boundaryRotated, boundaryIndex, switchX, y) - switchX.sort() - maximumX = max(beginRotated.real, endRotated.real) - minimumX = min(beginRotated.real, endRotated.real) - for xIntersection in switchX: - if xIntersection.x > minimumX and xIntersection.x < maximumX: - point = segment * complex(xIntersection.x, y) - points.append(point) - lineX.append(xIntersection) - points.append(end) - lineXIndex = 0 -# pathBetweenAdded = False - while lineXIndex < len(lineX) - 1: - lineXFirst = lineX[lineXIndex] - lineXSecond = lineX[lineXIndex + 1] - loopFirst = boundaries[lineXFirst.index] - if lineXSecond.index == lineXFirst.index: - pathBetween = self.getPathBetween(loopFirst, points[lineXIndex : lineXIndex + 4]) - pathBetween = self.getSimplifiedAroundPath(points[lineXIndex], points[lineXIndex + 3], loopFirst, pathBetween) - aroundBetweenPath += pathBetween - lineXIndex += 2 - else: - lineXIndex += 1 -# isLeavingPerimeter = False -# if lineXSecond.index != lineXFirst.index: -# isLeavingPerimeter = True -# pathBetween = self.getPathBetween( points[ lineXIndex + 1 ], points[ lineXIndex + 2 ], isLeavingPerimeter, loopFirst ) -# if isLeavingPerimeter: -# pathBetweenAdded = True -# else: -# pathBetween = self.getSimplifiedAroundPath( points[ lineXIndex ], points[ lineXIndex + 3 ], loopFirst, pathBetween ) -# pathBetweenAdded = True -# aroundBetweenPath += pathBetween -# lineXIndex += 2 - return aroundBetweenPath - - def getSimplifiedAroundPath( self, begin, end, loop, pathAround ): - """Get the simplified path between the perimeter and the fill.""" - pathAround = self.getSimplifiedBeginPath(begin, loop, pathAround) - return self.getSimplifiedEndPath(end, loop, pathAround) - - def getSimplifiedBeginPath( self, begin, loop, pathAround ): - """Get the simplified begin path between the perimeter and the fill.""" - if len(pathAround) < 2: - return pathAround - pathIndex = 0 - while pathIndex < len(pathAround) - 1: - if not self.getIsAsFarAndNotIntersecting(begin, pathAround[pathIndex + 1]): - return pathAround[pathIndex :] - pathIndex += 1 - return pathAround[-1 :] - - def getSimplifiedEndPath(self, end, loop, pathAround): - """Get the simplified end path between the perimeter and the fill.""" - if len(pathAround) < 2: - return pathAround - pathIndex = len(pathAround) - 1 - while pathIndex > 0: - if not self.getIsAsFarAndNotIntersecting(end, pathAround[pathIndex - 1]): - return pathAround[: pathIndex + 1] - pathIndex -= 1 - return pathAround[: 1] - - def parseBoundariesLayers( self, combRepository, line ): - """Parse a gcode line.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'M103': - self.boundaryLoop = None - elif firstWord == '(': - location = gcodec.getLocationFromSplitLine(None, splitLine) - self.addToLoop( location ) - elif firstWord == '(': - self.boundaryLoop = None - self.layer = None - self.oldZ = float(splitLine[1]) - - def parseInitialization( self, combRepository ): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( comb )') - return - elif firstWord == '(': - perimeterWidth = float(splitLine[1]) - self.combInset = 0.7 * perimeterWidth - self.betweenInset = 0.4 * perimeterWidth - self.uTurnWidth = 0.5 * self.betweenInset - elif firstWord == '(': - self.travelFeedRateMinute = 60.0 * float(splitLine[1]) - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the comb skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - self.addIfTravel(splitLine) - self.layerZ = self.nextLayerZ - elif firstWord == 'M101': - self.extruderActive = True - elif firstWord == 'M103': - self.extruderActive = False - elif firstWord == '()': - self.isAlteration = True - elif firstWord == '()': - self.isAlteration = False - elif firstWord == '(': - self.layerCount.printProgressIncrement('comb') - self.nextLayerZ = float(splitLine[1]) - if self.layerZ is None: - self.layerZ = self.nextLayerZ - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the comb dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/cool.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/cool.py deleted file mode 100644 index c2df5c8..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/cool.py +++ /dev/null @@ -1,389 +0,0 @@ -""" -This page is in the table of contents. -Cool is a script to cool the shape. - -Cool works well with a stepper extruder, it does not work well with a DC motor extruder. - -The cool manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Cool - -Allan Ecker aka The Masked Retriever's has written the "Skeinforge Quicktip: Cool" at: -http://blog.thingiverse.com/2009/07/28/skeinforge-quicktip-cool/ - -==Operation== -The default 'Activate Cool' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Bridge Cool=== -Default is one degree Celcius. - -If the layer is a bridge layer, then cool will lower the temperature by 'Bridge Cool' degrees Celcius. - -===Cool Type=== -Default is 'Slow Down'. - -====Orbit==== -When selected, cool will add orbits with the extruder off to give the layer time to cool, so that the next layer is not extruded on a molten base. The orbits will be around the largest island on that layer. Orbit should only be chosen if you can not upgrade to a stepper extruder. - -====Slow Down==== -When selected, cool will slow down the extruder so that it will take the minimum layer time to extrude the layer. DC motors do not operate properly at very slow flow rates, so if you have a DC motor extruder, you should upgrade to a stepper extruder, but if you can't do that, you can try using the 'Orbit' option. - -===Maximum Cool=== -Default is 2 degrees Celcius. - -If it takes less time to extrude the layer than the minimum layer time, then cool will lower the temperature by the 'Maximum Cool' setting times the layer time over the minimum layer time. - -===Minimum Layer Time=== -Default is 60 seconds. - -Defines the minimum amount of time the extruder will spend on a layer, this is an important setting. - -===Minimum Orbital Radius=== -Default is 10 millimeters. - -When the orbit cool type is selected, if the area of the largest island is as large as the square of the "Minimum Orbital Radius" then the orbits will be just within the island. If the island is smaller, then the orbits will be in a square of the "Minimum Orbital Radius" around the center of the island. - -===Name of Alteration Files=== -Cool looks for alteration files in the alterations folder in the .skeinforge folder in the home directory. Cool does not care if the text file names are capitalized, but some file systems do not handle file name cases properly, so to be on the safe side you should give them lower case names. If it doesn't find the file it then looks in the alterations folder in the skeinforge_plugins folder. The cool start and end text idea is from: -http://makerhahn.blogspot.com/2008/10/yay-minimug.html - -====Name of Cool End File==== -Default is cool_end.gcode. - -If there is a file with the name of the "Name of Cool End File" setting, it will be added to the start of the orbits. - -====Name of Cool Start File==== -Default is cool_start.gcode. - -If there is a file with the name of the "Name of Cool Start File" setting, it will be added to the end of the orbits. - -===Turn Fan On at Beginning=== -Default is on. - -When selected, cool will turn the fan on at the beginning of the fabrication. - -===Turn Fan On at Ending=== -Default is on. - -When selected, cool will turn the fan off at the ending of the fabrication. - -==Examples== -The following examples cool the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and cool.py. - -> python cool.py -This brings up the cool dialog. - -> python cool.py Screw Holder Bottom.stl -The cool tool is parsing the file: -Screw Holder Bottom.stl -.. -The cool tool has created the file: -.. Screw Holder Bottom_cool.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import os -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText(fileName, text, repository=None): - """Cool a gcode linear move text.""" - return getCraftedTextFromText(archive.getTextIfEmpty(fileName, text), repository) - -def getCraftedTextFromText(gcodeText, repository=None): - """Cool a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty(gcodeText, 'cool'): - return gcodeText - if repository is None: - repository = settings.getReadRepository(CoolRepository()) - if not repository.activateCool.value: - return gcodeText - return CoolSkein().getCraftedGcode(gcodeText, repository) - -def getNewRepository(): - """Get new repository.""" - return CoolRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Cool a gcode linear move file. Chain cool the gcode if it is not already cooled.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'cool', shouldAnalyze) - - -class CoolRepository: - """A class to handle the cool settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.cool.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( - fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Cool', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute( - 'http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Cool') - self.activateCool = settings.BooleanSetting().getFromValue('Activate Cool.. but use with a fan!', self, False) - - settings.LabelDisplay().getFromName('- When To use Cool?-', self ) - self.minimumLayerTime = settings.FloatSpin().getFromValue(0.0, 'Use Cool if layer takes shorter than(seconds):', self, 120.0, 10.0) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- What to do if Cool is necessary? -', self ) - self.turnFanOnAtBeginning = settings.BooleanSetting().getFromValue('Turn Fan On at Beginning', self, True) - self.turnFanOffAtEnding = settings.BooleanSetting().getFromValue('Turn Fan Off at Ending', self, True) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Name of Macro (gmc) Files to execute -', self ) - self.nameOfCoolStartFile = settings.StringSetting().getFromValue('Execute when Cool starts:', self, 'cool_start.gmc') - self.nameOfCoolEndFile = settings.StringSetting().getFromValue('Execute when Cool ends:', self, 'cool_end.gmc') - - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- How to Cool? -', self ) - self.coolType = settings.MenuButtonDisplay().getFromName('Cool by:', self) - self.orbit = settings.MenuRadio().getFromMenuButtonDisplay(self.coolType, 'Orbiting around Object', self, False) - self.slowDown = settings.MenuRadio().getFromMenuButtonDisplay(self.coolType, 'Slow Down during print', self, True) - settings.LabelSeparator().getFromRepository(self) - settings.LabelSeparator().getFromRepository(self) - self.maximumCool = settings.FloatSpin().getFromValue(0.0, 'Maximum Cool (Celcius):', self, 10.0, 2.0) - self.bridgeCool = settings.FloatSpin().getFromValue(0.0, 'Bridge Cool (Celcius):', self, 10.0, 1.0) - self.minimumOrbitalRadius = settings.FloatSpin().getFromValue( - 0.0, 'Minimum Orbital Radius (millimeters):', self, 20.0, 10.0) - settings.LabelSeparator().getFromRepository(self) - - - self.executeTitle = 'Cool' - - def execute(self): - """Cool button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode( - self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class CoolSkein: - """A class to cool a skein of extrusions.""" - def __init__(self): - self.boundaryLayer = None - self.coolTemperature = None - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.feedRateMinute = 960.0 - self.highestZ = 1.0 - self.isBridgeLayer = False - self.layerCount = settings.LayerCount() - self.lineIndex = 0 - self.lines = None - self.multiplier = 1.0 - self.oldFlowRate = None - self.oldFlowRateString = None - self.oldLocation = None - self.oldTemperature = None - - def addCoolOrbits(self, remainingOrbitTime): - """Add the minimum radius cool orbits.""" - if len(self.boundaryLayer.loops) < 1: - return - insetBoundaryLoops = intercircle.getInsetLoopsFromLoops(self.perimeterWidth, self.boundaryLayer.loops) - if len(insetBoundaryLoops) < 1: - insetBoundaryLoops = self.boundaryLayer.loops - largestLoop = euclidean.getLargestLoop(insetBoundaryLoops) - loopArea = euclidean.getAreaLoopAbsolute(largestLoop) - if loopArea < self.minimumArea: - center = 0.5 * (euclidean.getMaximumByComplexPath(largestLoop) + euclidean.getMinimumByComplexPath(largestLoop)) - centerXBounded = max(center.real, self.boundingRectangle.cornerMinimum.real) - centerXBounded = min(centerXBounded, self.boundingRectangle.cornerMaximum.real) - centerYBounded = max(center.imag, self.boundingRectangle.cornerMinimum.imag) - centerYBounded = min(centerYBounded, self.boundingRectangle.cornerMaximum.imag) - center = complex(centerXBounded, centerYBounded) - maximumCorner = center + self.halfCorner - minimumCorner = center - self.halfCorner - largestLoop = euclidean.getSquareLoopWiddershins(minimumCorner, maximumCorner) - pointComplex = euclidean.getXYComplexFromVector3(self.oldLocation) - if pointComplex is not None: - largestLoop = euclidean.getLoopStartingNearest(self.perimeterWidth, pointComplex, largestLoop) - intercircle.addOrbitsIfLarge( - self.distanceFeedRate, largestLoop, self.orbitalFeedRatePerSecond, remainingOrbitTime, self.highestZ) - - def addCoolTemperature(self, remainingOrbitTime): - "Parse a gcode line and add it to the cool skein.""" - layerCool = self.repository.maximumCool.value * remainingOrbitTime / self.repository.minimumLayerTime.value - if self.isBridgeLayer: - layerCool = max(self.repository.bridgeCool.value, layerCool) - if self.oldTemperature is not None and layerCool != 0.0: - self.coolTemperature = self.oldTemperature - layerCool - self.addTemperature(self.coolTemperature) - - def addFlowRateLineIfNecessary(self, flowRate): - "Add a line of flow rate if different.""" - flowRateString = euclidean.getFourSignificantFigures(flowRate) - if flowRateString == self.oldFlowRateString: - return - if flowRateString is not None: - self.distanceFeedRate.addLine('M108 S' + flowRateString) - self.oldFlowRateString = flowRateString - - def addFlowRateMultipliedLineIfNecessary(self, flowRate): - """Add a multipled line of flow rate if different.""" - if flowRate is not None: - self.addFlowRateLineIfNecessary(self.multiplier * flowRate) - - def addGcodeFromFeedRateMovementZ(self, feedRateMinute, point, z): - """Add a movement to the output.""" - self.distanceFeedRate.addLine(self.distanceFeedRate.getLinearGcodeMovementWithFeedRate(feedRateMinute, point, z)) - - def addOrbitsIfNecessary(self, remainingOrbitTime): - """Parse a gcode line and add it to the cool skein.""" - if remainingOrbitTime > 0.0 and self.boundaryLayer is not None: - self.addCoolOrbits(remainingOrbitTime) - - def addTemperature(self, temperature): - """Add a line of temperature.""" - self.distanceFeedRate.addLine('M104 S' + euclidean.getRoundedToThreePlaces(temperature)) - - def getCoolMove(self, line, location, splitLine): - """Add line to time spent on layer.""" - self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) - self.highestZ = max(location.z, self.highestZ) - self.addFlowRateMultipliedLineIfNecessary(self.oldFlowRate) - return self.distanceFeedRate.getLineWithFeedRate(self.multiplier * self.feedRateMinute, line, splitLine) - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the cool gcode.""" - self.repository = repository - self.coolEndLines = settings.getLinesInAlterationsOrGivenDirectory(repository.nameOfCoolEndFile.value) - self.coolStartLines = settings.getLinesInAlterationsOrGivenDirectory(repository.nameOfCoolStartFile.value) - self.halfCorner = complex(repository.minimumOrbitalRadius.value, repository.minimumOrbitalRadius.value) - self.lines = archive.getTextLines(gcodeText) - self.minimumArea = 4.0 * repository.minimumOrbitalRadius.value * repository.minimumOrbitalRadius.value - self.parseInitialization() - self.boundingRectangle = gcodec.BoundingRectangle().getFromGcodeLines( - self.lines[self.lineIndex :], 0.5 * self.perimeterWidth) - margin = 0.2 * self.perimeterWidth - halfCornerMargin = self.halfCorner + complex(margin, margin) - self.boundingRectangle.cornerMaximum -= halfCornerMargin - self.boundingRectangle.cornerMinimum += halfCornerMargin - for self.lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[self.lineIndex] - self.parseLine(line) - if repository.turnFanOffAtEnding.value: - self.distanceFeedRate.addLine('M107') - return self.distanceFeedRate.output.getvalue() - - def getLayerTime(self): - """Get the time the extruder spends on the layer.""" - feedRateMinute = self.feedRateMinute - layerTime = 0.0 - lastThreadLocation = self.oldLocation - for lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine(lastThreadLocation, splitLine) - feedRateMinute = gcodec.getFeedRateMinute(feedRateMinute, splitLine) - if lastThreadLocation is not None: - feedRateSecond = feedRateMinute / 60.0 - layerTime += location.distance(lastThreadLocation) / feedRateSecond - lastThreadLocation = location - elif firstWord == '(': - self.isBridgeLayer = True - elif firstWord == '()': - return layerTime - return layerTime - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == 'M108': - self.setOperatingFlowString(splitLine) - elif firstWord == '(': - self.perimeterWidth = float(splitLine[1]) - if self.repository.turnFanOnAtBeginning.value: - self.distanceFeedRate.addLine('M106') - elif firstWord == '()': - self.distanceFeedRate.addLine('( cool )') - return - elif firstWord == '(': - self.orbitalFeedRatePerSecond = float(splitLine[1]) - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the cool skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - line = self.getCoolMove(line, location, splitLine) - self.oldLocation = location - elif firstWord == 'M104': - self.oldTemperature = gcodec.getDoubleAfterFirstLetter(splitLine[1]) - elif firstWord == 'M108': - self.setOperatingFlowString(splitLine) - self.addFlowRateMultipliedLineIfNecessary(self.oldFlowRate) - return - elif firstWord == '(': - self.boundaryLoop.append(gcodec.getLocationFromSplitLine(None, splitLine).dropAxis()) - elif firstWord == '(': - self.layerCount.printProgressIncrement('cool') - self.distanceFeedRate.addLine(line) - self.distanceFeedRate.addLinesSetAbsoluteDistanceMode(self.coolStartLines) - layerTime = self.getLayerTime() - remainingOrbitTime = max(self.repository.minimumLayerTime.value - layerTime, 0.0) - self.addCoolTemperature(remainingOrbitTime) - if self.repository.orbit.value: - self.addOrbitsIfNecessary(remainingOrbitTime) - else: - self.setMultiplier(layerTime) - z = float(splitLine[1]) - self.boundaryLayer = euclidean.LoopLayer(z) - self.highestZ = max(z, self.highestZ) - self.distanceFeedRate.addLinesSetAbsoluteDistanceMode(self.coolEndLines) - return - elif firstWord == '()': - self.isBridgeLayer = False - self.multiplier = 1.0 - if self.coolTemperature is not None: - self.addTemperature(self.oldTemperature) - self.coolTemperature = None - self.addFlowRateLineIfNecessary(self.oldFlowRate) - elif firstWord == '()': - self.boundaryLoop = [] - self.boundaryLayer.loops.append(self.boundaryLoop) - self.distanceFeedRate.addLine(line) - - def setMultiplier(self, layerTime): - """Set the feed and flow rate multiplier.""" - self.multiplier = min(1.0, layerTime / self.repository.minimumLayerTime.value) - - def setOperatingFlowString(self, splitLine): - """Set the operating flow string from the split line.""" - self.oldFlowRate = float(splitLine[1][1 :]) - - -def main(): - """Display the cool dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor(getNewRepository()) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/dimension.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/dimension.py deleted file mode 100644 index 4cef6e9..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/dimension.py +++ /dev/null @@ -1,390 +0,0 @@ -#! /usr/bin/env python -""" -This page is in the table of contents. -Dimension adds Adrian's extruder distance E value to the gcode movement lines, as described at: -http://blog.reprap.org/2009/05/4d-printing.html - -and in Erik de Bruijn's conversion script page at: -http://objects.reprap.org/wiki/3D-to-5D-Gcode.php - -The dimension manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Dimension - -Nophead wrote an excellent article on how to set the filament parameters: -http://hydraraptor.blogspot.com/2011/03/spot-on-flow-rate.html - -==Operation== -The default 'Activate Dimension' checkbox is off. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Extrusion Distance Format Choice=== -Default is 'Absolute Extrusion Distance' because in Adrian's description the distance is absolute. In future, because the relative distances are smaller than the cumulative absolute distances, hopefully the firmaware will be able to use relative distance. - -====Absolute Extrusion Distance==== -When selected, the extrusion distance output will be the total extrusion distance to that gcode line. - -====Relative Extrusion Distance==== -When selected, the extrusion distance output will be the extrusion distance from the last gcode line. - -===Extruder Retraction Speed=== -Default is 13.3 mm/s. - -Defines the extruder retraction feed rate. - -===Filament=== -====Filament Diameter==== -Default is 2.8 millimeters. - -Defines the filament diameter. - -====Filament Packing Density==== -Default is 0.85. This is for ABS. - -Defines the effective filament packing density. - -The default value is so low for ABS because ABS is relatively soft and with a pinch wheel extruder the teeth of the pinch dig in farther, so it sees a smaller effective diameter. With a hard plastic like PLA the teeth of the pinch wheel don't dig in as far, so it sees a larger effective diameter, so feeds faster, so for PLA the value should be around 0.97. This is with Wade's hobbed bolt. The effect is less significant with larger pinch wheels. - -Overall, you'll have to find the optimal filament packing density by experiment. - -===Retraction Distance=== -Default is zero. - -Defines the retraction distance when the thread ends. - -===Restart Extra Distance=== -Default is zero. - -Defines the restart extra distance when the thread restarts. The restart distance will be the retraction distance plus the restart extra distance. - -==Examples== -The following examples dimension the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and dimension.py. - -> python dimension.py -This brings up the dimension dialog. - -> python dimension.py Screw Holder Bottom.stl -The dimension tool is parsing the file: -Screw Holder Bottom.stl -.. -The dimension tool has created the file: -.. Screw Holder Bottom_dimension.gcode - -""" - -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, gcodeText = '', repository=None): - """Dimension a gcode file or text.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, gcodeText), repository ) - -def getCraftedTextFromText(gcodeText, repository=None): - """Dimension a gcode text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'dimension'): - return gcodeText - if repository is None: - repository = settings.getReadRepository( DimensionRepository() ) - if not repository.activateDimension.value: - return gcodeText - return DimensionSkein().getCraftedGcode(gcodeText, repository) - -def getNewRepository(): - """Get new repository.""" - return DimensionRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Dimension a gcode file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'dimension', shouldAnalyze) - - -class DimensionRepository: - """A class to handle the dimension settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.dimension.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Dimension', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Dimension') - self.activateDimension = settings.BooleanSetting().getFromValue('Activate Volumetric Extrusion (Stepper driven Extruders)', self, True ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Filament Settings - YOU NEED TO HAVE YOUR EXTRUDER CALIBRATED FIRST -', self ) - settings.LabelDisplay().getFromName('http://josefprusa.cz/skeinforge-40-volumetric-calibration', self ) - settings.LabelSeparator().getFromRepository(self) - self.filamentDiameter = settings.FloatSpin().getFromValue(1.5, 'Filament Diameter (mm):', self, 3.5, 2.8) - self.filamentPackingDensity = settings.FloatSpin().getFromValue(0.7, 'Filament Packing Density (ratio) lower=more extrusion:', self, 1.0, 1.00) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Fighting Oooze -', self ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Filament Retraction Settings -', self ) - self.retractionDistance = settings.FloatSpin().getFromValue( 0.00, 'Retraction Distance (millimeters):', self, 3.00, 1.00 ) - self.restartExtraDistance = settings.FloatSpin().getFromValue( -0.50, 'Restart Extra Distance (millimeters):', self, 0.50, 0.00 ) - self.extruderRetractionSpeed = settings.FloatSpin().getFromValue( 5.0, 'Extruder Retraction Speed (mm/s):', self, 50.0, 15.0 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- When to retract ? -', self ) - self.retractWhenCrossing = settings.BooleanSetting().getFromValue('Force to retract when crossing over spaces', self, True) - self.minimumExtrusionForRetraction = settings.FloatSpin().getFromValue(0.0, 'Minimum Extrusion before Retraction (millimeters):', self, 2.0, 1.0) - self.minimumTravelForRetraction = settings.FloatSpin().getFromValue(0.0, 'Minimum Travelmove after Retraction (millimeters):', self, 2.0, 1.0) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Firmware Related Stuff -', self ) - extrusionDistanceFormatLatentStringVar = settings.LatentStringVar() - self.extrusionDistanceFormatChoiceLabel = settings.LabelDisplay().getFromName('Extrusion Values should be: ', self ) - settings.Radio().getFromRadio( extrusionDistanceFormatLatentStringVar, 'in Absolute units (Sprinter, FiveD a.o.)', self, True ) - self.relativeExtrusionDistance = settings.Radio().getFromRadio( extrusionDistanceFormatLatentStringVar, 'in Relative units (Teacup a.o.)', self, False ) - settings.LabelSeparator().getFromRepository(self) - self.executeTitle = 'Dimension' - - def execute(self): - """Dimension button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class DimensionSkein: - """A class to dimension a skein of extrusions.""" - def __init__(self): - """Initialize.""" - self.absoluteDistanceMode = True - self.boundaryLayers = [] - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.feedRateMinute = None - self.isExtruderActive = False - self.layerIndex = -1 - self.lineIndex = 0 - self.maximumZTravelFeedRatePerSecond = None - self.oldLocation = None - self.operatingFlowRate = None - self.retractionRatio = 1.0 - self.totalExtrusionDistance = 0.0 - self.travelFeedRatePerSecond = None - self.zDistanceRatio = 5.0 - - def addLinearMoveExtrusionDistanceLine( self, extrusionDistance ): - """Get the extrusion distance string from the extrusion distance.""" - - - self.distanceFeedRate.output.write('G1 F%s\n' % self.extruderRetractionSpeedMinuteString ) - self.distanceFeedRate.output.write('G1%s\n' % self.getExtrusionDistanceStringFromExtrusionDistance( extrusionDistance ) ) - self.distanceFeedRate.output.write('G1 F%s\n' % self.distanceFeedRate.getRounded( self.feedRateMinute ) ) - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the dimension gcode.""" - self.repository = repository - filamentRadius = 0.5 * repository.filamentDiameter.value - filamentPackingArea = math.pi * filamentRadius * filamentRadius * repository.filamentPackingDensity.value - self.minimumExtrusionForRetraction = self.repository.minimumExtrusionForRetraction.value - self.minimumTravelForRetraction = self.repository.minimumTravelForRetraction.value - self.doubleMinimumTravelForRetraction = self.minimumTravelForRetraction + self.minimumTravelForRetraction - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - if self.repository.retractWhenCrossing.value: - self.parseBoundaries() - self.flowScaleSixty = 60.0 * (((self.layerThickness/2)*(self.layerThickness/2)*math.pi)+self.layerThickness*(self.perimeterWidth-self.layerThickness))/filamentPackingArea - if self.operatingFlowRate is None: - print('There is no operatingFlowRate so dimension will do nothing.') - return gcodeText - self.restartDistance = self.repository.retractionDistance.value + self.repository.restartExtraDistance.value - self.extruderRetractionSpeedMinuteString = self.distanceFeedRate.getRounded(60.0 * self.repository.extruderRetractionSpeed.value) - if self.maximumZTravelFeedRatePerSecond is not None and self.travelFeedRatePerSecond is not None: - self.zDistanceRatio = self.travelFeedRatePerSecond / self.maximumZTravelFeedRatePerSecond - for lineIndex in xrange(self.lineIndex, len(self.lines)): - self.parseLine( lineIndex ) - return self.distanceFeedRate.output.getvalue() - - def getDimensionedArcMovement(self, line, splitLine): - """Get a dimensioned arc movement.""" - if self.oldLocation is None: - return line - relativeLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - self.oldLocation += relativeLocation - distance = gcodec.getArcDistance(relativeLocation, splitLine) - return line + self.getExtrusionDistanceString(distance, splitLine) - - def getDimensionedLinearMovement( self, line, splitLine ): - """Get a dimensioned linear movement.""" - distance = 0.0 - if self.absoluteDistanceMode: - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - if self.oldLocation is not None: - distance = abs( location - self.oldLocation ) - self.oldLocation = location - else: - if self.oldLocation is None: - print('Warning: There was no absolute location when the G91 command was parsed, so the absolute location will be set to the origin.') -# self.oldLocation = Vector3() - location = gcodec.getLocationFromSplitLine(None, splitLine) - distance = abs( location ) - self.oldLocation += location - return line + self.getExtrusionDistanceString( distance, splitLine ) - - def getDistanceToNextThread(self, lineIndex): - """Get the travel distance to the next thread.""" - if self.oldLocation is None: - return None - isActive = False - location = self.oldLocation - for afterIndex in xrange(lineIndex + 1, len(self.lines)): - line = self.lines[afterIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1': - if isActive: - location = gcodec.getLocationFromSplitLine(location, splitLine) - if self.repository.retractWhenCrossing.value: - locationEnclosureIndex = self.getSmallestEnclosureIndex(location.dropAxis()) - if locationEnclosureIndex != self.getSmallestEnclosureIndex(self.oldLocation.dropAxis()): - return None - locationMinusOld = location - self.oldLocation - xyTravel = abs(locationMinusOld.dropAxis()) - zTravelMultiplied = locationMinusOld.z * self.zDistanceRatio - return math.sqrt(xyTravel * xyTravel + zTravelMultiplied * zTravelMultiplied) - elif firstWord == 'M101': - isActive = True - elif firstWord == 'M103': - isActive = False - return None - - def getExtrusionDistanceString( self, distance, splitLine ): - """Get the extrusion distance string.""" - self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) - if not self.isExtruderActive: - return '' - if distance <= 0.0: - return '' - scaledFlowRate = self.flowRate * self.flowScaleSixty - return self.getExtrusionDistanceStringFromExtrusionDistance(scaledFlowRate / self.feedRateMinute * distance) - def getExtrusionDistanceStringFromExtrusionDistance( self, extrusionDistance ): - """Get the extrusion distance string from the extrusion distance.""" - if self.repository.relativeExtrusionDistance.value: - return ' E' + self.distanceFeedRate.getRounded( extrusionDistance ) - self.totalExtrusionDistance += extrusionDistance - return ' E' + self.distanceFeedRate.getRounded( self.totalExtrusionDistance ) - - - def getRetractionRatio(self, lineIndex): - """Get the retraction ratio.""" - distanceToNextThread = self.getDistanceToNextThread(lineIndex) - if self.totalExtrusionDistance <= self.minimumExtrusionForRetraction: - return self.totalExtrusionDistance/self.minimumExtrusionForRetraction - if distanceToNextThread is None: - return 1.0 - if distanceToNextThread >= self.doubleMinimumTravelForRetraction: - return 1.0 - if distanceToNextThread <= self.minimumTravelForRetraction: - return 0.0 - return (distanceToNextThread - self.minimumTravelForRetraction) / self.minimumTravelForRetraction - - def getSmallestEnclosureIndex(self, point): - """Get the index of the smallest boundary loop which encloses the point.""" - boundaryLayer = self.boundaryLayers[self.layerIndex] - for loopIndex, loop in enumerate(boundaryLayer.loops): - if euclidean.isPointInsideLoop(loop, point): - return loopIndex - return None - - def parseBoundaries(self): - """Parse the boundaries and add them to the boundary layers.""" - boundaryLoop = None - boundaryLayer = None - for line in self.lines[self.lineIndex :]: - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == '()': - boundaryLoop = None - elif firstWord == '(': - location = gcodec.getLocationFromSplitLine(None, splitLine) - if boundaryLoop is None: - boundaryLoop = [] - boundaryLayer.loops.append(boundaryLoop) - boundaryLoop.append(location.dropAxis()) - elif firstWord == '(': - boundaryLayer = euclidean.LoopLayer(float(splitLine[1])) - self.boundaryLayers.append(boundaryLayer) - for boundaryLayer in self.boundaryLayers: - triangle_mesh.sortLoopsInOrderOfArea(False, boundaryLayer.loops) - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( dimension )') - return - elif firstWord == '(': - self.layerThickness = float(splitLine[1]) - elif firstWord == '(': - self.maximumZTravelFeedRatePerSecond = float(splitLine[1]) - elif firstWord == '(': - self.maximumZTravelFeedRatePerSecond = float(splitLine[1]) - elif firstWord == '(': - self.feedRateMinute = 60.0 * float(splitLine[1]) - elif firstWord == '(': - self.operatingFlowRate = float(splitLine[1]) - self.flowRate = self.operatingFlowRate - elif firstWord == '(': - self.perimeterWidth = float(splitLine[1]) - elif firstWord == '(': - self.travelFeedRatePerSecond = float(splitLine[1]) - self.distanceFeedRate.addLine(line) - - def parseLine( self, lineIndex ): - """Parse a gcode line and add it to the dimension skein.""" - line = self.lines[lineIndex].lstrip() - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G2' or firstWord == 'G3': - line = self.getDimensionedArcMovement( line, splitLine ) - if firstWord == 'G1': - line = self.getDimensionedLinearMovement( line, splitLine ) - if firstWord == 'G90': - self.absoluteDistanceMode = True - elif firstWord == 'G91': - self.absoluteDistanceMode = False - elif firstWord == '(': - self.layerIndex += 1 - elif firstWord == 'M101': - self.addLinearMoveExtrusionDistanceLine(self.restartDistance * self.retractionRatio) - if not self.repository.relativeExtrusionDistance.value: - self.distanceFeedRate.addLine('G92 E0') - self.totalExtrusionDistance = 0.0 - self.isExtruderActive = True - elif firstWord == 'M103': - self.retractionRatio = self.getRetractionRatio(lineIndex) - self.addLinearMoveExtrusionDistanceLine(-self.repository.retractionDistance.value * self.retractionRatio) - self.isExtruderActive = False - elif firstWord == 'M108': - self.flowRate = float( splitLine[1][1 :] ) - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the dimension dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/export.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/export.py deleted file mode 100644 index a3ce001..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/export.py +++ /dev/null @@ -1,466 +0,0 @@ -""" -This page is in the table of contents. -Export is a script to pick an export plugin and optionally print the output to a file. - -The export manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Export - -==Operation== -The default 'Activate Export' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Also Send Output To=== -Default is empty. - -Defines the output name for sending to a file or pipe. A common choice is sys.stdout to print the output in the shell screen. Another common choice is sys.stderr. With the empty default, nothing will be done. If the value is anything else, the output will be written to that file name. - -===Comment Choice=== -Default is 'Delete All Comments'. - -====Do Not Delete Comments==== -When selected, export will not delete comments. Crafting comments slow down the processing in many firmware types, which leads to segment pauses. - -====Delete Crafting Comments==== -When selected, export will delete the time consuming crafting comments, but leave the initialization comments. Since the crafting comments are deleted, there are no additional segment pauses. The remaining initialization comments provide some useful information for the analyze tools. - -====Delete All Comments==== -When selected, export will delete all comments. The comments are not necessary to run a fabricator. - -===Export Operations=== -Export presents the user with a choice of the export plugins in the export_plugins folder. The chosen plugin will then modify the gcode or translate it into another format. There is also the "Do Not Change Output" choice, which will not change the output. An export plugin is a script in the export_plugins folder which has the getOutput function, the globalIsReplaceable variable and if it's output is not replaceable, the writeOutput function. - -===File Extension=== -Default is gcode. - -Defines the file extension added to the name of the output file. - -===Name of Replace File=== -Default is replace.csv. - -When export is exporting the code, if there is a tab separated file with the name of the "Name of Replace File" setting, it will replace the string in the first column by its replacement in the second column. If there is nothing in the second column, the first column string will be deleted, if this leads to an empty line, the line will be deleted. If there are replacement columns after the second, they will be added as extra lines of text. There is an example file replace_example.csv to demonstrate the tab separated format, which can be edited in a text editor or a spreadsheet. - -Export looks for the alteration file in the alterations folder in the .skeinforge folder in the home directory. Export does not care if the text file names are capitalized, but some file systems do not handle file name cases properly, so to be on the safe side you should give them lower case names. If it doesn't find the file it then looks in the alterations folder in the skeinforge_plugins folder. - -===Save Penultimate Gcode=== -Default is off. - -When selected, export will save the gcode file with the suffix '_penultimate.gcode' just before it is exported. This is useful because the code after it is exported could be in a form which the viewers can not display well. - -==Examples== -The following examples export the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and export.py. - -> python export.py -This brings up the export dialog. - -> python export.py Screw Holder Bottom.stl -The export tool is parsing the file: -Screw Holder Bottom.stl -.. -The export tool has created the file: -.. Screw Holder Bottom_export.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_analyze -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -from time import strftime -import cStringIO -import os -import sys -import time -import string -import zipfile - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedTextFromText(gcodeText, repository=None): - """Export a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'export'): - return gcodeText - if repository is None: - repository = settings.getReadRepository(ExportRepository()) - if not repository.activateExport.value: - return gcodeText - return ExportSkein().getCraftedGcode(repository, gcodeText) - -def getDistanceGcode(exportText): - """Get gcode lines with distance variable added.""" - lines = archive.getTextLines(exportText) - oldLocation = None - for line in lines: - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = None - if len(splitLine) > 0: - firstWord = splitLine[0] - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine(oldLocation, splitLine) - if oldLocation is not None: - distance = location.distance(oldLocation) - print( distance ) - oldLocation = location - return exportText - -def getNewRepository(): - """Get new repository.""" - return ExportRepository() - -def getReplaceableExportGcode(nameOfReplaceFile, replaceableExportGcode): - """Get text with strings replaced according to replace.csv file.""" - replaceLines = settings.getLinesInAlterationsOrGivenDirectory(nameOfReplaceFile) - if len(replaceLines) < 1: - return replaceableExportGcode - for replaceLine in replaceLines: - splitLine = replaceLine.replace('\\n', '\t').split('\t') - if len(splitLine) > 0: - replaceableExportGcode = replaceableExportGcode.replace(splitLine[0], '\n'.join(splitLine[1 :])) - output = cStringIO.StringIO() - gcodec.addLinesToCString(output, archive.getTextLines(replaceableExportGcode)) - return output.getvalue() - -def getSelectedPluginModule( plugins ): - """Get the selected plugin module.""" - for plugin in plugins: - if plugin.value: - return archive.getModuleWithDirectoryPath( plugin.directoryPath, plugin.name ) - return None - -def sendOutputTo(text, toValue): - """Send output to a file or a standard output.""" - if toValue == 'sys.stderr': - print(text, ' ', '\n', sys.stderr) - return - if toValue == 'sys.stdout': - print(text, ' ', '\n', sys.stdout) - return - archive.writeFileText(toValue, text) - -def writeOutput(fileName, shouldAnalyze=True): - """Export a gcode linear move file.""" - - if fileName == '': - return None - repository = ExportRepository() - settings.getReadRepository(repository) - startTime = time.time() - print('File ' + archive.getSummarizedFileName(fileName) + ' is being chain exported.') - fileNameSuffix = fileName[: fileName.rfind('.')] - - if repository.addExportSuffix.value: - fileNameSuffix += '_export' - - if repository.profileFileExtension.value: - profileName = skeinforge_profile.getProfileName(skeinforge_profile.getCraftTypeName()) - if profileName: - fileNameSuffix += '.' + string.replace(profileName, ' ', '_') - - if repository.descriptiveExtension.value: - fileNameSuffix += descriptiveExtension() - - if repository.timestampExtension.value: - fileNameSuffix += '.'+strftime("%Y%m%d_%H%M%S") - - if repository.archiveProfile.value: - profileName = skeinforge_profile.getProfileName(skeinforge_profile.getCraftTypeName()) - if profileName: - profileZipFileName = fileNameSuffix + '.zip' - zipper(archive.getProfilesPath(skeinforge_profile.getProfileDirectory()), profileName+'/', profileZipFileName) - print('Profile archived to ' + profileZipFileName) - - if repository.exportProfileAsCsv.value: - csvExportFilename = fileNameSuffix + '.csv' - archive.writeFileText(csvExportFilename, Condenser().readSettings()) - - fileNameSuffix += '.' + repository.fileExtension.value - gcodeText = gcodec.getGcodeFileText(fileName, '') - procedures = skeinforge_craft.getProcedures('export', gcodeText) - gcodeText = skeinforge_craft.getChainTextFromProcedures(fileName, procedures[ : - 1 ], gcodeText) - if gcodeText == '': - return None - fileNamePenultimate = fileName[: fileName.rfind('.')] + '_penultimate.gcode' - filePenultimateWritten = False - if repository.savePenultimateGcode.value: - archive.writeFileText(fileNamePenultimate, gcodeText) - filePenultimateWritten = True - print('The penultimate file is saved as ' + archive.getSummarizedFileName(fileNamePenultimate)) - exportGcode = getCraftedTextFromText(gcodeText, repository) - window = None - if shouldAnalyze: - window = skeinforge_analyze.writeOutput(fileName, fileNamePenultimate, fileNameSuffix, - filePenultimateWritten, gcodeText) - replaceableExportGcode = None - selectedPluginModule = getSelectedPluginModule(repository.exportPlugins) - if selectedPluginModule is None: - replaceableExportGcode = exportGcode - else: - if selectedPluginModule.globalIsReplaceable: - replaceableExportGcode = selectedPluginModule.getOutput(exportGcode) - else: - selectedPluginModule.writeOutput(fileNameSuffix, exportGcode) - if replaceableExportGcode is not None: - replaceableExportGcode = getReplaceableExportGcode(repository.nameOfReplaceFile.value, replaceableExportGcode) - archive.writeFileText( fileNameSuffix, replaceableExportGcode ) - print('The exported file is saved as ' + archive.getSummarizedFileName(fileNameSuffix)) - if repository.alsoSendOutputTo.value != '': - if replaceableExportGcode is None: - replaceableExportGcode = selectedPluginModule.getOutput(exportGcode) - sendOutputTo(replaceableExportGcode, repository.alsoSendOutputTo.value) - print('It took %s to export the file.' % euclidean.getDurationString(time.time() - startTime)) - - return window - -def descriptiveExtension(): - descriptionExtension = '.'+carveDescription()+speedDescription()+fillDescription()+multiplyDescription() - return descriptionExtension - -def carveDescription(): - """ - Dunno ACT - """ - global lt - descriptionExtension = '' - pluginModule = archive.getModuleWithPath(os.path.join( skeinforge_craft.getPluginsDirectoryPath(), 'carve' )) - prefs = settings.getReadRepository(pluginModule.getNewRepository()).preferences - for pref in prefs: - if pref.name == 'Layer Thickness (mm):': - lt = pref.value - descriptionExtension += str(pref.value).replace('.','')+'h' - if pref.name == 'Perimeter Width over Thickness (ratio):': - pwot = pref.value - descriptionExtension += 'x' + str(lt * pwot).replace('.','') + 'w' - return descriptionExtension - -def speedDescription(): - """ - ACT - """ - global feedrate, flowrate - descriptionExtension = '_' - pluginModule = archive.getModuleWithPath(os.path.join( skeinforge_craft.getPluginsDirectoryPath(), 'speed' )) - prefs = settings.getReadRepository(pluginModule.getNewRepository()).preferences - for pref in prefs: - if pref.name == 'Activate Speed:' and pref.value == False: - return '' - if pref.name == 'Feed Rate (mm/s):': - feedrate = pref.value - if pref.name == 'Flow Rate Setting (float):': - flowrate = pref.value - if feedrate == flowrate: - descriptionExtension += str(feedrate).replace('.0','')+'Ff' - else : - descriptionExtension += str(feedrate).replace('.0','')+'F'+str(flowrate).replace('.0','')+'f' - return descriptionExtension - -def fillDescription(): - """ - Infill ACT - """ - descriptionExtension = '_' - pluginModule = archive.getModuleWithPath(os.path.join( skeinforge_craft.getPluginsDirectoryPath(), 'fill' )) - prefs = settings.getReadRepository(pluginModule.getNewRepository()).preferences - for pref in prefs: - if pref.name == 'Activate Fill:' and pref.value == False: - return '' - if pref.name == 'Infill Solidity (ratio):': - infill = pref.value - descriptionExtension += str(pref.value).replace('.','')+'fill' - return descriptionExtension - -def multiplyDescription(): - global cols, rows - descriptionExtension = '' - pluginModule = archive.getModuleWithPath(os.path.join( skeinforge_craft.getPluginsDirectoryPath(), 'multiply' )) - prefs = settings.getReadRepository(pluginModule.getNewRepository()).preferences - for pref in prefs: - if pref.name == 'Activate Multiply:' and pref.value == False: - return '' - if pref.name == 'Number of Columns (integer):': - cols = pref.value - if pref.name == 'Number of Rows (integer):': - rows = pref.value - if cols > 1 or rows > 1: - descriptionExtension ='_'+str(cols * rows).replace('.','')+'off' - return descriptionExtension - -def zipper(dir, folderName, zip_file): - """Taken from http://coreygoldberg.blogspot.com/2009/07/python-zip-directories-recursively.html""" - zip = zipfile.ZipFile(zip_file, 'w', compression=zipfile.ZIP_DEFLATED) - root_len = len(os.path.abspath(dir)) - for root, dirs, files in os.walk(dir): - archive_root = os.path.abspath(root)[root_len:] - for f in files: - fullpath = os.path.join(root, f) - archive_name = os.path.join(archive_root, f) - zip.write(fullpath, folderName+archive_name, zipfile.ZIP_DEFLATED) - zip.close() - return zip_file - -class ExportRepository: - """A class to handle the export settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.export.html', self) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Export', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Export') - self.activateExport = settings.BooleanSetting().getFromValue('Activate Export', self, True) - self.addExportSuffix = settings.BooleanSetting().getFromValue('Add _export to filename (filename_export)', self, True) - self.alsoSendOutputTo = settings.StringSetting().getFromValue('Also Send Output To:', self, '') - self.commentChoice = settings.MenuButtonDisplay().getFromName('Handling of Comments in G-Code:', self) - self.doNotDeleteComments = settings.MenuRadio().getFromMenuButtonDisplay(self.commentChoice, 'Do Not Delete Comments', self, False) - self.deleteCraftingComments = settings.MenuRadio().getFromMenuButtonDisplay(self.commentChoice, 'Delete Crafting Comments', self, False) - self.deleteAllComments = settings.MenuRadio().getFromMenuButtonDisplay(self.commentChoice, 'Delete All Comments', self, True) - exportPluginsFolderPath = archive.getAbsoluteFrozenFolderPath(__file__, 'export_plugins') - exportStaticDirectoryPath = os.path.join(exportPluginsFolderPath, 'static_plugins') - exportPluginFileNames = archive.getPluginFileNamesFromDirectoryPath(exportPluginsFolderPath) - exportStaticPluginFileNames = archive.getPluginFileNamesFromDirectoryPath(exportStaticDirectoryPath) - settings.LabelDisplay().getFromName(' ', self) - self.exportLabel = settings.LabelDisplay().getFromName('--Export Operations-- ', self) - self.exportPlugins = [] - exportLatentStringVar = settings.LatentStringVar() - self.doNotChangeOutput = settings.RadioCapitalized().getFromRadio(exportLatentStringVar, 'Do Not Change Output', self, True) - self.doNotChangeOutput.directoryPath = None - allExportPluginFileNames = exportPluginFileNames + exportStaticPluginFileNames - for exportPluginFileName in allExportPluginFileNames: - exportPlugin = None - if exportPluginFileName in exportPluginFileNames: - path = os.path.join(exportPluginsFolderPath, exportPluginFileName) - exportPlugin = settings.RadioCapitalizedButton().getFromPath(exportLatentStringVar, exportPluginFileName, path, self, False) - exportPlugin.directoryPath = exportPluginsFolderPath - else: - exportPlugin = settings.RadioCapitalized().getFromRadio(exportLatentStringVar, exportPluginFileName, self, False) - exportPlugin.directoryPath = exportStaticDirectoryPath - self.exportPlugins.append(exportPlugin) - self.fileExtension = settings.StringSetting().getFromValue('File Extension (gcode):', self, 'gcode') - self.nameOfReplaceFile = settings.StringSetting().getFromValue('Name of Replace File:', self, 'replace.csv') - self.savePenultimateGcode = settings.BooleanSetting().getFromValue('Save Penultimate Gcode', self, False) - settings.LabelDisplay().getFromName(' ', self) - settings.LabelDisplay().getFromName('--Profile Sharing and Archiving--', self) - self.archiveProfile = settings.BooleanSetting().getFromValue('Archive Used Profile As Zip', self, False) - self.exportProfileAsCsv = settings.BooleanSetting().getFromValue('Export Profile Values As CSV File', self, False) - settings.LabelDisplay().getFromName(' ', self) - settings.LabelDisplay().getFromName('--File Name Alterations--', self) - settings.LabelDisplay().getFromName('"WARNING" IF ANY OF BELOW CHECKBOXES ARE CHECKED', self) - settings.LabelDisplay().getFromName('SFACT WILL NOT WORK FROM WITHIN PRONTERFACE!!', self) - self.profileFileExtension = settings.BooleanSetting().getFromValue('Add Profile Name to Filename', self, False) - self.descriptiveExtension = settings.BooleanSetting().getFromValue('Add Description to Filename', self, False) - self.timestampExtension = settings.BooleanSetting().getFromValue('Add Timestamp to Filename', self, False) - self.executeTitle = 'Export' - - def execute(self): - """Export button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class ExportSkein: - """A class to export a skein of extrusions.""" - def __init__(self): - self.crafting = False - self.decimalPlacesExported = 2 - self.output = cStringIO.StringIO() - - def addLine(self, line): - """Add a line of text and a newline to the output.""" - if line != '': - self.output.write(line + '\n') - - def getCraftedGcode( self, repository, gcodeText ): - """Parse gcode text and store the export gcode.""" - self.repository = repository - lines = archive.getTextLines(gcodeText) - for line in lines: - self.parseLine(line) - return self.output.getvalue() - - def getLineWithTruncatedNumber(self, character, line, splitLine): - """Get a line with the number after the character truncated.""" - numberString = gcodec.getStringFromCharacterSplitLine(character, splitLine) - if numberString is None: - return line - roundedNumberString = euclidean.getRoundedToPlacesString(self.decimalPlacesExported, float(numberString)) - return gcodec.getLineWithValueString(character, line, splitLine, roundedNumberString) - - def parseLine(self, line): - """Parse a gcode line.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == '()': - self.crafting = False - elif firstWord == '(': - self.decimalPlacesExported = int(splitLine[1]) - 1 - if self.repository.deleteAllComments.value or (self.repository.deleteCraftingComments.value and self.crafting): - if firstWord[0] == '(': - return - else: - line = line.split(';')[0].split('(')[0].strip() - if firstWord == '()': - self.crafting = True - if firstWord == '()': - self.addLine('( export )') - if firstWord != 'G1' and firstWord != 'G2' and firstWord != 'G3' : - self.addLine(line) - return - line = self.getLineWithTruncatedNumber('X', line, splitLine) - line = self.getLineWithTruncatedNumber('Y', line, splitLine) - line = self.getLineWithTruncatedNumber('Z', line, splitLine) - line = self.getLineWithTruncatedNumber('I', line, splitLine) - line = self.getLineWithTruncatedNumber('J', line, splitLine) - line = self.getLineWithTruncatedNumber('R', line, splitLine) - self.addLine(line) - -class Condenser: - def readSettings(self): - self.output = cStringIO.StringIO() - profileDirectory = skeinforge_profile.getProfileDirectory() - craftRepo = skeinforge_craft.CraftRepository() - profileBaseName = settings.getProfileBaseName( craftRepo ) - allCraftNames = archive.getPluginFileNamesFromDirectoryPath( skeinforge_craft.getPluginsDirectoryPath() ) - - fullProfilePath = os.path.join( archive.getSettingsPath() , 'profiles' ) - fullProfileDirectory = os.path.join( fullProfilePath , profileDirectory ) - - for craftName in allCraftNames: - pluginModule = archive.getModuleWithPath(os.path.join( skeinforge_craft.getPluginsDirectoryPath(), craftName )) - - repo = pluginModule.getNewRepository() - self.outputSettings(craftName, settings.getReadRepository(repo).preferences) - - return self.output.getvalue() - - def addLine(self, line): - """Add a line of text and a newline to the output.""" - self.output.write(line + '\n') - - def outputSettings(self, craftName, settings): - for setting in settings: - if hasattr(setting, 'value') and setting.name != 'WindowPosition' and not setting.name.startswith('Open File') : - self.outputSetting(craftName, setting) - - def outputSetting(self, craftName, setting): - self.addLine(craftName + ',' + setting.name + ',' + str(setting.value)) - -def main(): - """Display the export dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/export_plugins/__init__.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/export_plugins/__init__.py deleted file mode 100644 index 58ec332..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/export_plugins/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 4 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/export_plugins/export_plugins.zip b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/export_plugins/export_plugins.zip deleted file mode 100644 index fe8c0f5..0000000 Binary files a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/export_plugins/export_plugins.zip and /dev/null differ diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/export_plugins/static_plugins/__init__.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/export_plugins/static_plugins/__init__.py deleted file mode 100644 index b83e941..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/export_plugins/static_plugins/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 5 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/export_plugins/static_plugins/gcode_small.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/export_plugins/static_plugins/gcode_small.py deleted file mode 100644 index b7494c9..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/export_plugins/static_plugins/gcode_small.py +++ /dev/null @@ -1,110 +0,0 @@ -""" -This page is in the table of contents. -Gcode_small is an export plugin to remove the comments and the redundant z and feed rate parameters from a gcode file. - -An export plugin is a script in the export_plugins folder which has the getOutput function, the globalIsReplaceable variable and if it's output is not replaceable, the writeOutput function. It is meant to be run from the export tool. To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name. - -The getOutput function of this script takes a gcode text and returns that text without comments and redundant z and feed rate parameters. The writeOutput function of this script takes a gcode text and writes that text without comments and redundant z and feed rate parameters to a file. - -Many of the functions in this script are copied from gcodec in skeinforge_utilities. They are copied rather than imported so developers making new plugins do not have to learn about gcodec, the code here is all they need to learn. - -""" - -from __future__ import absolute_import -import cStringIO -import os - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -# This is true if the output is text and false if it is binary." -globalIsReplaceable = True - - -def getOutput(gcodeText): - """Get the exported version of a gcode file.""" - return GcodeSmallSkein().getCraftedGcode(gcodeText) - -def getSplitLineBeforeBracketSemicolon(line): - """Get the split line before a bracket or semicolon.""" - bracketSemicolonIndex = min( line.find(';'), line.find('(') ) - if bracketSemicolonIndex < 0: - return line.split() - return line[ : bracketSemicolonIndex ].split() - -def getStringFromCharacterSplitLine(character, splitLine): - """Get the string after the first occurence of the character in the split line.""" - indexOfCharacter = getIndexOfStartingWithSecond(character, splitLine) - if indexOfCharacter < 0: - return None - return splitLine[indexOfCharacter][1 :] - -def getSummarizedFileName(fileName): - """Get the fileName basename if the file is in the current working directory, otherwise return the original full name.""" - if os.getcwd() == os.path.dirname(fileName): - return os.path.basename(fileName) - return fileName - -def getTextLines(text): - """Get the all the lines of text of a text.""" - return text.replace('\r', '\n').split('\n') - -def getIndexOfStartingWithSecond(letter, splitLine): - """Get index of the first occurence of the given letter in the split line, starting with the second word. Return - 1 if letter is not found""" - for wordIndex in xrange( 1, len(splitLine) ): - word = splitLine[ wordIndex ] - firstLetter = word[0] - if firstLetter == letter: - return wordIndex - return - 1 - - -class GcodeSmallSkein: - """A class to remove redundant z and feed rate parameters from a skein of extrusions.""" - def __init__(self): - self.lastFeedRateString = None - self.lastZString = None - self.output = cStringIO.StringIO() - - def getCraftedGcode( self, gcodeText ): - """Parse gcode text and store the gcode.""" - lines = getTextLines(gcodeText) - for line in lines: - self.parseLine(line) - return self.output.getvalue() - - def parseLine(self, line): - """Parse a gcode line.""" - splitLine = getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if len(firstWord) < 1: - return - if firstWord[0] == '(': - return - if firstWord != 'G1': - self.output.write(line + '\n') - return - eString = getStringFromCharacterSplitLine('E', splitLine ) - xString = getStringFromCharacterSplitLine('X', splitLine ) - yString = getStringFromCharacterSplitLine('Y', splitLine ) - zString = getStringFromCharacterSplitLine('Z', splitLine ) - feedRateString = getStringFromCharacterSplitLine('F', splitLine ) - self.output.write('G1') - if xString is not None: - self.output.write(' X' + xString ) - if yString is not None: - self.output.write(' Y' + yString ) - if zString is not None and zString != self.lastZString: - self.output.write(' Z' + zString ) - if feedRateString is not None and feedRateString != self.lastFeedRateString: - self.output.write(' F' + feedRateString ) - if eString is not None: - self.output.write(' E' + eString ) - self.lastFeedRateString = feedRateString - self.lastZString = zString - self.output.write('\n') diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/fill.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/fill.py deleted file mode 100644 index 3529165..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/fill.py +++ /dev/null @@ -1,1456 +0,0 @@ -#! /usr/bin/env python -""" -This page is in the table of contents. -Fill is a script to fill the perimeters of a gcode file. - -The fill manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Fill - -Allan Ecker aka The Masked Retriever has written the "Skeinforge Quicktip: Fill" at: -http://blog.thingiverse.com/2009/07/21/mysteries-of-skeinforge-fill/ - -==Operation== -The default 'Activate Fill' checkbox is off. -When it is on, the functions described below will work, when it is off, -the functions will not be called. - -==Settings== -===Diaphragm=== -The diaphragm is a solid group of layers, at regular intervals. -It can be used with a sparse infill to give the object watertight, -horizontal compartments and/or a higher shear strength. - -====Diaphragm Period==== -Default is one hundred. - -Defines the number of layers between diaphrams. - -====Diaphragm Thickness==== -Default is zero, because the diaphragm feature is rarely used. - -Defines the number of layers the diaphram is composed of. - -===Extra Shells=== -The shells interior perimeter loops. Adding extra shells makes the object stronger -& heavier. - -====Extra Shells on Alternating Solid Layers==== -Default is two. - -Defines the number of extra shells, on the alternating solid layers. - -====Extra Shells on Base==== -Default is one. - -Defines the number of extra shells on the bottom, base layer -and every even solid layer after that. Setting this to a different -value than the "Extra Shells on Alternating Solid Layers" means the -infill pattern will alternate, creating a strong interleaved bond even -if the perimeter loop shrinks. - -====Extra Shells on Sparse Layer==== -Default is one. - -Defines the number of extra shells on the sparse layers. -The solid layers are those at the top & bottom, and wherever the object -has a plateau or overhang, the sparse layers are the layers in between. - -===Grid=== -====Grid Circle Separation over Perimeter Width==== -Default is 0.2. - -Defines the ratio of the amount the grid circle is inset over the perimeter width, -the default is zero. With a value of zero the circles will touch, -with a value of one two threads could be fitted between the circles. - -====Grid Extra Overlap==== -Default is 0.1. - -Defines the amount of extra overlap added when extruding the grid to -compensate for the fact that when the first thread going through a grid point -is extruded, since there is nothing there yet for it to connect to it -will shrink extra. - -====Grid Junction Separation over Octogon Radius At End==== -Default is zero. - -Defines the ratio of the amount the grid square is increased in each direction -over the extrusion width at the end. With a value of one or so the grid pattern -will have large squares to go with the octogons. - -====Grid Junction Separation over Octogon Radius At Middle==== -Default is zero. - -Defines the increase at the middle. If this value is different than the -value at the end, the grid would have an accordion pattern, which would give it -a higher shear strength. - -====Grid Junction Separation Band Height==== -Default is ten. - -Defines the height of the bands of the accordion pattern. - -===Infill=== -====Infill Pattern==== -Default is 'Line', since it is quicker to generate and does not add extra movements for the extruder. The grid pattern has extra diagonal lines, so when choosing a grid option, set the infill solidity to 0.2 or less so that there is not too much plastic and the grid generation time, which increases with the third power of solidity, will be reasonable. - -=====Grid Circular===== -When selected, the infill will be a grid of separated circles. -Because the circles are separated, the pattern is weak, -it only provides support for the top layer threads and some -strength in the z direction. The flip side is that this infill -does not warp the object, the object will get warped only by the walls. - -Because this pattern turns the extruder on and off often, -it is best to use a stepper motor extruder. - -=====Grid Hexagonal===== -When selected, the infill will be a hexagonal grid. -Because the grid is made with threads rather than with molding or milling, -only a partial hexagon is possible, so the rectangular grid pattern is stronger. - -=====Grid Rectangular===== -When selected, the infill will be a funky octogon square honeycomb -like pattern which gives the object extra strength. - -=====Line===== -When selected, the infill will be made up of lines. - -====Infill Begin Rotation==== -Default is forty five degrees, giving a diagonal infill. - -Defines the amount the infill direction of the base and every second layer -thereafter is rotated. - -====Infill Odd Layer Extra Rotation==== -Default is ninety degrees, making the odd layer infill perpendicular to the -base layer. - -Defines the extra amount the infill direction of the odd layers is rotated -compared to the base layer. - -====Infill Begin Rotation Repeat==== -Default is one, giving alternating cross hatching. - -Defines the number of layers that the infill begin rotation will repeat. With a value higher than one, the infill will go in one direction more often, giving the object more strength in one direction and less in the other, this is useful for beams and cantilevers. - -====Infill Perimeter Overlap==== -Default is 0.15. - -Defines the amount the infill overlaps the perimeter over the average of the -perimeter and infill width. The higher the value the more the infill will -overlap the perimeter, and the thicker join between the infill and the perimeter. -If the value is too high, the join will be so thick that the nozzle will run plow -through the join below making a mess, also when it is above 0.45 fill may not be -able to create infill correctly. If you want to stretch the infill a lot, -set 'Path Stretch over Perimeter Width' in stretch to a high value. - -====Infill Solidity==== -Default is 0.2. - -Defines the solidity of the infill, this is the most important setting in fill. -A value of one means the infill lines will be right beside each other, -resulting in a solid, strong, heavy shape which takes a long time to extrude. -A low value means the infill will be sparse, the interior will be mosty -empty space, the object will be weak, light and quick to build. - -====Infill Width over Thickness==== -Default is 1.5. - -Defines the ratio of the infill width over the layer thickness. -The higher the value the wider apart the infill will be and therefore -the sparser the infill will be. - -===Solid Surface Thickness=== -Default is three. - -Defines the number of solid layers that are at the bottom, top, -plateaus and overhang. With a value of zero, the entire object will be -composed of a sparse infill, and water could flow right through it. -With a value of one, water will leak slowly through the surface and with -a value of three, the object could be watertight. The higher the -solid surface thickness, the stronger and heavier the object will be. - -===Start From Choice=== -Default is 'Lower Left'. - -Defines where each layer starts from. - -====Lower Left==== -When selected the layer will start from the lower left corner. This is to extrude in round robin fashion so that the first extrusion will be deposited on the coolest part of the last layer. The reason for this is described at: -http://hydraraptor.blogspot.com/2010/12/round-robin.html - -====Nearest==== -When selected the layer will start from the nearest point to the end of the last layer. This leads to less stringing, but the first extrusion will be deposited on the hottest part of the last layer which leads to melting problems. So this option is deprecated, eventually this option will be removed and the layers will always start from the lower left. - -===Thread Sequence Choice=== -The 'Thread Sequence Choice' is the sequence in which the threads will be extruded on the second and higher layers. There are three kinds of thread, the perimeter threads on the outside of the object, the loop threads aka inner shell threads, and the interior infill threads. The first layer thread sequence is 'Perimeter > Loops > Infill'. - -The default choice is 'Perimeter > Loops > Infill', which the default stretch parameters are based on. If you change from the default sequence choice setting of perimeter, then loops, then infill, the optimal stretch thread parameters would also be different. In general, if the infill is extruded first, the infill would have to be stretched more so that even after the filament shrinkage, it would still be long enough to connect to the loop or perimeter. The six sequence combinations follow below. - -====Infill > Loops > Perimeter==== -====Infill > Perimeter > Loops==== -====Loops > Infill > Perimeter==== -====Loops > Perimeter > Infill==== -====Perimeter > Infill > Loops==== -====Perimeter > Loops > Infill==== - -==Examples== -The following examples fill the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and fill.py. - -> python fill.py -This brings up the fill dialog. - -> python fill.py Screw Holder Bottom.stl -The fill tool is parsing the file: -Screw Holder Bottom.stl -.. -The fill tool has created the file: -.. Screw Holder Bottom_fill.gcode - -""" - -from __future__ import absolute_import -try: - import psyco - psyco.full() -except: - pass -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/28/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - - -def addAroundGridPoint( arounds, gridPoint, gridPointInsetX, gridPointInsetY, gridPoints, isBothOrNone, isDoubleJunction, isJunctionWide, paths, pixelTable, width ): - """Add the path around the grid point.""" - closestPathIndex = None - aroundIntersectionPaths = [] - for aroundIndex in xrange( len(arounds) ): - loop = arounds[ aroundIndex ] - for pointIndex in xrange(len(loop)): - pointFirst = loop[pointIndex] - pointSecond = loop[(pointIndex + 1) % len(loop)] - yIntersection = euclidean.getYIntersectionIfExists( pointFirst, pointSecond, gridPoint.real ) - addYIntersectionPathToList( aroundIndex, pointIndex, gridPoint.imag, yIntersection, aroundIntersectionPaths ) - if len( aroundIntersectionPaths ) < 2: - print('This should never happen, aroundIntersectionPaths is less than 2 in fill.') - print( aroundIntersectionPaths ) - print( gridPoint ) - return - yCloseToCenterArounds = getClosestOppositeIntersectionPaths( aroundIntersectionPaths ) - if len( yCloseToCenterArounds ) < 2: -# This used to be worth the warning below. -# print('This should never happen, yCloseToCenterArounds is less than 2 in fill.') -# print( gridPoint ) -# print( len( yCloseToCenterArounds ) ) - return - segmentFirstY = min( yCloseToCenterArounds[0].y, yCloseToCenterArounds[1].y ) - segmentSecondY = max( yCloseToCenterArounds[0].y, yCloseToCenterArounds[1].y ) - yIntersectionPaths = [] - gridPixel = euclidean.getStepKeyFromPoint( gridPoint / width ) - segmentFirstPixel = euclidean.getStepKeyFromPoint( complex( gridPoint.real, segmentFirstY ) / width ) - segmentSecondPixel = euclidean.getStepKeyFromPoint( complex( gridPoint.real, segmentSecondY ) / width ) - pathIndexTable = {} - addPathIndexFirstSegment( gridPixel, pathIndexTable, pixelTable, segmentFirstPixel ) - addPathIndexSecondSegment( gridPixel, pathIndexTable, pixelTable, segmentSecondPixel ) - for pathIndex in pathIndexTable.keys(): - path = paths[ pathIndex ] - for pointIndex in xrange( len(path) - 1 ): - pointFirst = path[ pointIndex ] - pointSecond = path[ pointIndex + 1 ] - yIntersection = getYIntersectionInsideYSegment( segmentFirstY, segmentSecondY, pointFirst, pointSecond, gridPoint.real ) - addYIntersectionPathToList( pathIndex, pointIndex, gridPoint.imag, yIntersection, yIntersectionPaths ) - if len( yIntersectionPaths ) < 1: - return - yCloseToCenterPaths = [] - if isDoubleJunction: - yCloseToCenterPaths = getClosestOppositeIntersectionPaths( yIntersectionPaths ) - else: - yIntersectionPaths.sort( compareDistanceFromCenter ) - yCloseToCenterPaths = [ yIntersectionPaths[0] ] - for yCloseToCenterPath in yCloseToCenterPaths: - setIsOutside( yCloseToCenterPath, aroundIntersectionPaths ) - if len( yCloseToCenterPaths ) < 2: - yCloseToCenterPaths[0].gridPoint = gridPoint - insertGridPointPair( gridPoint, gridPointInsetX, gridPoints, isJunctionWide, paths, pixelTable, yCloseToCenterPaths[0], width ) - return - plusMinusSign = getPlusMinusSign( yCloseToCenterPaths[1].y - yCloseToCenterPaths[0].y ) - yCloseToCenterPaths[0].gridPoint = complex( gridPoint.real, gridPoint.imag - plusMinusSign * gridPointInsetY ) - yCloseToCenterPaths[1].gridPoint = complex( gridPoint.real, gridPoint.imag + plusMinusSign * gridPointInsetY ) - yCloseToCenterPaths.sort( comparePointIndexDescending ) - insertGridPointPairs( gridPoint, gridPointInsetX, gridPoints, yCloseToCenterPaths[0], yCloseToCenterPaths[1], isBothOrNone, isJunctionWide, paths, pixelTable, width ) - -def addLoop(infillWidth, infillPaths, loop, rotationPlaneAngle): - """Add simplified path to fill.""" - simplifiedLoop = euclidean.getSimplifiedLoop(loop, infillWidth) - if len(simplifiedLoop) < 2: - return - simplifiedLoop.append(simplifiedLoop[0]) - planeRotated = euclidean.getPointsRoundZAxis(rotationPlaneAngle, simplifiedLoop) - infillPaths.append(planeRotated) - -def addPath(infillWidth, infillPaths, path, rotationPlaneAngle): - """Add simplified path to fill.""" - simplifiedPath = euclidean.getSimplifiedPath(path, infillWidth) - if len(simplifiedPath) < 2: - return - planeRotated = euclidean.getPointsRoundZAxis(rotationPlaneAngle, simplifiedPath) - infillPaths.append(planeRotated) - -def addPathIndexFirstSegment( gridPixel, pathIndexTable, pixelTable, segmentFirstPixel ): - """Add the path index of the closest segment found toward the second segment.""" - for yStep in xrange( gridPixel[1], segmentFirstPixel[1] - 1, - 1 ): - if getKeyIsInPixelTableAddValue( ( gridPixel[0], yStep ), pathIndexTable, pixelTable ): - return - -def addPathIndexSecondSegment( gridPixel, pathIndexTable, pixelTable, segmentSecondPixel ): - """Add the path index of the closest segment found toward the second segment.""" - for yStep in xrange( gridPixel[1], segmentSecondPixel[1] + 1 ): - if getKeyIsInPixelTableAddValue( ( gridPixel[0], yStep ), pathIndexTable, pixelTable ): - return - -def addPointOnPath( path, pathIndex, pixelTable, point, pointIndex, width ): - """Add a point to a path and the pixel table.""" - pointIndexMinusOne = pointIndex - 1 - if pointIndex < len(path) and pointIndexMinusOne >= 0: - segmentTable = {} - begin = path[ pointIndexMinusOne ] - end = path[ pointIndex ] - euclidean.addValueSegmentToPixelTable( begin, end, segmentTable, pathIndex, width ) - euclidean.removePixelTableFromPixelTable( segmentTable, pixelTable ) - if pointIndexMinusOne >= 0: - begin = path[ pointIndexMinusOne ] - euclidean.addValueSegmentToPixelTable( begin, point, pixelTable, pathIndex, width ) - if pointIndex < len(path): - end = path[ pointIndex ] - euclidean.addValueSegmentToPixelTable( point, end, pixelTable, pathIndex, width ) - path.insert( pointIndex, point ) - -def addPointOnPathIfFree( path, pathIndex, pixelTable, point, pointIndex, width ): - """Add the closest point to a path, if the point added to a path is free.""" - if isAddedPointOnPathFree( path, pixelTable, point, pointIndex, width ): - addPointOnPath( path, pathIndex, pixelTable, point, pointIndex, width ) - -def addSparseEndpoints( doubleExtrusionWidth, endpoints, fillLine, horizontalSegmentLists, infillSolidity, removedEndpoints, solidSurfaceThickness, surroundingXIntersections ): - """Add sparse endpoints.""" - horizontalEndpoints = horizontalSegmentLists[fillLine] - for segment in horizontalEndpoints: - addSparseEndpointsFromSegment( doubleExtrusionWidth, endpoints, fillLine, horizontalSegmentLists, infillSolidity, removedEndpoints, segment, solidSurfaceThickness, surroundingXIntersections ) - -def addSparseEndpointsFromSegment( doubleExtrusionWidth, endpoints, fillLine, horizontalSegmentLists, infillSolidity, removedEndpoints, segment, solidSurfaceThickness, surroundingXIntersections ): - """Add sparse endpoints from a segment.""" - endpointFirstPoint = segment[0].point - endpointSecondPoint = segment[1].point - if surroundingXIntersections is None: - endpoints += segment - return - if infillSolidity > 0.0: - if fillLine < 1 or fillLine >= len( horizontalSegmentLists ) - 1: - endpoints += segment - return - if int( round( round( fillLine * infillSolidity ) / infillSolidity ) ) == fillLine: - endpoints += segment - return - if abs( endpointFirstPoint - endpointSecondPoint ) < doubleExtrusionWidth: - endpoints += segment - return - if not isSegmentAround( horizontalSegmentLists[ fillLine - 1 ], segment ): - endpoints += segment - return - if not isSegmentAround( horizontalSegmentLists[ fillLine + 1 ], segment ): - endpoints += segment - return - if not solidSurfaceThickness: - removedEndpoints += segment - return - if isSegmentCompletelyInAnIntersection( segment, surroundingXIntersections ): - removedEndpoints += segment - return - endpoints += segment - -def addYIntersectionPathToList( pathIndex, pointIndex, y, yIntersection, yIntersectionPaths ): - """Add the y intersection path to the y intersection paths.""" - if yIntersection is None: - return - yIntersectionPath = YIntersectionPath( pathIndex, pointIndex, yIntersection ) - yIntersectionPath.yMinusCenter = yIntersection - y - yIntersectionPaths.append( yIntersectionPath ) - -def compareDistanceFromCenter(self, other): - """Get comparison in order to sort y intersections in ascending order of distance from the center.""" - distanceFromCenter = abs( self.yMinusCenter ) - distanceFromCenterOther = abs( other.yMinusCenter ) - if distanceFromCenter > distanceFromCenterOther: - return 1 - if distanceFromCenter < distanceFromCenterOther: - return - 1 - return 0 - -def comparePointIndexDescending(self, other): - """Get comparison in order to sort y intersections in descending order of point index.""" - if self.pointIndex > other.pointIndex: - return - 1 - if self.pointIndex < other.pointIndex: - return 1 - return 0 - -def createExtraFillLoops(nestedRing, radius, shouldExtraLoopsBeAdded): - """Create extra fill loops.""" - for innerNestedRing in nestedRing.innerNestedRings: - createFillForSurroundings(innerNestedRing.innerNestedRings, radius, shouldExtraLoopsBeAdded) - allFillLoops = getExtraFillLoops(nestedRing.getLoopsToBeFilled(), radius) - if len(allFillLoops) < 1: - return - if shouldExtraLoopsBeAdded: - nestedRing.extraLoops += allFillLoops - nestedRing.penultimateFillLoops = nestedRing.lastFillLoops - nestedRing.lastFillLoops = allFillLoops - -def createFillForSurroundings(nestedRings, radius, shouldExtraLoopsBeAdded): - """Create extra fill loops for surrounding loops.""" - for nestedRing in nestedRings: - createExtraFillLoops(nestedRing, radius, shouldExtraLoopsBeAdded) - -def getAdditionalLength( path, point, pointIndex ): - """Get the additional length added by inserting a point into a path.""" - if not pointIndex: - return abs( point - path[0] ) - if pointIndex == len(path): - return abs( point - path[-1] ) - return abs( point - path[ pointIndex - 1 ] ) + abs( point - path[ pointIndex ] ) - abs( path[ pointIndex ] - path[ pointIndex - 1 ] ) - -def getCraftedText( fileName, gcodeText = '', repository=None): - """Fill the inset file or gcode text.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, gcodeText), repository ) - -def getCraftedTextFromText(gcodeText, repository=None): - """Fill the inset gcode text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'fill'): - return gcodeText - if repository is None: - repository = settings.getReadRepository( FillRepository() ) - if not repository.activateFill.value: - return gcodeText - return FillSkein().getCraftedGcode( repository, gcodeText ) - -def getClosestOppositeIntersectionPaths( yIntersectionPaths ): - """Get the close to center paths, starting with the first and an additional opposite if it exists.""" - yIntersectionPaths.sort( compareDistanceFromCenter ) - beforeFirst = yIntersectionPaths[0].yMinusCenter < 0.0 - yCloseToCenterPaths = [ yIntersectionPaths[0] ] - for yIntersectionPath in yIntersectionPaths[1 :]: - beforeSecond = yIntersectionPath.yMinusCenter < 0.0 - if beforeFirst != beforeSecond: - yCloseToCenterPaths.append( yIntersectionPath ) - return yCloseToCenterPaths - return yCloseToCenterPaths - -def getExtraFillLoops(loops, radius): - """Get extra loops between inside and outside loops.""" - greaterThanRadius = 1.4 * radius - extraFillLoops = [] - centers = intercircle.getCentersFromPoints(intercircle.getPointsFromLoops(loops, greaterThanRadius), greaterThanRadius) - for center in centers: - inset = intercircle.getSimplifiedInsetFromClockwiseLoop(center, radius) - if intercircle.isLargeSameDirection(inset, center, radius): - if euclidean.getIsInFilledRegion(loops, euclidean.getLeftPoint(inset)): - inset.reverse() - extraFillLoops.append(inset) - return extraFillLoops - -def getKeyIsInPixelTableAddValue( key, pathIndexTable, pixelTable ): - """Determine if the key is in the pixel table, and if it is and if the value is not None add it to the path index table.""" - if key in pixelTable: - value = pixelTable[key] - if value is not None: - pathIndexTable[value] = None - return True - return False - -def getLowerLeftCorner(nestedRings): - """Get the lower left corner from the nestedRings.""" - lowerLeftCorner = Vector3() - lowestRealPlusImaginary = 987654321.0 - for nestedRing in nestedRings: - for point in nestedRing.boundary: - realPlusImaginary = point.real + point.imag - if realPlusImaginary < lowestRealPlusImaginary: - lowestRealPlusImaginary = realPlusImaginary - lowerLeftCorner.setToXYZ(point.real, point.imag, nestedRing.z) - return lowerLeftCorner - -def getNonIntersectingGridPointLine( gridPointInsetX, isJunctionWide, paths, pixelTable, yIntersectionPath, width ): - """Get the points around the grid point that is junction wide that do not intersect.""" - pointIndexPlusOne = yIntersectionPath.getPointIndexPlusOne() - path = yIntersectionPath.getPath(paths) - begin = path[ yIntersectionPath.pointIndex ] - end = path[ pointIndexPlusOne ] - plusMinusSign = getPlusMinusSign( end.real - begin.real ) - if isJunctionWide: - gridPointXFirst = complex( yIntersectionPath.gridPoint.real - plusMinusSign * gridPointInsetX, yIntersectionPath.gridPoint.imag ) - gridPointXSecond = complex( yIntersectionPath.gridPoint.real + plusMinusSign * gridPointInsetX, yIntersectionPath.gridPoint.imag ) - if isAddedPointOnPathFree( path, pixelTable, gridPointXSecond, pointIndexPlusOne, width ): - if isAddedPointOnPathFree( path, pixelTable, gridPointXFirst, pointIndexPlusOne, width ): - return [ gridPointXSecond, gridPointXFirst ] - if isAddedPointOnPathFree( path, pixelTable, yIntersectionPath.gridPoint, pointIndexPlusOne, width ): - return [ gridPointXSecond, yIntersectionPath.gridPoint ] - return [ gridPointXSecond ] - if isAddedPointOnPathFree( path, pixelTable, yIntersectionPath.gridPoint, pointIndexPlusOne, width ): - return [ yIntersectionPath.gridPoint ] - return [] - -def getPlusMinusSign(number): - """Get one if the number is zero or positive else negative one.""" - if number >= 0.0: - return 1.0 - return - 1.0 - -def getNewRepository(): - """Get new repository.""" - return FillRepository() - -def getWithLeastLength( path, point ): - """Insert a point into a path, at the index at which the path would be shortest.""" - if len(path) < 1: - return 0 - shortestPointIndex = None - shortestAdditionalLength = 999999999987654321.0 - for pointIndex in xrange( len(path) + 1 ): - additionalLength = getAdditionalLength( path, point, pointIndex ) - if additionalLength < shortestAdditionalLength: - shortestAdditionalLength = additionalLength - shortestPointIndex = pointIndex - return shortestPointIndex - -def getYIntersectionInsideYSegment( segmentFirstY, segmentSecondY, beginComplex, endComplex, x ): - """Get the y intersection inside the y segment if it does, else none.""" - yIntersection = euclidean.getYIntersectionIfExists( beginComplex, endComplex, x ) - if yIntersection is None: - return None - if yIntersection < min( segmentFirstY, segmentSecondY ): - return None - if yIntersection <= max( segmentFirstY, segmentSecondY ): - return yIntersection - return None - -def insertGridPointPair( gridPoint, gridPointInsetX, gridPoints, isJunctionWide, paths, pixelTable, yIntersectionPath, width ): - """Insert a pair of points around the grid point is is junction wide, otherwise inset one point.""" - linePath = getNonIntersectingGridPointLine( gridPointInsetX, isJunctionWide, paths, pixelTable, yIntersectionPath, width ) - insertGridPointPairWithLinePath( gridPoint, gridPointInsetX, gridPoints, isJunctionWide, linePath, paths, pixelTable, yIntersectionPath, width ) - -def insertGridPointPairs( gridPoint, gridPointInsetX, gridPoints, intersectionPathFirst, intersectionPathSecond, isBothOrNone, isJunctionWide, paths, pixelTable, width ): - """Insert a pair of points around a pair of grid points.""" - gridPointLineFirst = getNonIntersectingGridPointLine( gridPointInsetX, isJunctionWide, paths, pixelTable, intersectionPathFirst, width ) - if len( gridPointLineFirst ) < 1: - if isBothOrNone: - return - intersectionPathSecond.gridPoint = gridPoint - insertGridPointPair( gridPoint, gridPointInsetX, gridPoints, isJunctionWide, paths, pixelTable, intersectionPathSecond, width ) - return - gridPointLineSecond = getNonIntersectingGridPointLine( gridPointInsetX, isJunctionWide, paths, pixelTable, intersectionPathSecond, width ) - if len( gridPointLineSecond ) > 0: - insertGridPointPairWithLinePath( gridPoint, gridPointInsetX, gridPoints, isJunctionWide, gridPointLineFirst, paths, pixelTable, intersectionPathFirst, width ) - insertGridPointPairWithLinePath( gridPoint, gridPointInsetX, gridPoints, isJunctionWide, gridPointLineSecond, paths, pixelTable, intersectionPathSecond, width ) - return - if isBothOrNone: - return - originalGridPointFirst = intersectionPathFirst.gridPoint - intersectionPathFirst.gridPoint = gridPoint - gridPointLineFirstCenter = getNonIntersectingGridPointLine( gridPointInsetX, isJunctionWide, paths, pixelTable, intersectionPathFirst, width ) - if len( gridPointLineFirstCenter ) > 0: - insertGridPointPairWithLinePath( gridPoint, gridPointInsetX, gridPoints, isJunctionWide, gridPointLineFirstCenter, paths, pixelTable, intersectionPathFirst, width ) - return - intersectionPathFirst.gridPoint = originalGridPointFirst - insertGridPointPairWithLinePath( gridPoint, gridPointInsetX, gridPoints, isJunctionWide, gridPointLineFirst, paths, pixelTable, intersectionPathFirst, width ) - -def insertGridPointPairWithLinePath( gridPoint, gridPointInsetX, gridPoints, isJunctionWide, linePath, paths, pixelTable, yIntersectionPath, width ): - """Insert a pair of points around the grid point is is junction wide, otherwise inset one point.""" - if len( linePath ) < 1: - return - if gridPoint in gridPoints: - gridPoints.remove( gridPoint ) - intersectionBeginPoint = None - moreThanInset = 2.1 * gridPointInsetX - path = yIntersectionPath.getPath(paths) - begin = path[ yIntersectionPath.pointIndex ] - end = path[ yIntersectionPath.getPointIndexPlusOne() ] - if yIntersectionPath.isOutside: - distanceX = end.real - begin.real - if abs( distanceX ) > 2.1 * moreThanInset: - intersectionBeginXDistance = yIntersectionPath.gridPoint.real - begin.real - endIntersectionXDistance = end.real - yIntersectionPath.gridPoint.real - intersectionPoint = begin * endIntersectionXDistance / distanceX + end * intersectionBeginXDistance / distanceX - distanceYAbsoluteInset = max( abs( yIntersectionPath.gridPoint.imag - intersectionPoint.imag ), moreThanInset ) - intersectionEndSegment = end - intersectionPoint - intersectionEndSegmentLength = abs( intersectionEndSegment ) - if intersectionEndSegmentLength > 1.1 * distanceYAbsoluteInset: - intersectionEndPoint = intersectionPoint + intersectionEndSegment * distanceYAbsoluteInset / intersectionEndSegmentLength - path.insert( yIntersectionPath.getPointIndexPlusOne(), intersectionEndPoint ) - intersectionBeginSegment = begin - intersectionPoint - intersectionBeginSegmentLength = abs( intersectionBeginSegment ) - if intersectionBeginSegmentLength > 1.1 * distanceYAbsoluteInset: - intersectionBeginPoint = intersectionPoint + intersectionBeginSegment * distanceYAbsoluteInset / intersectionBeginSegmentLength - for point in linePath: - addPointOnPath( path, yIntersectionPath.pathIndex, pixelTable, point, yIntersectionPath.getPointIndexPlusOne(), width ) - if intersectionBeginPoint is not None: - addPointOnPath( path, yIntersectionPath.pathIndex, pixelTable, intersectionBeginPoint, yIntersectionPath.getPointIndexPlusOne(), width ) - -def isAddedPointOnPathFree( path, pixelTable, point, pointIndex, width ): - """Determine if the point added to a path is intersecting the pixel table or the path.""" - if pointIndex > 0 and pointIndex < len(path): - if isSharpCorner( ( path[ pointIndex - 1 ] ), point, ( path[ pointIndex ] ) ): - return False - pointIndexMinusOne = pointIndex - 1 - if pointIndexMinusOne >= 0: - maskTable = {} - begin = path[ pointIndexMinusOne ] - if pointIndex < len(path): - end = path[ pointIndex ] - euclidean.addValueSegmentToPixelTable( begin, end, maskTable, None, width ) - segmentTable = {} - euclidean.addSegmentToPixelTable( point, begin, segmentTable, 0.0, 2.0, width ) - if euclidean.isPixelTableIntersecting( pixelTable, segmentTable, maskTable ): - return False - if isAddedPointOnPathIntersectingPath( begin, path, point, pointIndexMinusOne ): - return False - if pointIndex < len(path): - maskTable = {} - begin = path[ pointIndex ] - if pointIndexMinusOne >= 0: - end = path[ pointIndexMinusOne ] - euclidean.addValueSegmentToPixelTable( begin, end, maskTable, None, width ) - segmentTable = {} - euclidean.addSegmentToPixelTable( point, begin, segmentTable, 0.0, 2.0, width ) - if euclidean.isPixelTableIntersecting( pixelTable, segmentTable, maskTable ): - return False - if isAddedPointOnPathIntersectingPath( begin, path, point, pointIndex ): - return False - return True - -def isAddedPointOnPathIntersectingPath( begin, path, point, pointIndex ): - """Determine if the point added to a path is intersecting the path by checking line intersection.""" - segment = point - begin - segmentLength = abs( segment ) - if segmentLength <= 0.0: - return False - normalizedSegment = segment / segmentLength - segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) - pointRotated = segmentYMirror * point - beginRotated = segmentYMirror * begin - if euclidean.isXSegmentIntersectingPath( path[ max( 0, pointIndex - 20 ) : pointIndex ], pointRotated.real, beginRotated.real, segmentYMirror, pointRotated.imag ): - return True - return euclidean.isXSegmentIntersectingPath( path[ pointIndex + 1 : pointIndex + 21 ], pointRotated.real, beginRotated.real, segmentYMirror, pointRotated.imag ) - -def isIntersectingLoopsPaths( loops, paths, pointBegin, pointEnd ): - """Determine if the segment between the first and second point is intersecting the loop list.""" - normalizedSegment = pointEnd.dropAxis() - pointBegin.dropAxis() - normalizedSegmentLength = abs( normalizedSegment ) - if normalizedSegmentLength == 0.0: - return False - normalizedSegment /= normalizedSegmentLength - segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) - pointBeginRotated = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, pointBegin ) - pointEndRotated = euclidean.getRoundZAxisByPlaneAngle( segmentYMirror, pointEnd ) - if euclidean.isLoopListIntersectingInsideXSegment( loops, pointBeginRotated.real, pointEndRotated.real, segmentYMirror, pointBeginRotated.imag ): - return True - return euclidean.isXSegmentIntersectingPaths( paths, pointBeginRotated.real, pointEndRotated.real, segmentYMirror, pointBeginRotated.imag ) - -#def isPerimeterPathInSurroundLoops( nestedRings ): -# 'Determine if there is a perimeter path in the surrounding loops.' -# for nestedRing in nestedRings: -# if len( nestedRing.perimeterPaths ) > 0: -# return True -# return False - -def isPointAddedAroundClosest( pixelTable, layerExtrusionWidth, paths, removedEndpointPoint, width ): - """Add the closest removed endpoint to the path, with minimal twisting.""" - closestDistanceSquared = 999999999987654321.0 - closestPathIndex = None - for pathIndex in xrange( len(paths) ): - path = paths[ pathIndex ] - for pointIndex in xrange( len(path) ): - point = path[ pointIndex ] - distanceSquared = abs( point - removedEndpointPoint ) - if distanceSquared < closestDistanceSquared: - closestDistanceSquared = distanceSquared - closestPathIndex = pathIndex - if closestPathIndex is None: - return - if closestDistanceSquared < 0.8 * layerExtrusionWidth * layerExtrusionWidth: - return - closestPath = paths[ closestPathIndex ] - closestPointIndex = getWithLeastLength( closestPath, removedEndpointPoint ) - if isAddedPointOnPathFree( closestPath, pixelTable, removedEndpointPoint, closestPointIndex, width ): - addPointOnPath( closestPath, closestPathIndex, pixelTable, removedEndpointPoint, closestPointIndex, width ) - return True - return isSidePointAdded( pixelTable, closestPath, closestPathIndex, closestPointIndex, layerExtrusionWidth, removedEndpointPoint, width ) - -def isSegmentAround( aroundSegments, segment ): - """Determine if there is another segment around.""" - for aroundSegment in aroundSegments: - endpoint = aroundSegment[0] - if isSegmentInX( segment, endpoint.point.real, endpoint.otherEndpoint.point.real ): - return True - return False - -def isSegmentCompletelyInAnIntersection( segment, xIntersections ): - """Add sparse endpoints from a segment.""" - for xIntersectionIndex in xrange( 0, len( xIntersections ), 2 ): - surroundingXFirst = xIntersections[ xIntersectionIndex ] - surroundingXSecond = xIntersections[ xIntersectionIndex + 1 ] - if euclidean.isSegmentCompletelyInX( segment, surroundingXFirst, surroundingXSecond ): - return True - return False - -def isSegmentInX( segment, xFirst, xSecond ): - """Determine if the segment overlaps within x.""" - segmentFirstX = segment[0].point.real - segmentSecondX = segment[1].point.real - if min( segmentFirstX, segmentSecondX ) > max( xFirst, xSecond ): - return False - return max( segmentFirstX, segmentSecondX ) > min( xFirst, xSecond ) - -def isSharpCorner( beginComplex, centerComplex, endComplex ): - """Determine if the three complex points form a sharp corner.""" - centerBeginComplex = beginComplex - centerComplex - centerEndComplex = endComplex - centerComplex - centerBeginLength = abs( centerBeginComplex ) - centerEndLength = abs( centerEndComplex ) - if centerBeginLength <= 0.0 or centerEndLength <= 0.0: - return False - centerBeginComplex /= centerBeginLength - centerEndComplex /= centerEndLength - return euclidean.getDotProduct( centerBeginComplex, centerEndComplex ) > 0.9 - -def isSidePointAdded( pixelTable, closestPath, closestPathIndex, closestPointIndex, layerExtrusionWidth, removedEndpointPoint, width ): - """Add side point along with the closest removed endpoint to the path, with minimal twisting.""" - if closestPointIndex <= 0 or closestPointIndex >= len( closestPath ): - return False - pointBegin = closestPath[ closestPointIndex - 1 ] - pointEnd = closestPath[ closestPointIndex ] - removedEndpointPoint = removedEndpointPoint - closest = pointBegin - farthest = pointEnd - removedMinusClosest = removedEndpointPoint - pointBegin - removedMinusClosestLength = abs( removedMinusClosest ) - if removedMinusClosestLength <= 0.0: - return False - removedMinusOther = removedEndpointPoint - pointEnd - removedMinusOtherLength = abs( removedMinusOther ) - if removedMinusOtherLength <= 0.0: - return False - insertPointAfter = None - insertPointBefore = None - if removedMinusOtherLength < removedMinusClosestLength: - closest = pointEnd - farthest = pointBegin - removedMinusClosest = removedMinusOther - removedMinusClosestLength = removedMinusOtherLength - insertPointBefore = removedEndpointPoint - else: - insertPointAfter = removedEndpointPoint - removedMinusClosestNormalized = removedMinusClosest / removedMinusClosestLength - perpendicular = removedMinusClosestNormalized * complex( 0.0, layerExtrusionWidth ) - sidePoint = removedEndpointPoint + perpendicular - #extra check in case the line to the side point somehow slips by the line to the perpendicular - sidePointOther = removedEndpointPoint - perpendicular - if abs( sidePoint - farthest ) > abs( sidePointOther - farthest ): - perpendicular = - perpendicular - sidePoint = sidePointOther - maskTable = {} - closestSegmentTable = {} - toPerpendicularTable = {} - euclidean.addValueSegmentToPixelTable( pointBegin, pointEnd, maskTable, None, width ) - euclidean.addValueSegmentToPixelTable( closest, removedEndpointPoint, closestSegmentTable, None, width ) - euclidean.addValueSegmentToPixelTable( sidePoint, farthest, toPerpendicularTable, None, width ) - if euclidean.isPixelTableIntersecting( pixelTable, toPerpendicularTable, maskTable ) or euclidean.isPixelTableIntersecting( closestSegmentTable, toPerpendicularTable, maskTable ): - sidePoint = removedEndpointPoint - perpendicular - toPerpendicularTable = {} - euclidean.addValueSegmentToPixelTable( sidePoint, farthest, toPerpendicularTable, None, width ) - if euclidean.isPixelTableIntersecting( pixelTable, toPerpendicularTable, maskTable ) or euclidean.isPixelTableIntersecting( closestSegmentTable, toPerpendicularTable, maskTable ): - return False - if insertPointBefore is not None: - addPointOnPathIfFree( closestPath, closestPathIndex, pixelTable, insertPointBefore, closestPointIndex, width ) - addPointOnPathIfFree( closestPath, closestPathIndex, pixelTable, sidePoint, closestPointIndex, width ) - if insertPointAfter is not None: - addPointOnPathIfFree( closestPath, closestPathIndex, pixelTable, insertPointAfter, closestPointIndex, width ) - return True - -def removeEndpoints( pixelTable, layerExtrusionWidth, paths, removedEndpoints, aroundWidth ): - """Remove endpoints which are added to the path.""" - for removedEndpointIndex in xrange( len(removedEndpoints) - 1, - 1, - 1 ): - removedEndpoint = removedEndpoints[ removedEndpointIndex ] - removedEndpointPoint = removedEndpoint.point - if isPointAddedAroundClosest( pixelTable, layerExtrusionWidth, paths, removedEndpointPoint, aroundWidth ): - removedEndpoints.remove( removedEndpoint ) - -def setIsOutside( yCloseToCenterPath, yIntersectionPaths ): - """Determine if the yCloseToCenterPath is outside.""" - beforeClose = yCloseToCenterPath.yMinusCenter < 0.0 - for yIntersectionPath in yIntersectionPaths: - if yIntersectionPath != yCloseToCenterPath: - beforePath = yIntersectionPath.yMinusCenter < 0.0 - if beforeClose == beforePath: - yCloseToCenterPath.isOutside = False - return - yCloseToCenterPath.isOutside = True - -def writeOutput(fileName, shouldAnalyze=True): - """Fill an inset gcode file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'fill', shouldAnalyze) - - -class FillRepository: - """A class to handle the fill settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.fill.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Fill', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Fill') - self.activateFill = settings.BooleanSetting().getFromValue('Activate Fill:', self, True ) - - - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Main Fill Settings -', self ) - self.infillSolidity = settings.FloatSpin().getFromValue( 0.05, 'Infill Solidity (ratio):', self, 1.00, 0.35 ) - self.infillWidthRatio = settings.FloatSpin().getFromValue( 0.75, 'Extrusion Lines extra Spacing (Scaler):', self, 1.25, 1.0 ) - self.infillPerimeterOverlap = settings.FloatSpin().getFromValue( 0.000, 'Infill Overlap over Perimeter (Scaler):', self, 0.400, 1.0 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Shell Settings -', self ) - settings.LabelDisplay().getFromName('- Additional Perimeter Shells -', self ) - self.extraShellsAlternatingSolidLayer = settings.IntSpin().getFromValue( 0, 'Extra Shells on Alternating Solid Layer (layers):', self, 3, 1 ) - self.extraShellsBase = settings.IntSpin().getFromValue( 0, 'Extra Shells on Base (layers):', self, 3, 1 ) - self.extraShellsSparseLayer = settings.IntSpin().getFromValue( 0, 'Extra Shells on Sparse Layer (layers):', self, 3, 1 ) - - - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Top and Bottom Layers -', self ) - self.solidSurfaceThickness = settings.IntSpin().getFromValue( 0, 'Fully filled Layers (each top and bottom):', self, 5, 2 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Extrusion Sequence -', self ) - self.startFromChoice = settings.MenuButtonDisplay().getFromName('Start New Layer From :', self) - self.startFromLowerLeft = settings.MenuRadio().getFromMenuButtonDisplay(self.startFromChoice, 'Lower Left', self, True) - self.startFromNearest = settings.MenuRadio().getFromMenuButtonDisplay(self.startFromChoice, 'Nearest', self, False) - settings.LabelSeparator().getFromRepository(self) - self.threadSequenceChoice = settings.MenuButtonDisplay().getFromName('What order to print:', self) - self.threadSequenceInfillLoops = settings.MenuRadio().getFromMenuButtonDisplay(self.threadSequenceChoice, 'Infill > Loops > Perimeter', self, False) - self.threadSequenceInfillPerimeter = settings.MenuRadio().getFromMenuButtonDisplay(self.threadSequenceChoice, 'Infill > Perimeter > Loops', self, False) - self.threadSequenceLoopsInfill = settings.MenuRadio().getFromMenuButtonDisplay(self.threadSequenceChoice, 'Loops > Infill > Perimeter', self, False) - self.threadSequenceLoopsPerimeter = settings.MenuRadio().getFromMenuButtonDisplay(self.threadSequenceChoice, 'Loops > Perimeter > Infill', self, False) - self.threadSequencePerimeterInfill = settings.MenuRadio().getFromMenuButtonDisplay(self.threadSequenceChoice, 'Perimeter > Infill > Loops', self, False) - self.threadSequencePerimeterLoops = settings.MenuRadio().getFromMenuButtonDisplay(self.threadSequenceChoice, 'Perimeter > Loops > Infill', self, True) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- How to make the infill -', self ) - self.infillPatternLabel = settings.LabelDisplay().getFromName('Infill Pattern:', self ) - infillLatentStringVar = settings.LatentStringVar() - self.infillPatternLine = settings.Radio().getFromRadio( infillLatentStringVar, 'Line', self, True ) - self.infillPatternGridCircular = settings.Radio().getFromRadio( infillLatentStringVar, 'Grid Circular', self, False ) - self.infillPatternGridHexagonal = settings.Radio().getFromRadio( infillLatentStringVar, 'Grid Hexagonal', self, False ) - self.infillPatternGridRectangular = settings.Radio().getFromRadio( infillLatentStringVar, 'Grid Rectangular', self, False ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Diaphragm (fully filled layers -', self ) - self.diaphragmPeriod = settings.IntSpin().getFromValue( 20, 'Diaphragm at every ...th Layer:', self, 200, 100 ) - self.diaphragmThickness = settings.IntSpin().getFromValue( 0, 'Diaphragm Thickness (layers):', self, 5, 0 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- if one of the Grids chosen as Infill Pattern -', self ) - self.gridCircleSeparationOverPerimeterWidth = settings.FloatSpin().getFromValue(0.0, 'Grid Circle Separation over Perimeter Width (ratio):', self, 1.0, 0.2) - self.gridExtraOverlap = settings.FloatSpin().getFromValue( 0.0, 'Grid Extra Overlap (ratio):', self, 0.5, 0.1 ) - self.gridJunctionSeparationBandHeight = settings.IntSpin().getFromValue( 0, 'Grid Junction Separation Band Height (layers):', self, 20, 10 ) - self.gridJunctionSeparationOverOctogonRadiusAtEnd = settings.FloatSpin().getFromValue( 0.0, 'Grid Junction Separation over Octogon Radius At End (ratio):', self, 0.8, 0.0 ) - self.gridJunctionSeparationOverOctogonRadiusAtMiddle = settings.FloatSpin().getFromValue( 0.0, 'Grid Junction Separation over Octogon Radius At Middle (ratio):', self, 0.8, 0.0 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Infill Angles -', self ) - self.infillBeginRotation = settings.FloatSpin().getFromValue( 0.0, 'Infill Begin Rotation (degrees):', self, 90.0, 45.0 ) - self.infillBeginRotationRepeat = settings.IntSpin().getFromValue( 0, 'Infill Begin Rotation Repeat (layers):', self, 3, 1 ) - self.infillOddLayerExtraRotation = settings.FloatSpin().getFromValue( 30.0, 'Infill Odd Layer Extra Rotation (degrees):', self, 90.0, 90.0 ) - self.executeTitle = 'Fill' - - def execute(self): - """Fill button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class FillSkein: - """A class to fill a skein of extrusions.""" - def __init__(self): - self.bridgeWidthMultiplier = 1.0 - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.infillWidthRatio = 1 - self.extruderActive = False - self.fillInset = 0.18 - self.isPerimeter = False - self.lastExtraShells = - 1 - self.lineIndex = 0 - self.oldLocation = None - self.oldOrderedLocation = None - self.perimeterWidth = None - self.rotatedLayer = None - self.rotatedLayers = [] - self.shutdownLineIndex = sys.maxint - self.nestedRing = None - self.thread = None - self.infillWidth = None - - def addFill(self, layerIndex): - """Add fill to the carve layer.""" -# if layerIndex > 2: -# return - settings.printProgressByNumber(layerIndex, len(self.rotatedLayers), 'fill') - alreadyFilledArounds = [] - pixelTable = {} - arounds = [] - betweenWidth = self.betweenWidth - self.layerExtrusionWidth = self.infillWidth - layerFillInset = self.fillInset - rotatedLayer = self.rotatedLayers[layerIndex] - self.distanceFeedRate.addLine('( %s )' % rotatedLayer.z) - layerRotation = self.getLayerRotation(layerIndex) - reverseRotation = complex(layerRotation.real, - layerRotation.imag) - surroundingCarves = [] - layerRemainder = layerIndex % int(round(self.repository.diaphragmPeriod.value)) - if layerRemainder >= int(round(self.repository.diaphragmThickness.value)) and rotatedLayer.rotation is None: - for surroundingIndex in xrange(1, self.solidSurfaceThickness + 1): - self.addRotatedCarve(layerIndex, -surroundingIndex, reverseRotation, surroundingCarves) - self.addRotatedCarve(layerIndex, surroundingIndex, reverseRotation, surroundingCarves) - extraShells = self.repository.extraShellsSparseLayer.value - if len(surroundingCarves) < self.doubleSolidSurfaceThickness: - extraShells = self.repository.extraShellsAlternatingSolidLayer.value - if self.lastExtraShells != self.repository.extraShellsBase.value: - extraShells = self.repository.extraShellsBase.value - if rotatedLayer.rotation is not None: - extraShells = 0 - betweenWidth *= self.bridgeWidthMultiplier - self.layerExtrusionWidth *= self.bridgeWidthMultiplier - layerFillInset *= self.bridgeWidthMultiplier - self.distanceFeedRate.addLine('( %s )' % rotatedLayer.rotation) - aroundInset = 0.25 * self.layerExtrusionWidth - aroundWidth = 0.25 * self.layerExtrusionWidth - self.lastExtraShells = extraShells - gridPointInsetX = 0.5 * layerFillInset - doubleExtrusionWidth = 2.0 * self.layerExtrusionWidth - endpoints = [] - infillPaths = [] - layerInfillSolidity = self.infillSolidity - self.isDoubleJunction = True - self.isJunctionWide = True - if self.repository.infillPatternGridHexagonal.value: - infillBeginRotationPolar = euclidean.getWiddershinsUnitPolar(self.infillBeginRotation) - if abs(euclidean.getDotProduct(layerRotation, infillBeginRotationPolar)) < math.sqrt( 0.5): - layerInfillSolidity *= 0.5 - self.isDoubleJunction = False - else: - self.isJunctionWide = False - rotatedLoops = [] -# for nestedRing in rotatedLayer.nestedRings: -# nestedRing.fillBoundaries = intercircle.getInsetLoopsFromLoop( nestedRing.boundary, betweenWidth ) -# nestedRing.lastExistingFillLoops = nestedRing.fillBoundaries - nestedRings = euclidean.getOrderedNestedRings(rotatedLayer.nestedRings) -# if isPerimeterPathInSurroundLoops( nestedRings ): -# extraShells = 0 - createFillForSurroundings(nestedRings, betweenWidth, False) - for extraShellIndex in xrange(extraShells): - createFillForSurroundings(nestedRings, self.layerExtrusionWidth, True) - fillLoops = euclidean.getFillOfSurroundings(nestedRings, None) - slightlyGreaterThanFill = 1.01 * layerFillInset - for loop in fillLoops: - alreadyFilledLoop = [] - alreadyFilledArounds.append(alreadyFilledLoop) - planeRotatedPerimeter = euclidean.getPointsRoundZAxis(reverseRotation, loop) - rotatedLoops.append(planeRotatedPerimeter) - centers = intercircle.getCentersFromLoop(planeRotatedPerimeter, slightlyGreaterThanFill) - euclidean.addLoopToPixelTable(planeRotatedPerimeter, pixelTable, aroundWidth) - for center in centers: - alreadyFilledInset = intercircle.getSimplifiedInsetFromClockwiseLoop(center, layerFillInset) - if intercircle.isLargeSameDirection(alreadyFilledInset, center, layerFillInset): - alreadyFilledLoop.append(alreadyFilledInset) - around = intercircle.getSimplifiedInsetFromClockwiseLoop(center, aroundInset) - if euclidean.isPathInsideLoop(planeRotatedPerimeter, around) == euclidean.isWiddershins(planeRotatedPerimeter): - around.reverse() - arounds.append(around) - euclidean.addLoopToPixelTable(around, pixelTable, aroundWidth) - if len(arounds) < 1: - self.addThreadsBridgeLayer(layerIndex, nestedRings, rotatedLayer) - return - back = euclidean.getBackOfLoops(arounds) - front = euclidean.getFrontOfLoops(arounds) - front = math.ceil(front / self.layerExtrusionWidth) * self.layerExtrusionWidth - fillWidth = back - front - numberOfLines = int(math.ceil(fillWidth / self.layerExtrusionWidth)) - self.frontOverWidth = 0.0 - self.horizontalSegmentLists = euclidean.getHorizontalSegmentListsFromLoopLists(alreadyFilledArounds, front, numberOfLines, rotatedLoops, self.layerExtrusionWidth) - self.surroundingXIntersectionLists = [] - self.yList = [] - gridCircular = False - removedEndpoints = [] - if len(surroundingCarves) >= self.doubleSolidSurfaceThickness: - if self.repository.infillPatternGridCircular.value and self.repository.infillSolidity.value > 0.0: - gridCircular = True - layerInfillSolidity = 0.0 - xIntersectionIndexLists = [] - self.frontOverWidth = euclidean.getFrontOverWidthAddXListYList(front, surroundingCarves, numberOfLines, xIntersectionIndexLists, self.layerExtrusionWidth, self.yList) - for fillLine in xrange(len(self.horizontalSegmentLists)): - xIntersectionIndexList = xIntersectionIndexLists[fillLine] - surroundingXIntersections = euclidean.getIntersectionOfXIntersectionIndexes(self.doubleSolidSurfaceThickness, xIntersectionIndexList) - self.surroundingXIntersectionLists.append(surroundingXIntersections) - addSparseEndpoints(doubleExtrusionWidth, endpoints, fillLine, self.horizontalSegmentLists, layerInfillSolidity, removedEndpoints, self.solidSurfaceThickness, surroundingXIntersections) - else: - for fillLine in xrange(len(self.horizontalSegmentLists)): - addSparseEndpoints(doubleExtrusionWidth, endpoints, fillLine, self.horizontalSegmentLists, layerInfillSolidity, removedEndpoints, self.solidSurfaceThickness, None) - paths = euclidean.getPathsFromEndpoints(endpoints, 5.0 * self.layerExtrusionWidth, pixelTable, aroundWidth) - if gridCircular: - startAngle = euclidean.globalGoldenAngle * float(layerIndex) - for gridPoint in self.getGridPoints(fillLoops, reverseRotation): - self.addGridCircle(gridPoint, infillPaths, layerRotation, pixelTable, rotatedLoops, layerRotation, aroundWidth) - else: - if self.isGridToBeExtruded(): - self.addGrid( - arounds, fillLoops, gridPointInsetX, layerIndex, paths, pixelTable, reverseRotation, surroundingCarves, aroundWidth) - oldRemovedEndpointLength = len(removedEndpoints) + 1 - while oldRemovedEndpointLength - len(removedEndpoints) > 0: - oldRemovedEndpointLength = len(removedEndpoints) - removeEndpoints(pixelTable, self.layerExtrusionWidth, paths, removedEndpoints, aroundWidth) - paths = euclidean.getConnectedPaths(paths, pixelTable, aroundWidth) - for path in paths: - addPath(self.layerExtrusionWidth, infillPaths, path, layerRotation) - euclidean.transferPathsToSurroundingLoops(nestedRings, infillPaths) - self.addThreadsBridgeLayer(layerIndex, nestedRings, rotatedLayer) - - def addGcodeFromThreadZ( self, thread, z ): - """Add a gcode thread to the output.""" - self.distanceFeedRate.addGcodeFromThreadZ( thread, z ) - - def addGrid(self, arounds, fillLoops, gridPointInsetX, layerIndex, paths, pixelTable, reverseRotation, surroundingCarves, width): - """Add the grid to the infill layer.""" - if len(surroundingCarves) < self.doubleSolidSurfaceThickness: - return - explodedPaths = [] - pathGroups = [] - for path in paths: - pathIndexBegin = len( explodedPaths ) - for pointIndex in xrange( len(path) - 1 ): - pathSegment = [ path[ pointIndex ], path[ pointIndex + 1 ] ] - explodedPaths.append( pathSegment ) - pathGroups.append( ( pathIndexBegin, len( explodedPaths ) ) ) - for pathIndex in xrange( len( explodedPaths ) ): - explodedPath = explodedPaths[ pathIndex ] - euclidean.addPathToPixelTable( explodedPath, pixelTable, pathIndex, width ) - gridPoints = self.getGridPoints(fillLoops, reverseRotation) - gridPointInsetY = gridPointInsetX * ( 1.0 - self.repository.gridExtraOverlap.value ) - if self.repository.infillPatternGridRectangular.value: - gridBandHeight = self.repository.gridJunctionSeparationBandHeight.value - gridLayerRemainder = ( layerIndex - self.solidSurfaceThickness ) % gridBandHeight - halfBandHeight = 0.5 * float( gridBandHeight ) - halfBandHeightFloor = math.floor( halfBandHeight ) - fromMiddle = math.floor( abs( gridLayerRemainder - halfBandHeight ) ) - fromEnd = halfBandHeightFloor - fromMiddle - gridJunctionSeparation = self.gridJunctionEnd * fromMiddle + self.gridJunctionMiddle * fromEnd - gridJunctionSeparation /= halfBandHeightFloor - gridPointInsetX += gridJunctionSeparation - gridPointInsetY += gridJunctionSeparation - oldGridPointLength = len( gridPoints ) + 1 - while oldGridPointLength - len( gridPoints ) > 0: - oldGridPointLength = len( gridPoints ) - self.addRemainingGridPoints( arounds, gridPointInsetX, gridPointInsetY, gridPoints, True, explodedPaths, pixelTable, width ) - oldGridPointLength = len( gridPoints ) + 1 - while oldGridPointLength - len( gridPoints ) > 0: - oldGridPointLength = len( gridPoints ) - self.addRemainingGridPoints( arounds, gridPointInsetX, gridPointInsetY, gridPoints, False, explodedPaths, pixelTable, width ) - for pathGroupIndex in xrange( len( pathGroups ) ): - pathGroup = pathGroups[ pathGroupIndex ] - paths[ pathGroupIndex ] = [] - for explodedPathIndex in xrange( pathGroup[0], pathGroup[1] ): - explodedPath = explodedPaths[ explodedPathIndex ] - if not len(paths[pathGroupIndex]): - paths[ pathGroupIndex ] = explodedPath - else: - paths[ pathGroupIndex ] += explodedPath[1 :] - - def addGridCircle(self, center, infillPaths, layerRotation, pixelTable, rotatedLoops, startRotation, width): - """Add circle to the grid.""" - startAngle = -math.atan2(startRotation.imag, startRotation.real) - loop = euclidean.getComplexPolygon(center, self.gridCircleRadius, 17, startAngle) - loopPixelDictionary = {} - euclidean.addLoopToPixelTable(loop, loopPixelDictionary, width) - if not euclidean.isPixelTableIntersecting(pixelTable, loopPixelDictionary): - if euclidean.getIsInFilledRegion(rotatedLoops, euclidean.getLeftPoint(loop)): - addLoop(self.layerExtrusionWidth, infillPaths, loop, layerRotation) - return - insideIndexPaths = [] - insideIndexPath = None - for pointIndex, point in enumerate(loop): - nextPoint = loop[(pointIndex + 1) % len(loop)] - segmentDictionary = {} - euclidean.addValueSegmentToPixelTable(point, nextPoint, segmentDictionary, None, width) - euclidean.addSquareTwoToPixelDictionary(segmentDictionary, point, None, width) - euclidean.addSquareTwoToPixelDictionary(segmentDictionary, nextPoint, None, width) - shouldAddLoop = not euclidean.isPixelTableIntersecting(pixelTable, segmentDictionary) - if shouldAddLoop: - shouldAddLoop = euclidean.getIsInFilledRegion(rotatedLoops, point) - if shouldAddLoop: - if insideIndexPath is None: - insideIndexPath = [pointIndex] - insideIndexPaths.append(insideIndexPath) - else: - insideIndexPath.append(pointIndex) - else: - insideIndexPath = None - if len(insideIndexPaths) > 1: - insideIndexPathFirst = insideIndexPaths[0] - insideIndexPathLast = insideIndexPaths[-1] - if insideIndexPathFirst[0] == 0 and insideIndexPathLast[-1] == len(loop) - 1: - insideIndexPaths[0] = insideIndexPathLast + insideIndexPathFirst - del insideIndexPaths[-1] - for insideIndexPath in insideIndexPaths: - path = [] - for insideIndex in insideIndexPath: - if not len(path): - path.append(loop[insideIndex]) - path.append(loop[(insideIndex + 1) % len(loop)]) - addPath(self.layerExtrusionWidth, infillPaths, path, layerRotation) - - def addGridLinePoints( self, begin, end, gridPoints, gridRotationAngle, offset, y ): - """Add the segments of one line of a grid to the infill.""" - if self.gridRadius == 0.0: - return - gridXStep = int(math.floor(begin / self.gridXStepSize)) - 3 - gridXOffset = offset + self.gridXStepSize * float(gridXStep) - while gridXOffset < end: - if gridXOffset >= begin: - gridPointComplex = complex(gridXOffset, y) * gridRotationAngle - if self.repository.infillPatternGridCircular.value or self.isPointInsideLineSegments(gridPointComplex): - gridPoints.append(gridPointComplex) - gridXStep = self.getNextGripXStep(gridXStep) - gridXOffset = offset + self.gridXStepSize * float(gridXStep) - - def addRemainingGridPoints( - self, arounds, gridPointInsetX, gridPointInsetY, gridPoints, isBothOrNone, paths, pixelTable, width): - """Add the remaining grid points to the grid point list.""" - for gridPointIndex in xrange( len( gridPoints ) - 1, - 1, - 1 ): - gridPoint = gridPoints[ gridPointIndex ] - addAroundGridPoint( arounds, gridPoint, gridPointInsetX, gridPointInsetY, gridPoints, self.gridRadius, isBothOrNone, self.isDoubleJunction, self.isJunctionWide, paths, pixelTable, width ) - - def addRotatedCarve(self, currentLayer, layerDelta, reverseRotation, surroundingCarves): - """Add a rotated carve to the surrounding carves.""" - layerIndex = currentLayer + layerDelta - if layerIndex < 0 or layerIndex >= len(self.rotatedLayers): - return - nestedRings = self.rotatedLayers[layerIndex].nestedRings - rotatedCarve = [] - for nestedRing in nestedRings: - planeRotatedLoop = euclidean.getPointsRoundZAxis(reverseRotation, nestedRing.boundary) - rotatedCarve.append(planeRotatedLoop) - outsetRadius = float(abs(layerDelta)) * self.layerThickness - rotatedCarve = intercircle.getInsetSeparateLoopsFromLoops(-outsetRadius, rotatedCarve) - surroundingCarves.append(rotatedCarve) - - def addThreadsBridgeLayer(self, layerIndex, nestedRings, rotatedLayer): - """Add the threads, add the bridge end & the layer end tag.""" - if self.oldOrderedLocation is None or self.repository.startFromLowerLeft.value: - self.oldOrderedLocation = getLowerLeftCorner(nestedRings) - extrusionHalfWidth = 0.5 * self.layerExtrusionWidth - threadSequence = self.threadSequence - if layerIndex < 1: - threadSequence = ['perimeter', 'loops', 'infill'] - euclidean.addToThreadsRemove(extrusionHalfWidth, nestedRings, self.oldOrderedLocation, self, threadSequence) - if rotatedLayer.rotation is not None: - self.distanceFeedRate.addLine('()') - self.distanceFeedRate.addLine('()') - - def addToThread(self, location): - """Add a location to thread.""" - if self.oldLocation is None: - return - if self.isPerimeter: - self.nestedRing.addToLoop( location ) - return - if self.thread is None: - self.thread = [ self.oldLocation.dropAxis() ] - self.nestedRing.perimeterPaths.append(self.thread) - self.thread.append(location.dropAxis()) - - def getCraftedGcode( self, repository, gcodeText ): - """Parse gcode text and store the bevel gcode.""" - self.repository = repository - self.lines = archive.getTextLines(gcodeText) - self.threadSequence = None - if repository.threadSequenceInfillLoops.value: - self.threadSequence = ['infill', 'loops', 'perimeter'] - if repository.threadSequenceInfillPerimeter.value: - self.threadSequence = ['infill', 'perimeter', 'loops'] - if repository.threadSequenceLoopsInfill.value: - self.threadSequence = ['loops', 'infill', 'perimeter'] - if repository.threadSequenceLoopsPerimeter.value: - self.threadSequence = ['loops', 'perimeter', 'infill'] - if repository.threadSequencePerimeterInfill.value: - self.threadSequence = ['perimeter', 'infill', 'loops'] - if repository.threadSequencePerimeterLoops.value: - self.threadSequence = ['perimeter', 'loops', 'infill'] - if self.repository.infillPerimeterOverlap.value > 0.45: - print('') - print('Here we GO !!!') - print('') - self.parseInitialization() - if self.perimeterWidth is None: - print('Warning, nothing will be done because self.perimeterWidth in getCraftedGcode in FillSkein was None.') - return '' - self.betweenWidth = self.perimeterWidth - 0.5 * self.infillWidth -# self.fillInset = self.infillWidth - self.infillWidth * 0.23 -# self.fillInset = self.infillWidth - self.infillWidth * self.repository.infillPerimeterOverlap.value - self.fillInset = ((self.infillWidth * (math.pi / 4)) / self.repository.infillPerimeterOverlap.value ) -# self.fillInset = ((self.infillWidth / 2 + self.infillWidth) / 2) / self.repository.infillPerimeterOverlap.value -# (self.layerThickness - (clipRepository.clipOverPerimeterWidth.value * self.layerThickness * 0.7853)) * 2 -# self.fillInset = self.infillWidth - self.infillWidth * self.repository.infillPerimeterOverlap.value - self.infillSolidity = repository.infillSolidity.value - if self.isGridToBeExtruded(): - self.setGridVariables(repository) - self.infillBeginRotation = math.radians( repository.infillBeginRotation.value ) - self.infillOddLayerExtraRotation = math.radians( repository.infillOddLayerExtraRotation.value ) - self.solidSurfaceThickness = int( round( self.repository.solidSurfaceThickness.value ) ) - self.doubleSolidSurfaceThickness = self.solidSurfaceThickness + self.solidSurfaceThickness - for lineIndex in xrange( self.lineIndex, len(self.lines) ): - self.parseLine( lineIndex ) - for layerIndex in xrange(len(self.rotatedLayers)): - self.addFill(layerIndex) - self.distanceFeedRate.addLines( self.lines[ self.shutdownLineIndex : ] ) - return self.distanceFeedRate.output.getvalue() - - def getGridPoints(self, fillLoops, reverseRotation): - """Get the grid points.""" - if self.infillSolidity > 0.8: - return [] - rotationBaseAngle = euclidean.getWiddershinsUnitPolar(self.infillBeginRotation) - reverseRotationBaseAngle = complex(rotationBaseAngle.real, - rotationBaseAngle.imag) - gridRotationAngle = reverseRotation * rotationBaseAngle - slightlyGreaterThanFill = 1.01 * self.gridInset - rotatedLoops = [] - triangle_mesh.sortLoopsInOrderOfArea(True, fillLoops) - for fillLoop in fillLoops: - rotatedLoops.append(euclidean.getPointsRoundZAxis(reverseRotationBaseAngle, fillLoop)) - if self.repository.infillPatternGridCircular.value: - return self.getGridPointsByLoops( - gridRotationAngle, intercircle.getInsetSeparateLoopsFromLoops(-self.gridCircleRadius, rotatedLoops)) - return self.getGridPointsByLoops(gridRotationAngle, intercircle.getInsetSeparateLoopsFromLoops(self.gridInset, rotatedLoops)) - - def getGridPointsByLoops(self, gridRotationAngle, loops): - """Get the grid points by loops.""" - gridIntersectionsDictionary = {} - gridPoints = [] - euclidean.addXIntersectionsFromLoopsForTable(loops, gridIntersectionsDictionary, self.gridRadius) - for gridIntersectionsKey in gridIntersectionsDictionary: - y = gridIntersectionsKey * self.gridRadius + self.gridRadius * 0.5 - gridIntersections = gridIntersectionsDictionary[gridIntersectionsKey] - gridIntersections.sort() - gridIntersectionsLength = len(gridIntersections) - if gridIntersectionsLength % 2 == 1: - gridIntersectionsLength -= 1 - for gridIntersectionIndex in xrange(0, gridIntersectionsLength, 2): - begin = gridIntersections[gridIntersectionIndex] - end = gridIntersections[gridIntersectionIndex + 1] - offset = self.offsetMultiplier * (gridIntersectionsKey % 2) + self.offsetBaseX - self.addGridLinePoints(begin, end, gridPoints, gridRotationAngle, offset, y) - return gridPoints - - def getLayerRotation(self, layerIndex): - """Get the layer rotation.""" - rotation = self.rotatedLayers[layerIndex].rotation - if rotation is not None: - return rotation - infillBeginRotationRepeat = self.repository.infillBeginRotationRepeat.value - infillOddLayerRotationMultiplier = float( layerIndex % ( infillBeginRotationRepeat + 1 ) == infillBeginRotationRepeat ) - layerAngle = self.infillBeginRotation + infillOddLayerRotationMultiplier * self.infillOddLayerExtraRotation - return euclidean.getWiddershinsUnitPolar(layerAngle) - - def getNextGripXStep( self, gridXStep ): - """Get the next grid x step, increment by an extra one every three if hexagonal grid is chosen.""" - gridXStep += 1 - if self.repository.infillPatternGridHexagonal.value and not gridXStep % 3: - gridXStep += 1 - return gridXStep - - def isGridToBeExtruded(self): - """Determine if the grid is to be extruded.""" - if self.repository.infillPatternLine.value: - return False - return self.repository.infillSolidity.value > 0.0 - - def isPointInsideLineSegments( self, gridPoint ): - """Is the point inside the line segments of the loops.""" - if self.solidSurfaceThickness <= 0: - return True - fillLine = int( round( gridPoint.imag / self.layerExtrusionWidth - self.frontOverWidth ) ) - if fillLine >= len( self.horizontalSegmentLists ) or fillLine < 0: - return False - lineSegments = self.horizontalSegmentLists[fillLine] - surroundingXIntersections = self.surroundingXIntersectionLists[fillLine] - for lineSegment in lineSegments: - if isSegmentCompletelyInAnIntersection( lineSegment, surroundingXIntersections ): - xFirst = lineSegment[0].point.real - xSecond = lineSegment[1].point.real - if gridPoint.real > min( xFirst, xSecond ) and gridPoint.real < max( xFirst, xSecond ): - return True - return False - - def linearMove( self, splitLine ): - """Add a linear move to the thread.""" - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - if self.extruderActive: - self.addToThread( location ) - self.oldLocation = location - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '(': - self.perimeterWidth = float(splitLine[1]) - threadSequenceString = ' '.join( self.threadSequence ) - self.distanceFeedRate.addTagBracketedLine('threadSequenceString', threadSequenceString ) - self.infillWidth = self.repository.infillWidthRatio.value * self.perimeterWidth * ((self.perimeterWidth -(self.layerThickness -( math.pi * (self.layerThickness/4))))/self.perimeterWidth) - self.distanceFeedRate.addTagRoundedLine('infillWidth', self.infillWidth) - self.infillWidthOverThickness = self.perimeterWidth / self.layerThickness - elif firstWord == '()': - self.distanceFeedRate.addLine('( fill )') - elif firstWord == '()': - self.distanceFeedRate.addLine(line) - return - elif firstWord == '(': - self.bridgeWidthMultiplier = float(splitLine[1]) - elif firstWord == '(': - self.layerThickness = float(splitLine[1]) -# self.infillWidth = self.repository.infillWidthOverThickness.value * self.layerThickness -# self.distanceFeedRate.addTagRoundedLine('infillWidth', self.infillWidth) - self.distanceFeedRate.addLine(line) - - def parseLine( self, lineIndex ): - """Parse a gcode line and add it to the fill skein.""" - line = self.lines[lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - self.linearMove(splitLine) - elif firstWord == 'M101': - self.extruderActive = True - elif firstWord == 'M103': - self.extruderActive = False - self.thread = None - self.isPerimeter = False - elif firstWord == '()': - self.nestedRing = euclidean.NestedBand() - self.rotatedLayer.nestedRings.append( self.nestedRing ) - elif firstWord == '()': - self.nestedRing = None - elif firstWord == '(': - location = gcodec.getLocationFromSplitLine(None, splitLine) - self.nestedRing.addToBoundary( location ) - elif firstWord == '(': - secondWordWithoutBrackets = splitLine[1].replace('(', '').replace(')', '') - self.rotatedLayer.rotation = complex( secondWordWithoutBrackets ) - elif firstWord == '()': - self.shutdownLineIndex = lineIndex - elif firstWord == '(': - self.rotatedLayer = RotatedLayer(float(splitLine[1])) - self.rotatedLayers.append( self.rotatedLayer ) - self.thread = None - elif firstWord == '(': - self.isPerimeter = True - - def setGridVariables( self, repository ): - """Set the grid variables.""" - self.gridInset = 1.2 * self.infillWidth - self.gridRadius = self.infillWidth / self.infillSolidity - self.gridXStepSize = 2.0 * self.gridRadius - self.offsetMultiplier = self.gridRadius - if self.repository.infillPatternGridHexagonal.value: - self.gridXStepSize = 4.0 / 3.0 * self.gridRadius - self.offsetMultiplier = 1.5 * self.gridXStepSize - if self.repository.infillPatternGridCircular.value: - self.gridRadius += self.gridRadius - self.gridXStepSize = self.gridRadius / math.sqrt(.75) - self.offsetMultiplier = 0.5 * self.gridXStepSize - circleInsetOverPerimeterWidth = repository.gridCircleSeparationOverPerimeterWidth.value + 0.5 - self.gridMinimumCircleRadius = self.perimeterWidth - self.gridInset = self.gridMinimumCircleRadius - self.gridCircleRadius = self.offsetMultiplier - circleInsetOverPerimeterWidth * self.perimeterWidth - if self.gridCircleRadius < self.gridMinimumCircleRadius: - print('') - print('!!! WARNING !!!') - print('Grid Circle Separation over Perimeter Width is too high, which makes the grid circles too small.') - print('You should reduce Grid Circle Separation over Perimeter Width to a reasonable value, like the default of 0.5.') - print('The grid circle radius will be set to the minimum grid circle radius.') - print('') - self.gridCircleRadius = self.gridMinimumCircleRadius - self.offsetBaseX = 0.25 * self.gridXStepSize - if self.repository.infillPatternGridRectangular.value: - halfGridMinusWidth = 0.5 * ( self.gridRadius - self.infillWidth ) - self.gridJunctionEnd = halfGridMinusWidth * repository.gridJunctionSeparationOverOctogonRadiusAtEnd.value - self.gridJunctionMiddle = halfGridMinusWidth * repository.gridJunctionSeparationOverOctogonRadiusAtMiddle.value - - -class RotatedLayer: - """A rotated layer.""" - def __init__( self, z ): - self.rotation = None - self.nestedRings = [] - self.z = z - - def __repr__(self): - """Get the string representation of this RotatedLayer.""" - return '%s, %s, %s' % ( self.z, self.rotation, self.nestedRings ) - - -class YIntersectionPath: - """A class to hold the y intersection position, the loop which it intersected and the point index of the loop which it intersected.""" - def __init__( self, pathIndex, pointIndex, y ): - """Initialize from the path, point index, and y.""" - self.pathIndex = pathIndex - self.pointIndex = pointIndex - self.y = y - - def __repr__(self): - """Get the string representation of this y intersection.""" - return '%s, %s, %s' % ( self.pathIndex, self.pointIndex, self.y ) - - def getPath( self, paths ): - """Get the path from the paths and path index.""" - return paths[ self.pathIndex ] - - def getPointIndexPlusOne(self): - """Get the point index plus one.""" - return self.pointIndex + 1 - - -def main(): - """Display the fill dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/inset.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/inset.py deleted file mode 100644 index a874e41..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/inset.py +++ /dev/null @@ -1,411 +0,0 @@ -#! /usr/bin/env python -""" -This page is in the table of contents. -Inset will inset the outside outlines by half the perimeter width, and outset the inside outlines by the same amount. - -The inset manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Inset - -==Settings== -===Add Custom Code for Temperature Reading=== -Default is on. - -When selected, the M105 custom code for temperature reading will be added at the beginning of the file. - -===Bridge Width Multiplier=== -Default is one. - -Defines the ratio of the extrusion width of a bridge layer over the extrusion width of the typical non bridge layers. - -===Loop Order Choice=== -Default loop order choice is 'Ascending Area'. - -When overlap is to be removed, for each loop, the overlap is checked against the list of loops already extruded. If the latest loop overlaps an already extruded loop, the overlap is removed from the latest loop. The loops are ordered according to their areas. - -====Ascending Area==== -When selected, the loops will be ordered in ascending area. With thin walled parts, if overlap is being removed the outside of the container will not be extruded. Holes will be the correct size. - -====Descending Area==== -When selected, the loops will be ordered in descending area. With thin walled parts, if overlap is being removed the inside of the container will not be extruded. Holes will be missing the interior wall so they will be slightly wider than model size. - -===Overlap Removal Width over Perimeter Width=== -Default is 0.6. - -Defines the ratio of the overlap removal width over the perimeter width. Any part of the extrusion that comes within the overlap removal width of another is removed. This is to prevent the extruder from depositing two extrusions right beside each other. If the 'Overlap Removal Width over Perimeter Width' is less than 0.2, the overlap will not be removed. - -===Turn Extruder Heater Off at Shut Down=== -Default is on. - -When selected, the M104 S0 gcode line will be added to the end of the file to turn the extruder heater off by setting the extruder heater temperature to 0. - -==Examples== -The following examples inset the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and inset.py. - -> python inset.py -This brings up the inset dialog. - -> python inset.py Screw Holder Bottom.stl -The inset tool is parsing the file: -Screw Holder Bottom.stl -.. -The inset tool has created the file: -.. Screw Holder Bottom_inset.gcode - -""" - -from __future__ import absolute_import -try: - import psyco - psyco.full() -except: - pass -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addAlreadyFilledArounds( alreadyFilledArounds, loop, radius ): - """Add already filled loops around loop to alreadyFilledArounds.""" - radius = abs(radius) - alreadyFilledLoop = [] - slightlyGreaterThanRadius = 1.01 * radius - muchGreaterThanRadius = 2.5 * radius - centers = intercircle.getCentersFromLoop( loop, slightlyGreaterThanRadius ) - for center in centers: - alreadyFilledInset = intercircle.getSimplifiedInsetFromClockwiseLoop( center, radius ) - if intercircle.isLargeSameDirection( alreadyFilledInset, center, radius ): - alreadyFilledLoop.append( alreadyFilledInset ) - if len( alreadyFilledLoop ) > 0: - alreadyFilledArounds.append( alreadyFilledLoop ) - -def addSegmentOutline( isThick, outlines, pointBegin, pointEnd, width ): - """Add a diamond or hexagonal outline for a line segment.""" - width = abs( width ) - exclusionWidth = 0.6 * width - slope = 0.2 - if isThick: - slope = 3.0 - exclusionWidth = 0.8 * width - segment = pointEnd - pointBegin - segmentLength = abs(segment) - if segmentLength == 0.0: - return - normalizedSegment = segment / segmentLength - outline = [] - segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) - pointBeginRotated = segmentYMirror * pointBegin - pointEndRotated = segmentYMirror * pointEnd - along = 0.05 - 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 = complex( 0.0, exclusionWidth ) - if alongToWidth > 0.9 * remainingToHalf: - verticalWidth = complex( 0.0, slope * remainingToHalf * segmentLength ) - middle = ( pointBeginIntermediate + pointEndIntermediate ) * 0.5 - middleDown = middle - verticalWidth - middleUp = middle + 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 - verticalWidth - outsideBeginCenterUp = outsideBeginCenter + verticalWidth - outsideEndCenter = euclidean.getIntermediateLocation( alongOutsideEnd, pointBeginRotated, pointEndRotated ) - outsideEndCenterDown = outsideEndCenter - verticalWidth - outsideEndCenterUp = outsideEndCenter + verticalWidth - outline.append( outsideBeginCenterUp ) - outline.append( outsideEndCenterUp ) - outline.append( pointEndIntermediate ) - outline.append( outsideEndCenterDown ) - outline.append( outsideBeginCenterDown ) - outlines.append( euclidean.getPointsRoundZAxis( normalizedSegment, outline ) ) - -def getCraftedText( fileName, text='', repository=None): - """Inset the preface file or text.""" - return getCraftedTextFromText(archive.getTextIfEmpty(fileName, text), repository) - -def getCraftedTextFromText(gcodeText, repository=None): - """Inset the preface gcode text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'inset'): - return gcodeText - if repository is None: - repository = settings.getReadRepository( InsetRepository() ) - return InsetSkein().getCraftedGcode(gcodeText, repository) - -def getInteriorSegments(loops, segments): - """Get segments inside the loops.""" - interiorSegments = [] - for segment in segments: - center = 0.5 * (segment[0].point + segment[1].point) - if euclidean.getIsInFilledRegion(loops, center): - interiorSegments.append(segment) - return interiorSegments - -def getIsIntersectingWithinList(loop, loopList): - """Determine if the loop is intersecting or is within the loop list.""" - leftPoint = euclidean.getLeftPoint(loop) - for otherLoop in loopList: - if euclidean.getNumberOfIntersectionsToLeft(otherLoop, leftPoint) % 2 == 1: - return True - return euclidean.isLoopIntersectingLoops(loop, loopList) - -def getNewRepository(): - """Get new repository.""" - return InsetRepository() - -def getSegmentsFromLoopListsPoints( loopLists, pointBegin, pointEnd ): - """Get endpoint segments from the beginning and end of a line segment.""" - normalizedSegment = pointEnd - pointBegin - normalizedSegmentLength = abs( normalizedSegment ) - if normalizedSegmentLength == 0.0: - return [] - normalizedSegment /= normalizedSegmentLength - segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) - pointBeginRotated = segmentYMirror * pointBegin - pointEndRotated = segmentYMirror * pointEnd - rotatedLoopLists = [] - for loopList in loopLists: - rotatedLoopList = [] - rotatedLoopLists.append( rotatedLoopList ) - for loop in loopList: - rotatedLoop = euclidean.getPointsRoundZAxis( segmentYMirror, loop ) - rotatedLoopList.append( rotatedLoop ) - xIntersectionIndexList = [euclidean.XIntersectionIndex(- 1, pointBeginRotated.real), - euclidean.XIntersectionIndex(- 1, pointEndRotated.real)] - euclidean.addXIntersectionIndexesFromLoopListsY( rotatedLoopLists, xIntersectionIndexList, pointBeginRotated.imag ) - segments = euclidean.getSegmentsFromXIntersectionIndexes( xIntersectionIndexList, pointBeginRotated.imag ) - for segment in segments: - for endpoint in segment: - endpoint.point *= normalizedSegment - return segments - -def isCloseToLast( paths, point, radius ): - """Determine if the point is close to the last point of the last path.""" - if len(paths) < 1: - return False - lastPath = paths[-1] - return abs( lastPath[-1] - point ) < radius - -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 isIntersectingWithinLists( loop, loopLists ): - """Determine if the loop is intersecting or is within the loop lists.""" - for loopList in loopLists: - if getIsIntersectingWithinList( loop, loopList ): - return True - return False - -def writeOutput(fileName, shouldAnalyze=True): - """Inset the carving of a gcode file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'inset', shouldAnalyze) - - -class InsetRepository: - """A class to handle the inset settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.inset.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Inset', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Inset') - self.bridgeWidthMultiplier = settings.FloatSpin().getFromValue( 0.8, 'Bridge Width Multiplier (ratio):', self, 1.2, 1.0 ) - self.loopOrderChoice = settings.MenuButtonDisplay().getFromName('In case of Conflict Solve:', self ) - self.loopOrderAscendingArea = settings.MenuRadio().getFromMenuButtonDisplay( self.loopOrderChoice, 'Prefer Loops', self, False ) - self.loopOrderDescendingArea = settings.MenuRadio().getFromMenuButtonDisplay( self.loopOrderChoice, 'Prefer Perimeter', self, True ) - self.overlapRemovalWidthOverPerimeterWidth = settings.FloatSpin().getFromValue( 0.5, 'Overlap Removal(Scaler):', self, 1.5, 1.0 ) - self.executeTitle = 'Inset' - - def execute(self): - """Inset button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class InsetSkein: - """A class to inset a skein of extrusions.""" - def __init__(self): - self.boundary = None - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.layerCount = settings.LayerCount() - self.lineIndex = 0 - self.rotatedLoopLayer = None - - def addGcodeFromPerimeterPaths(self, isIntersectingSelf, loop, loopLists, radius, rotatedLoopLayer): - """Add the perimeter paths to the output.""" - segments = [] - outlines = [] - thickOutlines = [] - allLoopLists = loopLists[:] + [thickOutlines] - aroundLists = loopLists - for pointIndex in xrange(len(loop)): - pointBegin = loop[pointIndex] - pointEnd = loop[(pointIndex + 1) % len(loop)] - if isIntersectingSelf: - if euclidean.isLineIntersectingLoops(outlines, pointBegin, pointEnd): - segments += getSegmentsFromLoopListsPoints(allLoopLists, pointBegin, pointEnd) - else: - segments += getSegmentsFromLoopListsPoints(loopLists, pointBegin, pointEnd) - addSegmentOutline(False, outlines, pointBegin, pointEnd, self.overlapRemovalWidth) - addSegmentOutline(True, thickOutlines, pointBegin, pointEnd, self.overlapRemovalWidth) - else: - segments += getSegmentsFromLoopListsPoints(loopLists, pointBegin, pointEnd) - perimeterPaths = [] - path = [] - muchSmallerThanRadius = 0.1 * radius - segments = getInteriorSegments(rotatedLoopLayer.loops, segments) - for segment in segments: - pointBegin = segment[0].point - if not isCloseToLast(perimeterPaths, pointBegin, muchSmallerThanRadius): - path = [pointBegin] - perimeterPaths.append(path) - path.append(segment[1].point) - if len(perimeterPaths) > 1: - firstPath = perimeterPaths[0] - lastPath = perimeterPaths[-1] - if abs(lastPath[-1] - firstPath[0]) < 0.1 * muchSmallerThanRadius: - connectedBeginning = lastPath[: -1] + firstPath - perimeterPaths[0] = connectedBeginning - perimeterPaths.remove(lastPath) - muchGreaterThanRadius = 6.0 * radius - for perimeterPath in perimeterPaths: - if euclidean.getPathLength(perimeterPath) > muchGreaterThanRadius: - self.distanceFeedRate.addGcodeFromThreadZ(perimeterPath, rotatedLoopLayer.z) - - def addGcodeFromRemainingLoop(self, loop, loopLists, radius, rotatedLoopLayer): - """Add the remainder of the loop which does not overlap the alreadyFilledArounds loops.""" - centerOutset = intercircle.getLargestCenterOutsetLoopFromLoopRegardless(loop, radius) - euclidean.addSurroundingLoopBeginning(self.distanceFeedRate, centerOutset.outset, rotatedLoopLayer.z) - self.addGcodePerimeterBlockFromRemainingLoop(centerOutset.center, loopLists, radius, rotatedLoopLayer) - self.distanceFeedRate.addLine('()') - self.distanceFeedRate.addLine('()') - - def addGcodePerimeterBlockFromRemainingLoop(self, loop, loopLists, radius, rotatedLoopLayer): - """Add the perimter block remainder of the loop which does not overlap the alreadyFilledArounds loops.""" - if self.repository.overlapRemovalWidthOverPerimeterWidth.value < 0.2: - self.distanceFeedRate.addPerimeterBlock(loop, rotatedLoopLayer.z) - return - isIntersectingSelf = isIntersectingItself(loop, self.overlapRemovalWidth) - if isIntersectingWithinLists(loop, loopLists) or isIntersectingSelf: - self.addGcodeFromPerimeterPaths(isIntersectingSelf, loop, loopLists, radius, rotatedLoopLayer) - else: - self.distanceFeedRate.addPerimeterBlock(loop, rotatedLoopLayer.z) - addAlreadyFilledArounds(loopLists, loop, self.overlapRemovalWidth) - - def addInitializationToOutput(self): - """Add initialization gcode to the output.""" - - def addInset(self, rotatedLoopLayer): - """Add inset to the layer.""" - alreadyFilledArounds = [] - halfWidth = self.halfPerimeterWidth - if rotatedLoopLayer.rotation is not None: - halfWidth *= self.repository.bridgeWidthMultiplier.value - self.distanceFeedRate.addTagBracketedLine('bridgeRotation', rotatedLoopLayer.rotation) - extrudateLoops = intercircle.getInsetLoopsFromLoops(halfWidth, rotatedLoopLayer.loops) - triangle_mesh.sortLoopsInOrderOfArea(not self.repository.loopOrderAscendingArea.value, extrudateLoops) - for extrudateLoop in extrudateLoops: - self.addGcodeFromRemainingLoop(extrudateLoop, alreadyFilledArounds, halfWidth, rotatedLoopLayer) - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the bevel gcode.""" - self.repository = repository - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - for line in self.lines[self.lineIndex :]: - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '(': - self.addInitializationToOutput() - self.distanceFeedRate.addTagBracketedLine( - 'bridgeWidthMultiplier', self.distanceFeedRate.getRounded( self.repository.bridgeWidthMultiplier.value ) ) - elif firstWord == '()': - self.distanceFeedRate.addTagBracketedLine('procedureName', 'inset') - return - elif firstWord == '(': - self.layerThickness = float(splitLine[1]) - elif firstWord == '(': - self.perimeterWidth = float(splitLine[1]) - self.halfPerimeterWidth = 0.5 * self.perimeterWidth - self.overlapRemovalWidth = (self.halfPerimeterWidth + self.layerThickness/2) * ((math.pi/4) * self.repository.overlapRemovalWidthOverPerimeterWidth.value) - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the inset skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == '(': - location = gcodec.getLocationFromSplitLine(None, splitLine) - self.boundary.append(location.dropAxis()) - elif firstWord == '(': - secondWordWithoutBrackets = splitLine[1].replace('(', '').replace(')', '') - self.rotatedLoopLayer.rotation = complex(secondWordWithoutBrackets) - return - elif firstWord == '(': - self.layerCount.printProgressIncrement('inset') - self.rotatedLoopLayer = euclidean.RotatedLoopLayer(float(splitLine[1])) - self.distanceFeedRate.addLine(line) - elif firstWord == '()': - self.addInset( self.rotatedLoopLayer ) - self.rotatedLoopLayer = None - elif firstWord == '()': - self.boundary = [] - self.rotatedLoopLayer.loops.append( self.boundary ) - if self.rotatedLoopLayer is None: - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the inset dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/jitter.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/jitter.py deleted file mode 100644 index 7c1e870..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/jitter.py +++ /dev/null @@ -1,256 +0,0 @@ -""" -This page is in the table of contents. -Jitter jitters the loop end position to a different place on each layer to prevent the a ridge from forming. - -The jitter manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Jitter - -==Operation== -The default 'Activate Jitter' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Jitter Over Perimeter Width=== -Default is two. - -Defines the amount the loop ends will be jittered over the perimeter width. -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. - -==Examples== -The following examples jitter the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder -which contains Screw Holder Bottom.stl and jitter.py. - -> python jitter.py -This brings up the jitter dialog. - -> python jitter.py Screw Holder Bottom.stl -The jitter tool is parsing the file: -Screw Holder Bottom.stl -.. -The jitter tool has created the file: -.. Screw Holder Bottom_jitter.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. - -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, text, jitterRepository = None ): - """Jitter a gcode linear move text.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, text), jitterRepository ) - -def getCraftedTextFromText( gcodeText, jitterRepository = None ): - """Jitter a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'jitter'): - return gcodeText - if jitterRepository is None: - jitterRepository = settings.getReadRepository( JitterRepository() ) - if not jitterRepository.activateJitter.value: - return gcodeText - return JitterSkein().getCraftedGcode( jitterRepository, gcodeText ) - -def getJitteredLoop( jitterDistance, jitterLoop ): - """Get a jittered loop path.""" - loopLength = euclidean.getLoopLength( 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 += abs(firstPoint - secondPoint) - remainingLength = jitterPosition - lastLength - pointIndex = pointIndex % len( jitterLoop ) - ultimateJitteredPoint = jitterLoop[pointIndex] - penultimateJitteredPointIndex = ( pointIndex + len( jitterLoop ) - 1 ) % len( jitterLoop ) - penultimateJitteredPoint = jitterLoop[ penultimateJitteredPointIndex ] - segment = ultimateJitteredPoint - penultimateJitteredPoint - segmentLength = abs(segment) - originalOffsetLoop = euclidean.getAroundLoop( pointIndex, pointIndex, jitterLoop ) - if segmentLength <= 0.0: - return originalOffsetLoop - newUltimatePoint = penultimateJitteredPoint + segment * remainingLength / segmentLength - return [newUltimatePoint] + originalOffsetLoop - -def getNewRepository(): - """Get new repository.""" - return JitterRepository() - -def isLoopNumberEqual( betweenX, betweenXIndex, loopNumber ): - """Determine if the loop number is equal.""" - if betweenXIndex >= len( betweenX ): - return False - return betweenX[ betweenXIndex ].index == loopNumber - -def writeOutput(fileName, shouldAnalyze=True): - """Jitter a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'jitter', shouldAnalyze) - - -class JitterRepository: - """A class to handle the jitter settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.jitter.html', self) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Jitter', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Jitter') - self.activateJitter = settings.BooleanSetting().getFromValue('Activate Jitter to have your perimeter and loop endpoints scattered', self, False) - self.jitterOverPerimeterWidth = settings.FloatSpin().getFromValue(0.0, 'Jitter Over Perimeter Width (ratio):', self, 10.0, 2.0) - self.executeTitle = 'Jitter' - - def execute(self): - """Jitter button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class JitterSkein: - """A class to jitter a skein of extrusions.""" - def __init__(self): - """Initialize.""" - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.feedRateMinute = None - self.isLoopPerimeter = False - self.layerCount = settings.LayerCount() - self.layerGolden = 0.0 - self.lineIndex = 0 - self.lines = None - self.loopPath = None - self.oldLocation = None - self.operatingFeedRatePerMinute = None - self.travelFeedRateMinute = None - - def addGcodeFromThreadZ( self, thread, z ): - """Add a gcode thread to the output.""" - if len(thread) > 0: - self.addGcodeMovementZ( self.travelFeedRateMinute, thread[0], z ) - else: - print('zero length vertex positions array which was skipped over, this should never happen.') - if len(thread) < 2: - return - self.distanceFeedRate.addLine('M101') - self.addGcodePathZ( self.feedRateMinute, thread[1 :], z ) - - def addGcodeMovementZ(self, feedRateMinute, point, z): - """Add a movement to the output.""" - if feedRateMinute is None: - feedRateMinute = self.operatingFeedRatePerMinute - self.distanceFeedRate.addGcodeMovementZWithFeedRate(feedRateMinute, point, z) - - def addGcodePathZ( self, feedRateMinute, path, z ): - """Add a gcode path, without modifying the extruder, to the output.""" - for point in path: - self.addGcodeMovementZ(feedRateMinute, point, z) - - def addTailoredLoopPath(self): - """Add a clipped and jittered loop path.""" - loop = getJitteredLoop(self.layerJitter, self.loopPath.path[: -1]) - loop = euclidean.getAwayPoints(loop, 0.2 * self.perimeterWidth) - self.addGcodeFromThreadZ(loop + [loop[0]], self.loopPath.z) - self.loopPath = None - - def getCraftedGcode(self, jitterRepository, gcodeText): - """Parse gcode text and store the jitter gcode.""" - if jitterRepository.jitterOverPerimeterWidth.value == 0.0: - print('Warning, Jitter Over Perimeter Width is zero so thing will be done.') - return gcodeText - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization(jitterRepository) - for self.lineIndex in xrange(self.lineIndex, len(self.lines)): - self.parseLine(self.lines[self.lineIndex]) - return self.distanceFeedRate.output.getvalue() - - def parseInitialization( self, jitterRepository ): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( jitter )') - return - elif firstWord == '(': - self.operatingFeedRatePerMinute = 60.0 * float(splitLine[1]) - elif firstWord == '(': - self.perimeterWidth = float(splitLine[1]) - self.jitter = jitterRepository.jitterOverPerimeterWidth.value * self.perimeterWidth - elif firstWord == '(': - self.travelFeedRateMinute = 60.0 * float(splitLine[1]) - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line, jitter it and add it to the jitter skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - self.setFeedRateLocationLoopPath(line, splitLine) - if self.loopPath is not None: - self.loopPath.path.append(self.oldLocation.dropAxis()) - return - elif firstWord == 'M101': - if self.loopPath is not None: - return - elif firstWord == 'M103': - self.isLoopPerimeter = False - if self.loopPath is not None: - self.addTailoredLoopPath() - elif firstWord == '(': - self.layerCount.printProgressIncrement('jitter') - self.layerGolden = math.fmod(self.layerGolden + 0.61803398874989479, 1.0) - self.layerJitter = self.jitter * self.layerGolden - 0.5 - elif firstWord == '(' or firstWord == '(': - self.isLoopPerimeter = True - self.distanceFeedRate.addLine(line) - - def setFeedRateLocationLoopPath(self, line, splitLine): - """Set the feedRateMinute, oldLocation and loopPath.""" - self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) - self.oldLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - if not self.isLoopPerimeter or self.loopPath is not None: - return - for afterIndex in xrange(self.lineIndex + 1, len(self.lines)): - line = self.lines[afterIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1' or firstWord == 'M103': - return - elif firstWord == 'M101': - self.loopPath = euclidean.PathZ(self.oldLocation.z) - return - - -def main(): - """Display the jitter dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/lash.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/lash.py deleted file mode 100644 index 2ea46c9..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/lash.py +++ /dev/null @@ -1,171 +0,0 @@ -""" -This page is in the table of contents. -Lash is a script to partially compensate for the backlash of the tool head. - -The lash manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Lash - -The lash tool is ported from Erik de Bruijn's 3D-to-5D-Gcode php GPL'd script at: -http://objects.reprap.org/wiki/3D-to-5D-Gcode.php - -The default values are from the settings in Erik's 3D-to-5D-Gcode, I believe the settings are used on his Darwin reprap. - -==Operation== -The default 'Activate Lash' checkbox is off. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===X Backlash=== -Default is 0.2 millimeters. - -Defines the distance the tool head will be lashed in the X direction. - -===Y Backlash=== -Default is 0.2 millimeters. - -Defines the distance the tool head will be lashed in the Y direction. - -==Examples== -The following examples lash the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and lash.py. - -> python lash.py -This brings up the lash dialog. - -> python lash.py Screw Holder Bottom.stl -The lash tool is parsing the file: -Screw Holder Bottom.stl -.. -The lash tool has created the file: -.. Screw Holder Bottom_lash.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, text, lashRepository = None ): - """Get a lashed gcode linear move text.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, text), lashRepository ) - -def getCraftedTextFromText( gcodeText, lashRepository = None ): - """Get a lashed gcode linear move text from text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'lash'): - return gcodeText - if lashRepository is None: - lashRepository = settings.getReadRepository( LashRepository() ) - if not lashRepository.activateLash.value: - return gcodeText - return LashSkein().getCraftedGcode( gcodeText, lashRepository ) - -def getNewRepository(): - """Get new repository.""" - return LashRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Lash a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'lash', shouldAnalyze) - - -class LashRepository: - """A class to handle the lash settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.lash.html', self) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Lash', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Lash') - self.activateLash = settings.BooleanSetting().getFromValue('Activate Lash if you have backlash in your axes. \nBut its better to fix the mechanical problem!', self, False ) - self.xBacklash = settings.FloatSpin().getFromValue( 0.0, 'X Backlash (mm):', self, 0.5, 0.0 ) - self.yBacklash = settings.FloatSpin().getFromValue( 0.0, 'Y Backlash (mm):', self, 0.5, 0.0 ) - self.executeTitle = 'Lash' - - def execute(self): - """Lash button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class LashSkein: - """A class to lash a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.feedRateMinute = 958.0 - self.lineIndex = 0 - self.lines = None - self.oldLocation = None - - def getCraftedGcode( self, gcodeText, lashRepository ): - """Parse gcode text and store the lash gcode.""" - self.lines = archive.getTextLines(gcodeText) - self.lashRepository = lashRepository - self.xBacklash = lashRepository.xBacklash.value - self.yBacklash = lashRepository.yBacklash.value - self.parseInitialization() - for self.lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[self.lineIndex] - self.parseLash(line) - return self.distanceFeedRate.output.getvalue() - - def getLashedLine( self, line, location, splitLine ): - """Get lashed gcode line.""" - if self.oldLocation is None: - return line - if location.x > self.oldLocation.x: - line = self.distanceFeedRate.getLineWithX( line, splitLine, location.x + self.xBacklash ) - else: - line = self.distanceFeedRate.getLineWithX( line, splitLine, location.x - self.xBacklash ) - if location.y > self.oldLocation.y: - line = self.distanceFeedRate.getLineWithY( line, splitLine, location.y + self.yBacklash ) - else: - line = self.distanceFeedRate.getLineWithY( line, splitLine, location.y - self.yBacklash ) - return line - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( lash )') - return - self.distanceFeedRate.addLine(line) - - def parseLash(self, line): - """Parse a gcode line and add it to the lash skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - line = self.getLashedLine( line, location, splitLine ) - self.oldLocation = location - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the lash dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/limit.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/limit.py deleted file mode 100644 index b6bba93..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/limit.py +++ /dev/null @@ -1,198 +0,0 @@ -#! /usr/bin/env python -""" -This page is in the table of contents. - -Limit limts the feed rate of the tool head, so that the stepper motors are not driven too fast and skip steps. - -==Operation== -The default 'Activate Limit' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Maximum Initial Feed Rate=== -Default is one millimeter per second. - -Defines the maximum speed of the inital tool head will move. - -===Maximum Z Feed Rate=== -Default is one millimeter per second. - -If your firmware limits the z feed rate, you do not need to set this setting. - -Defines the maximum speed that the tool head will move in the z direction. - -==Examples== -The following examples limit the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and limit.py. - -> python limit.py -This brings up the limit dialog. - -> python limit.py Screw Holder Bottom.stl -The limit tool is parsing the file: -Screw Holder Bottom.stl -.. -The limit tool has created the file: -.. Screw Holder Bottom_limit.gcode - -""" - -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/28/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText(fileName, gcodeText='', repository=None): - """Limit a gcode file or text.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, gcodeText), repository ) - -def getCraftedTextFromText(gcodeText, repository=None): - """Limit a gcode text.""" - if gcodec.isProcedureDoneOrFileIsEmpty(gcodeText, 'limit'): - return gcodeText - if repository is None: - repository = settings.getReadRepository(LimitRepository()) - if not repository.activateLimit.value: - return gcodeText - return LimitSkein().getCraftedGcode(gcodeText, repository) - -def getNewRepository(): - """Get new repository.""" - return LimitRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Limit a gcode file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'limit', shouldAnalyze) - - -class LimitRepository: - """A class to handle the limit settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.limit.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Limit', self, '') - self.activateLimit = settings.BooleanSetting().getFromValue('Activate Limit if your Firmware is unable to Limiting your Z-Speed.', self, False) - self.maximumInitialFeedRate = settings.FloatSpin().getFromValue(0.5, 'Maximum Initial Feed Rate (mm/s):', self, 10.0, 5.0) - self.maximumZFeedRatePerSecond = settings.FloatSpin().getFromValue(0.5, 'Maximum Z Feed Rate (mm/s):', self, 10.0, 5.0) - self.executeTitle = 'Limit' - - def execute(self): - """Limit button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class LimitSkein: - """A class to limit a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.feedRateMinute = None - self.lineIndex = 0 - self.oldLocation = None - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the limit gcode.""" - self.maximumZDrillFeedRatePerSecond = repository.maximumZFeedRatePerSecond.value - self.maximumZTravelFeedRatePerSecond = repository.maximumZFeedRatePerSecond.value - self.maximumZFeedRatePerSecond = self.maximumZTravelFeedRatePerSecond - self.repository = repository - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - for lineIndex in xrange(self.lineIndex, len(self.lines)): - self.parseLine( lineIndex ) - return self.distanceFeedRate.output.getvalue() - - def getLimitedInitialMovement(self, line, splitLine): - """Get a limited linear movement.""" - if self.oldLocation is None: - line = self.distanceFeedRate.getLineWithFeedRate(60.0 * self.repository.maximumInitialFeedRate.value, line, splitLine) - return line - - def getZLimitedLine(self, deltaZ, distance, line, splitLine): - """Get a replaced z limited gcode movement line.""" - zFeedRateSecond = self.feedRateMinute * deltaZ / distance / 60.0 - if zFeedRateSecond <= self.maximumZFeedRatePerSecond: - return line - limitedFeedRateMinute = self.feedRateMinute * self.maximumZFeedRatePerSecond / zFeedRateSecond - return self.distanceFeedRate.getLineWithFeedRate(limitedFeedRateMinute, line, splitLine) - - def getZLimitedLineArc(self, line, splitLine): - """Get a replaced z limited gcode arc movement line.""" - self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) - if self.feedRateMinute is None or self.oldLocation is None: - return line - relativeLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - self.oldLocation += relativeLocation - deltaZ = abs(relativeLocation.z) - distance = gcodec.getArcDistance(relativeLocation, splitLine) - return self.getZLimitedLine(deltaZ, distance, line, splitLine) - - def getZLimitedLineLinear(self, line, location, splitLine): - """Get a replaced z limited gcode linear movement line.""" - self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) - if location == self.oldLocation: - return '' - if self.feedRateMinute is None or self.oldLocation is None: - return line - deltaZ = abs(location.z - self.oldLocation.z) - distance = abs(location - self.oldLocation) - return self.getZLimitedLine(deltaZ, distance, line, splitLine) - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( limit )') - return - elif firstWord == '(': - self.maximumZDrillFeedRatePerSecond = float(splitLine[1]) - elif firstWord == '(': - self.distanceFeedRate.addTagBracketedLine('maximumZTravelFeedRatePerSecond', self.maximumZTravelFeedRatePerSecond ) - self.distanceFeedRate.addLine(line) - - def parseLine( self, lineIndex ): - """Parse a gcode line and add it to the limit skein.""" - line = self.lines[lineIndex].lstrip() - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - line = self.getLimitedInitialMovement(line, splitLine) - line = self.getZLimitedLineLinear(line, location, splitLine) - self.oldLocation = location - elif firstWord == 'G2' or firstWord == 'G3': - line = self.getZLimitedLineArc(line, splitLine) - elif firstWord == 'M101': - self.maximumZFeedRatePerSecond = self.maximumZDrillFeedRatePerSecond - elif firstWord == 'M103': - self.maximumZFeedRatePerSecond = self.maximumZTravelFeedRatePerSecond - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the limit dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/multiply.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/multiply.py deleted file mode 100644 index 96cc2c1..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/multiply.py +++ /dev/null @@ -1,274 +0,0 @@ -""" -This page is in the table of contents. -Multiply is a script to multiply the shape into an array of copies arranged in a table. - -The multiply manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Multiply - -Besides using the multiply tool, another way of printing many copies of the model is to duplicate the model in Art of Illusion, however many times you want, with the appropriate offsets. Then you can either use the Join Objects script in the scripts submenu to create a combined shape or you can export the whole scene as an xml file, which skeinforge can then slice. - -==Operation== -The default 'Activate Multiply' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Center=== -Default is the origin. - -The center of the shape will be moved to the "Center X" and "Center Y" coordinates. - -====Center X==== -====Center Y==== - -===Number of Cells=== -====Number of Columns==== -Default is one. - -Defines the number of columns in the array table. - -====Number of Rows==== -Default is one. - -Defines the number of rows in the table. - -===Separation over Perimeter Width=== -Default is fifteen. - -Defines the ratio of separation between the shape copies over the extrusion width. - -==Examples== -The following examples multiply the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and multiply.py. - -> python multiply.py -This brings up the multiply dialog. - -> python multiply.py Screw Holder Bottom.stl -The multiply tool is parsing the file: -Screw Holder Bottom.stl -.. -The multiply tool has created the file: -.. Screw Holder Bottom_multiply.gcode - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText(fileName, text='', repository=None): - """Multiply the fill file or text.""" - return getCraftedTextFromText(archive.getTextIfEmpty(fileName, text), repository) - -def getCraftedTextFromText(gcodeText, repository=None): - """Multiply the fill text.""" - if gcodec.isProcedureDoneOrFileIsEmpty(gcodeText, 'multiply'): - return gcodeText - if repository is None: - repository = settings.getReadRepository(MultiplyRepository()) - if not repository.activateMultiply.value: - return gcodeText - return MultiplySkein().getCraftedGcode(gcodeText, repository) - -def getNewRepository(): - """Get new repository.""" - return MultiplyRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Multiply a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'multiply', shouldAnalyze) - - -class MultiplyRepository: - """A class to handle the multiply settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.multiply.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( - fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Multiply', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Multiply') - self.activateMultiply = settings.BooleanSetting().getFromValue('Activate Multiply: ', self, True ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Center - (Set half your total x and y travel distance \nfor centering your prints!', self ) - self.centerX = settings.FloatSpin().getFromValue(-240.0, 'Center X (mm):', self, 240.0, 100.0) - self.centerY = settings.FloatSpin().getFromValue(-240.0, 'Center Y (mm):', self, 240.0, 100.0) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Number of Cells -', self) - self.numberOfColumns = settings.IntSpin().getFromValue(1, 'Number of Columns (integer):', self, 10, 1) - self.numberOfRows = settings.IntSpin().getFromValue(1, 'Number of Rows (integer):', self, 10, 1) - settings.LabelSeparator().getFromRepository(self) - self.separationOverPerimeterWidth = settings.FloatSpin().getFromValue( - 5.0, 'Separation over Perimeter Width (ratio):', self, 25.0, 15.0) - self.executeTitle = 'Multiply' - - def execute(self): - """Multiply button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode( - self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class MultiplySkein: - """A class to multiply a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.isExtrusionActive = False - self.layerCount = settings.LayerCount() - self.layerIndex = 0 - self.layerLines = [] - self.lineIndex = 0 - self.lines = None - self.oldLocation = None - self.rowIndex = 0 - self.shouldAccumulate = True - - def addElement(self, offset): - """Add moved element to the output.""" - for line in self.layerLines: - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1': - movedLocation = self.getMovedLocationSetOldLocation(offset, splitLine) - line = self.distanceFeedRate.getLinearGcodeMovement(movedLocation.dropAxis(), movedLocation.z) - elif firstWord == '(': - movedLocation = self.getMovedLocationSetOldLocation(offset, splitLine) - line = self.distanceFeedRate.getBoundaryLine(movedLocation) - self.distanceFeedRate.addLine(line) - - def addLayer(self): - """Add multiplied layer to the output.""" - self.layerCount.printProgressIncrement('multiply') - self.addRemoveThroughLayer() - offset = self.centerOffset - self.arrayCenter - self.shapeCenter - for rowIndex in xrange(self.repository.numberOfRows.value): - yRowOffset = float(rowIndex) * self.extentPlusSeparation.imag - if self.layerIndex % 2 == 1: - yRowOffset = self.arrayExtent.imag - yRowOffset - for columnIndex in xrange(self.repository.numberOfColumns.value): - xColumnOffset = float(columnIndex) * self.extentPlusSeparation.real - if self.rowIndex % 2 == 1: - xColumnOffset = self.arrayExtent.real - xColumnOffset - elementOffset = complex(offset.real + xColumnOffset, offset.imag + yRowOffset) - self.addElement(elementOffset) - self.rowIndex += 1 - if len(self.layerLines) > 1: - self.layerIndex += 1 - self.layerLines = [] - - def addRemoveThroughLayer(self): - """Parse gcode initialization and store the parameters.""" - for layerLineIndex in xrange(len(self.layerLines)): - line = self.layerLines[layerLineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.addLine(line) - if firstWord == '(': - self.layerLines = self.layerLines[layerLineIndex + 1 :] - return - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the multiply gcode.""" - self.centerOffset = complex(repository.centerX.value, repository.centerY.value) - self.repository = repository - self.numberOfColumns = repository.numberOfColumns.value - self.numberOfRows = repository.numberOfRows.value - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - self.setCorners() - for line in self.lines[self.lineIndex :]: - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getMovedLocationSetOldLocation(self, offset, splitLine): - """Get the moved location and set the old location.""" - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - self.oldLocation = location - return Vector3(location.x + offset.real, location.y + offset.imag, location.z) - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( multiply )') - self.distanceFeedRate.addLine(line) - self.lineIndex += 1 - return - elif firstWord == '(': - self.absolutePerimeterWidth = abs(float(splitLine[1])) - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the multiply skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == '()': - self.addLayer() - self.distanceFeedRate.addLine(line) - return - elif firstWord == '()': - self.shouldAccumulate = False - if self.shouldAccumulate: - self.layerLines.append(line) - return - self.distanceFeedRate.addLine(line) - - def setCorners(self): - """Set maximum and minimum corners and z.""" - cornerMaximumComplex = complex(-987654321.0, -987654321.0) - cornerMinimumComplex = -cornerMaximumComplex - for line in self.lines[self.lineIndex :]: - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1': - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - if self.isExtrusionActive: - locationComplex = location.dropAxis() - cornerMaximumComplex = euclidean.getMaximum(locationComplex, cornerMaximumComplex) - cornerMinimumComplex = euclidean.getMinimum(locationComplex, cornerMinimumComplex) - self.oldLocation = location - elif firstWord == 'M101': - self.isExtrusionActive = True - elif firstWord == 'M103': - self.isExtrusionActive = False - self.extent = cornerMaximumComplex - cornerMinimumComplex - self.shapeCenter = 0.5 * (cornerMaximumComplex + cornerMinimumComplex) - self.separation = self.repository.separationOverPerimeterWidth.value * self.absolutePerimeterWidth - self.extentPlusSeparation = self.extent + complex(self.separation, self.separation) - columnsMinusOne = self.numberOfColumns - 1 - rowsMinusOne = self.numberOfRows - 1 - self.arrayExtent = complex(self.extentPlusSeparation.real * columnsMinusOne, self.extentPlusSeparation.imag * rowsMinusOne) - self.arrayCenter = 0.5 * self.arrayExtent - - -def main(): - """Display the multiply dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor(getNewRepository()) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/preface.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/preface.py deleted file mode 100644 index 1d0f114..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/preface.py +++ /dev/null @@ -1,221 +0,0 @@ -#! /usr/bin/env python -""" -This page is in the table of contents. -Preface converts the svg slices into gcode extrusion layers, optionally prefaced with some gcode commands. - -The preface manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Preface - -==Settings== -===Meta=== -Default is empty. - -The 'Meta' field is to add meta tags or a note to all your files. Whatever is in that field will be added in a meta tagged line to the output. - -===Name of Alteration Files=== -Preface looks for alteration files in the alterations folder in the .skeinforge folder in the home directory. Preface does not care if the text file names are capitalized, but some file systems do not handle file name cases properly, so to be on the safe side you should give them lower case names. If it doesn't find the file it then looks in the alterations folder in the skeinforge_plugins folder. - -====Name of End File==== -Default is end.gcode. - -If there is a file with the name of the "Name of End File" setting, it will be added to the very end of the gcode. - -====Name of Start File==== -Default is start.gcode. - -If there is a file with the name of the "Name of Start File" setting, it will be added to the very beginning of the gcode. - -===Set Positioning to Absolute=== -Default is on. - -When selected, preface will add the G90 command to set positioning to absolute. - -===Set Units to Millimeters=== -Default is on. - -When selected, preface will add the G21 command to set the units to millimeters. - -===Start at Home=== -Default is off. - -When selected, the G28 go to home gcode will be added at the beginning of the file. - -===Turn Extruder Off=== -====Turn Extruder Off at Shut Down==== -Default is on. - -When selected, the M103 turn extruder off gcode will be added at the end of the file. - -====Turn Extruder Off at Start Up==== -Default is on. - -When selected, the M103 turn extruder off gcode will be added at the beginning of the file. - -==Examples== -The following examples preface the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and preface.py. - -> python preface.py -This brings up the preface dialog. - -> python preface.py Screw Holder Bottom.stl -The preface tool is parsing the file: -Screw Holder Bottom.stl -.. -The preface tool has created the file: -.. Screw Holder Bottom_preface.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from datetime import date -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.svg_reader import SVGReader -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import os -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, text='', repository = None ): - """Preface and convert an svg file or text.""" - return getCraftedTextFromText(archive.getTextIfEmpty(fileName, text), repository) - -def getCraftedTextFromText( text, repository = None ): - """Preface and convert an svg text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( text, 'preface'): - return text - if repository is None: - repository = settings.getReadRepository(PrefaceRepository()) - return PrefaceSkein().getCraftedGcode(repository, text) - -def getNewRepository(): - """Get new repository.""" - return PrefaceRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Preface the carving of a gcode file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'preface', shouldAnalyze) - - -class PrefaceRepository: - """A class to handle the preface settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.preface.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Preface', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Preface') - self.meta = settings.StringSetting().getFromValue('Meta:', self, '') - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Name of Alteration Files -', self ) - self.nameOfEndFile = settings.StringSetting().getFromValue('Name of End File:', self, 'end.gcode') - self.nameOfStartFile = settings.StringSetting().getFromValue('Name of Start File:', self, 'start.gcode') - settings.LabelSeparator().getFromRepository(self) - self.setPositioningToAbsolute = settings.BooleanSetting().getFromValue('Set Positioning to Absolute', self, True ) - self.setUnitsToMillimeters = settings.BooleanSetting().getFromValue('Set Units to Millimeters', self, True ) - self.startAtHome = settings.BooleanSetting().getFromValue('Home before Print', self, False ) - self.resetExtruder = settings.BooleanSetting().getFromValue('Reset Extruder before Print', self, True ) - settings.LabelSeparator().getFromRepository(self) - self.executeTitle = 'Preface' - - def execute(self): - """Preface button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class PrefaceSkein: - """A class to preface a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.extruderActive = False - self.lineIndex = 0 - self.oldLocation = None - self.svgReader = SVGReader() - - - - def addFromUpperLowerFile(self, fileName): - """Add lines of text from the fileName or the lowercase fileName, if there is no file by the original fileName in the directory.""" - self.distanceFeedRate.addLinesSetAbsoluteDistanceMode(settings.getLinesInAlterationsOrGivenDirectory(fileName)) - - def addInitializationToOutput(self): - """Add initialization gcode to the output.""" - self.addFromUpperLowerFile(self.repository.nameOfStartFile.value) # Add a start file if it exists. - self.distanceFeedRate.addTagBracketedLine('creation', 'skeinforge') # GCode formatted comment - absoluteFilePathUntilDot = os.path.abspath(__file__)[: os.path.abspath(__file__).rfind('.')] - if absoluteFilePathUntilDot == '/home/enrique/Desktop/backup/babbleold/script/reprap/fabmetheus/skeinforge_application/skeinforge_plugins/craft_plugins/preface': #is this script on Enrique's computer? - archive.writeFileText(archive.getVersionFileName(), date.today().isoformat().replace('-', '.')[2 :]) - versionText = archive.getFileText(archive.getVersionFileName()) - self.distanceFeedRate.addTagBracketedLine('version', versionText) # GCode formatted comment - self.distanceFeedRate.addLine('()') # GCode formatted comment - if self.repository.setPositioningToAbsolute.value: - self.distanceFeedRate.addLine('G90 ;set positioning to absolute') # Set positioning to absolute. - if self.repository.setUnitsToMillimeters.value: - self.distanceFeedRate.addLine('G21 ;set units to millimeters') # Set units to millimeters. - if self.repository.startAtHome.value: - self.distanceFeedRate.addLine('G28 ;start at home') # Start at home. - if self.repository.resetExtruder.value: - self.distanceFeedRate.addLine('G92 E0 ;reset extruder distance') # Start at home. - craftTypeName = skeinforge_profile.getCraftTypeName() - self.distanceFeedRate.addTagBracketedLine('craftTypeName', craftTypeName) - self.distanceFeedRate.addTagBracketedLine('decimalPlacesCarried', self.distanceFeedRate.decimalPlacesCarried) - layerThickness = float(self.svgReader.sliceDictionary['layerThickness']) - self.distanceFeedRate.addTagRoundedLine('layerThickness', layerThickness) - if self.repository.meta.value: - self.distanceFeedRate.addTagBracketedLine('meta', self.repository.meta.value) - perimeterWidth = float(self.svgReader.sliceDictionary['perimeterWidth']) - self.distanceFeedRate.addTagRoundedLine('perimeterWidth', perimeterWidth) - self.distanceFeedRate.addTagBracketedLine('profileName', skeinforge_profile.getProfileName(craftTypeName)) - procedureNames = self.svgReader.sliceDictionary['procedureName'].replace(',', ' ').split() - for procedureName in procedureNames: - self.distanceFeedRate.addTagBracketedLine('procedureName', procedureName) - self.distanceFeedRate.addTagBracketedLine('procedureName', 'preface') - self.distanceFeedRate.addLine('()') # Initialization is finished, extrusion is starting. - self.distanceFeedRate.addLine('()') # Initialization is finished, crafting is starting. - - def addPreface( self, rotatedLoopLayer ): - """Add preface to the carve layer.""" - self.distanceFeedRate.addLine('( %s )' % rotatedLoopLayer.z ) # Indicate that a new layer is starting. - if rotatedLoopLayer.rotation is not None: - self.distanceFeedRate.addTagBracketedLine('bridgeRotation', str( rotatedLoopLayer.rotation ) ) # Indicate the bridge rotation. - for loop in rotatedLoopLayer.loops: - self.distanceFeedRate.addGcodeFromLoop(loop, rotatedLoopLayer.z) - self.distanceFeedRate.addLine('()') - - def getCraftedGcode( self, repository, gcodeText ): - """Parse gcode text and store the bevel gcode.""" - self.repository = repository - self.svgReader.parseSVG('', gcodeText) - if self.svgReader.sliceDictionary is None: - print('Warning, nothing will be done because the sliceDictionary could not be found getCraftedGcode in preface.') - return '' - self.distanceFeedRate.decimalPlacesCarried = int(self.svgReader.sliceDictionary['decimalPlacesCarried']) - self.addInitializationToOutput() - for rotatedLoopLayerIndex, rotatedLoopLayer in enumerate(self.svgReader.rotatedLoopLayers): - settings.printProgressByNumber(rotatedLoopLayerIndex, len(self.svgReader.rotatedLoopLayers), 'preface') - self.addPreface( rotatedLoopLayer ) - return self.distanceFeedRate.output.getvalue() - - -def main(): - """Display the preface dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/raft.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/raft.py deleted file mode 100644 index 35ba22f..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/raft.py +++ /dev/null @@ -1,1146 +0,0 @@ -""" -This page is in the table of contents. -Raft is a script to create a raft, elevate the nozzle and set the temperature. - -The raft manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Raft - -Allan Ecker aka The Masked Retriever's has written two quicktips for raft which follow below. -"Skeinforge Quicktip: The Raft, Part 1" at: -http://blog.thingiverse.com/2009/07/14/skeinforge-quicktip-the-raft-part-1/ -"Skeinforge Quicktip: The Raft, Part II" at: -http://blog.thingiverse.com/2009/08/04/skeinforge-quicktip-the-raft-part-ii/ - -Pictures of rafting in action are available from the Metalab blog at: -http://reprap.soup.io/?search=rafting - -Raft is based on the Nophead's reusable raft, which has a base layer running one way, and a couple of perpendicular layers above. Each set of layers can be set to a different temperature. There is the option of having the extruder orbit the raft for a while, so the heater barrel has time to reach a different temperature, without ooze accumulating around the nozzle. - -If you want to only set the temperature or only create support material or only elevate the nozzle without creating a raft, set the Base Layers and Interface Layers to zero. - -The important values for the raft settings are the temperatures of the raft, the first layer and the next layers. These will be different for each material. The default settings for ABS, HDPE, PCL & PLA are extrapolated from Nophead's experiments. - -==Operation== -The default 'Activate Raft' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. The raft script sets the temperature. - -==Settings== -===Add Raft, Elevate Nozzle, Orbit=== -Default is on. - -When selected, the script will also create a raft, elevate the nozzle, orbit and set the altitude of the bottom of the raft. - -===Base=== -====Base Feed Rate Multiplier==== -Default is one. - -Defines the base feed rate multiplier. The greater the 'Base Feed Rate Multiplier', the thinner the base, the lower the 'Base Feed Rate Multiplier', the thicker the base. - -====Base Flow Rate Multiplier==== -Default is one. - -Defines the base flow rate multiplier. The greater the 'Base Flow Rate Multiplier', the thicker the base, the lower the 'Base Flow Rate Multiplier', the thinner the base. - -====Base Infill Density==== -Default is 0.5. - -Defines the infill density ratio of the base of the raft. - -====Base Layer Height over Layer Thickness==== -Default is two. - -Defines the ratio of the height & width of the base layer compared to the height and width of the object infill. The feed rate will be slower for raft layers which have thicker extrusions than the object infill. - -====Base Layers==== -Default is one. - -Defines the number of base layers. - -====Base Nozzle Lift over Base Layer Thickness==== -Default is 0.4. - -Defines the amount the nozzle is above the center of the base extrusion divided by the base layer thickness. - -===Initial Circling=== -Default is off. - -When selected, the extruder will initially circle around until it reaches operating temperature. - -===Infill Overhang over Extrusion Width=== -Default is 0.05. - -Defines the ratio of the infill overhang over the the extrusion width of the raft. - -===Interface=== -====Interface Feed Rate Multiplier==== -Default is one. - -Defines the interface feed rate multiplier. The greater the 'Interface Feed Rate Multiplier', the thinner the interface, the lower the 'Interface Feed Rate Multiplier', the thicker the interface. - -====Interface Flow Rate Multiplier==== -Default is one. - -Defines the interface flow rate multiplier. The greater the 'Interface Flow Rate Multiplier', the thicker the interface, the lower the 'Interface Flow Rate Multiplier', the thinner the interface. - -====Interface Infill Density==== -Default is 0.5. - -Defines the infill density ratio of the interface of the raft. - -====Interface Layer Thickness over Extrusion Height==== -Default is one. - -Defines the ratio of the height & width of the interface layer compared to the height and width of the object infill. The feed rate will be slower for raft layers which have thicker extrusions than the object infill. - -====Interface Layers==== -Default is two. - -Defines the number of interface layers. - -====Interface Nozzle Lift over Interface Layer Thickness==== -Default is 0.45. - -Defines the amount the nozzle is above the center of the interface extrusion divided by the interface layer thickness. - -===Name of Alteration Files=== -If support material is generated, raft looks for alteration files in the alterations folder in the .skeinforge folder in the home directory. Raft does not care if the text file names are capitalized, but some file systems do not handle file name cases properly, so to be on the safe side you should give them lower case names. If it doesn't find the file it then looks in the alterations folder in the skeinforge_plugins folder. - -====Name of Support End File==== -Default is support_end.gcode. - -If support material is generated and if there is a file with the name of the "Name of Support End File" setting, it will be added to the end of the support gcode. - -====Name of Support Start File==== -If support material is generated and if there is a file with the name of the "Name of Support Start File" setting, it will be added to the start of the support gcode. - -===Object First Layer Feed Rate Infill Multiplier=== -Default is 0.4. - -Defines the object first layer infill feed rate multiplier. The greater the 'Object First Layer g Rate Infill Multiplier, the thinner the infill, the lower the 'Object First Layer Feed Rate Infill Multiplier', the thicker the infill. - -===Object First Layer Feed Rate Perimeter Multiplier=== -Default is 0.4. - -Defines the object first layer perimeter feed rate multiplier. The greater the 'Object First Layer Feed Rate Perimeter Multiplier, the thinner the perimeter, the lower the 'Object First Layer Feed Rate Perimeter Multiplier', the thicker the perimeter. - -====Object First Layer Flow Rate Infill Multiplier==== -Default is 0.4. - -Defines the object first layer infill flow rate multiplier. The greater the 'Object First Layer Flow Rate Infill Multiplier', the thicker the infill, the lower the 'Object First Layer Flow Rate Infill Multiplier, the thinner the infill. - -====Object First Layer Flow Rate Perimeter Multiplier==== -Default is 0.4. - -Defines the object first layer perimeter flow rate multiplier. The greater the 'Object First Layer Flow Rate Perimeter Multiplier', the thicker the perimeter, the lower the 'Object First Layer Flow Rate Perimeter Multiplier, the thinner the perimeter. - -===Operating Nozzle Lift over Layer Thickness=== -Default is 0.5. - -Defines the amount the nozzle is above the center of the operating extrusion divided by the layer thickness. - -===Raft Size=== -The raft fills a rectangle whose base size is the rectangle around the bottom layer of the object expanded on each side by the 'Raft Margin' plus the 'Raft Additional Margin over Length (%)' percentage times the length of the side. - -====Raft Margin==== -Default is three millimeters. - -====Raft Additional Margin over Length==== -Default is 1 percent. - -===Support=== -Good articles on support material are at: -http://davedurant.wordpress.com/2010/07/31/skeinforge-support-part-1/ -http://davedurant.wordpress.com/2010/07/31/skeinforge-support-part-2/ - -====Support Cross Hatch==== -Default is off. - -When selected, the support material will cross hatched. Cross hatching the support makes it stronger and harder to remove, which is why the default is off. - -====Support Flow Rate over Operating Flow Rate==== -Default is 0.9. - -Defines the ratio of the flow rate when the support is extruded over the operating flow rate. With a number less than one, the support flow rate will be smaller so the support will be thinner and easier to remove. - -====Support Gap over Perimeter Extrusion Width==== -Default is 0.5. - -Defines the gap between the support material and the object over the perimeter extrusion width. - -====Support Material Choice==== -Default is 'None' because the raft takes time to generate. - -=====Empty Layers Only===== -When selected, support material will be only on the empty layers. This is useful when making identical objects in a stack. - -=====Everywhere===== -When selected, support material will be added wherever there are overhangs, even inside the object. Because support material inside objects is hard or impossible to remove, this option should only be chosen if the object has a cavity that needs support and there is some way to extract the support material. - -=====Exterior Only===== -When selected, support material will be added only the exterior of the object. This is the best option for most objects which require support material. - -=====None===== -When selected, raft will not add support material. - -====Support Minimum Angle==== -Default is sixty degrees. - -Defines the minimum angle that a surface overhangs before support material is added. This angle is defined from the vertical, so zero is a vertical wall, ten is a wall with a bit of overhang, thirty is the typical safe angle for filament extrusion, sixty is a really high angle for extrusion and ninety is an unsupported horizontal ceiling. - -==Examples== -The following examples raft the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and raft.py. - -> python raft.py -This brings up the raft dialog. - -> python raft.py Screw Holder Bottom.stl -The raft tool is parsing the file: -Screw Holder Bottom.stl -.. -The raft tool has created the file: -Screw Holder Bottom_raft.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import math -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -#maybe later wide support -#raft outline temperature http://hydraraptor.blogspot.com/2008/09/screw-top-pot.html -def getCraftedText( fileName, text='', repository=None): - """Raft the file or text.""" - return getCraftedTextFromText(archive.getTextIfEmpty(fileName, text), repository) - -def getCraftedTextFromText(gcodeText, repository=None): - """Raft a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'raft'): - return gcodeText - if repository is None: - repository = settings.getReadRepository( RaftRepository() ) - if not repository.activateRaft.value: - return gcodeText - return RaftSkein().getCraftedGcode(gcodeText, repository) - -def getCrossHatchPointLine( crossHatchPointLineTable, y ): - """Get the cross hatch point line.""" - if not crossHatchPointLineTable.has_key(y): - crossHatchPointLineTable[ y ] = {} - return crossHatchPointLineTable[ y ] - -def getEndpointsFromYIntersections( x, yIntersections ): - """Get endpoints from the y intersections.""" - endpoints = [] - for yIntersectionIndex in xrange( 0, len( yIntersections ), 2 ): - firstY = yIntersections[ yIntersectionIndex ] - secondY = yIntersections[ yIntersectionIndex + 1 ] - if firstY != secondY: - firstComplex = complex( x, firstY ) - secondComplex = complex( x, secondY ) - endpointFirst = euclidean.Endpoint() - endpointSecond = euclidean.Endpoint().getFromOtherPoint( endpointFirst, secondComplex ) - endpointFirst.getFromOtherPoint( endpointSecond, firstComplex ) - endpoints.append( endpointFirst ) - endpoints.append( endpointSecond ) - return endpoints - -def getExtendedLineSegment(extensionDistance, lineSegment, loopXIntersections): - """Get extended line segment.""" - pointBegin = lineSegment[0].point - pointEnd = lineSegment[1].point - segment = pointEnd - pointBegin - segmentLength = abs(segment) - if segmentLength <= 0.0: - print('This should never happen in getExtendedLineSegment in raft, the segment should have a length greater than zero.') - print(lineSegment) - return None - segmentExtend = segment * extensionDistance / segmentLength - lineSegment[0].point -= segmentExtend - lineSegment[1].point += segmentExtend - for loopXIntersection in loopXIntersections: - setExtendedPoint(lineSegment[0], pointBegin, loopXIntersection) - setExtendedPoint(lineSegment[1], pointEnd, loopXIntersection) - return lineSegment - -def getLoopsBySegmentsDictionary(segmentsDictionary, width): - """Get loops from a horizontal segments dictionary.""" - points = [] - for endpoint in getVerticalEndpoints(segmentsDictionary, width, 0.1 * width, width): - points.append(endpoint.point) - for endpoint in euclidean.getEndpointsFromSegmentTable(segmentsDictionary): - points.append(endpoint.point) - return triangle_mesh.getDescendingAreaOrientedLoops(points, points, width + width) - -def getNewRepository(): - """Get new repository.""" - return RaftRepository() - -def getVerticalEndpoints(horizontalSegmentsTable, horizontalStep, verticalOverhang, verticalStep): - """Get vertical endpoints.""" - interfaceSegmentsTableKeys = horizontalSegmentsTable.keys() - interfaceSegmentsTableKeys.sort() - verticalTableTable = {} - for interfaceSegmentsTableKey in interfaceSegmentsTableKeys: - interfaceSegments = horizontalSegmentsTable[interfaceSegmentsTableKey] - for interfaceSegment in interfaceSegments: - begin = int(round(interfaceSegment[0].point.real / verticalStep)) - end = int(round(interfaceSegment[1].point.real / verticalStep)) - for stepIndex in xrange(begin, end + 1): - if stepIndex not in verticalTableTable: - verticalTableTable[stepIndex] = {} - verticalTableTable[stepIndex][interfaceSegmentsTableKey] = None - verticalTableTableKeys = verticalTableTable.keys() - verticalTableTableKeys.sort() - verticalEndpoints = [] - for verticalTableTableKey in verticalTableTableKeys: - verticalTable = verticalTableTable[verticalTableTableKey] - verticalTableKeys = verticalTable.keys() - verticalTableKeys.sort() - xIntersections = [] - for verticalTableKey in verticalTableKeys: - y = verticalTableKey * horizontalStep - if verticalTableKey - 1 not in verticalTableKeys: - xIntersections.append(y - verticalOverhang) - if verticalTableKey + 1 not in verticalTableKeys: - xIntersections.append(y + verticalOverhang) - for segment in euclidean.getSegmentsFromXIntersections(xIntersections, verticalTableTableKey * verticalStep): - for endpoint in segment: - endpoint.point = complex(endpoint.point.imag, endpoint.point.real) - verticalEndpoints.append(endpoint) - return verticalEndpoints - -def setExtendedPoint( lineSegmentEnd, pointOriginal, x ): - """Set the point in the extended line segment.""" - if x > min( lineSegmentEnd.point.real, pointOriginal.real ) and x < max( lineSegmentEnd.point.real, pointOriginal.real ): - lineSegmentEnd.point = complex( x, pointOriginal.imag ) - -def writeOutput(fileName, shouldAnalyze=True): - """Raft a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'raft', shouldAnalyze) - - -class RaftRepository: - """A class to handle the raft settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.raft.html', self) - self.fileNameInput = settings.FileNameInput().getFromFileName( - fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Raft', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute( - 'http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Raft') - self.activateRaft = settings.BooleanSetting().getFromValue('Activate Raft', self, True) - self.addRaftElevateNozzleOrbitSetAltitude = settings.BooleanSetting().getFromValue( - 'Add Raft, Elevate Nozzle, Orbit:', self, True) - settings.LabelSeparator().getFromRepository(self) - - settings.LabelDisplay().getFromName('- Support -', self) - self.supportMaterialChoice = settings.MenuButtonDisplay().getFromName('Where to add support: ', self) - self.supportChoiceNone = settings.MenuRadio().getFromMenuButtonDisplay( - self.supportMaterialChoice, 'None', self, True) - self.supportChoiceEmptyLayersOnly = settings.MenuRadio().getFromMenuButtonDisplay( - self.supportMaterialChoice, 'Empty Layers Only', self, False) - self.supportChoiceEverywhere = settings.MenuRadio().getFromMenuButtonDisplay( - self.supportMaterialChoice, 'Everywhere', self, False) - self.supportChoiceExteriorOnly = settings.MenuRadio().getFromMenuButtonDisplay( - self.supportMaterialChoice, 'Exterior Only', self, False) - self.supportMinimumAngle = settings.FloatSpin().getFromValue( - 40.0, 'Add support if flatter than (degrees):', self, 80.0, 50.0) - self.supportCrossHatch = settings.BooleanSetting().getFromValue('Cross Hatch instead of Lines', self, False) - self.interfaceInfillDensity = settings.FloatSpin().getFromValue( - 0.1, 'Interface/Support Lines Density (ratio):', self, 0.5, 0.25) - self.interfaceLayerThicknessOverLayerThickness = settings.FloatSpin().getFromValue( - 0.8, 'Interface/Support Layer Thickness over Layer Thickness:', self, 1.5, 1.0) - self.supportFeedRate = settings.FloatSpin().getFromValue( - 10.0, 'Support Feed Rate mm/sec:', self, 50.0,15.0) - self.supportFlowRateOverOperatingFlowRate = settings.FloatSpin().getFromValue( - 0.5, 'Support Flow Rate (scaler):', self, 2.0, 1.0) - self.supportGapOverPerimeterExtrusionWidth = settings.FloatSpin().getFromValue( - 0.5, 'Support Gap over Perimeter Extrusion Width (ratio):', self, 1.5, 1.0) - self.raftAdditionalMarginOverLengthPercent = settings.FloatSpin().getFromValue( - 0.0, 'Raft/Support extension in (%):', self, 10.0, 5.0) - self.raftMargin = settings.FloatSpin().getFromValue( - 0.0, 'Raft/Support extension in(mm):', self, 5.0, 2.0) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Name of Support Macro files (gcode) -', self) - self.nameOfSupportEndFile = settings.StringSetting().getFromValue('Name of Support End File:', self, 'support_end.gcode') - self.nameOfSupportStartFile = settings.StringSetting().getFromValue( - 'Name of Support Start File:', self, 'support_start.gcode') - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Print Adhesion to Printbed Objects first layer -', self) - self.operatingNozzleLiftOverLayerThickness = settings.FloatSpin().getFromValue( - -0.1, 'Extra Nozzle clearance over Object(ratio):', self, 0.3, 0.0) - - self.objectFirstLayerFeedRateInfillMultiplier = settings.FloatSpin().getFromValue( - 10, 'First Layer Main Feedrate (mm/s):', self, 100, 35) - self.objectFirstLayerFeedRatePerimeterMultiplier = settings.FloatSpin().getFromValue( - 10, 'First Layer Perimeter Feedrate (mm/s):', self, 100, 25) - self.objectFirstLayerFlowRateInfillMultiplier = settings.FloatSpin().getFromValue( - 0.50, 'First Layer Flow Rate Infill(scaler):', self, 1.50, 1.0) - self.objectFirstLayerFlowRatePerimeterMultiplier = settings.FloatSpin().getFromValue( - 0.50, 'First Layer Flow Rate Perimeter(scaler):', self, 1.50, 1.0) - settings.LabelSeparator().getFromRepository(self) - - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Interface -', self) - self.interfaceLayers = settings.IntSpin().getFromValue( - 0, 'Interface Layers (integer):', self, 3, 0) - self.interfaceFeedRateMultiplier = settings.FloatSpin().getFromValue( - 0.7, 'Interface Feed Rate Multiplier (ratio):', self, 1.1, 1.0) - self.interfaceFlowRateMultiplier = settings.FloatSpin().getFromValue( - 0.7, 'Interface Flow Rate Multiplier (ratio):', self, 1.1, 1.0) - self.interfaceNozzleLiftOverInterfaceLayerThickness = settings.FloatSpin().getFromValue( - 0.25, 'Interface Nozzle Lift over Interface Layer Thickness (ratio):', self, 0.85, 0.45) - - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Base -', self) - self.baseLayers = settings.IntSpin().getFromValue(0, 'Base Layers (integer):', self, 3, 0) - self.baseFeedRateMultiplier = settings.FloatSpin().getFromValue(0.1, 'Base Feed Rate Multiplier (ratio):', self, 1.0, 0.5) - self.baseFlowRateMultiplier = settings.FloatSpin().getFromValue(0.1, 'Base Flow Rate Multiplier (ratio):', self, 1.0, 0.5) - self.baseInfillDensity = settings.FloatSpin().getFromValue(0.2, 'Base Infill Density (ratio):', self, 1.0, 0.5) - self.baseLayerThicknessOverLayerThickness = settings.FloatSpin().getFromValue( - 1.0, 'Base Layer Thickness over Layer Thickness:', self, 3.0, 2.0) - self.baseNozzleLiftOverBaseLayerThickness = settings.FloatSpin().getFromValue( - 0.2, 'Base Nozzle Lift over Base Layer Thickness (ratio):', self, 0.8, 0.4) - settings.LabelSeparator().getFromRepository(self) - self.initialCircling = settings.BooleanSetting().getFromValue('Initial Circling:', self, False) - self.infillOverhangOverExtrusionWidth = settings.FloatSpin().getFromValue( - 0.0, 'Infill Overhang over Extrusion Width (ratio):', self, 5.0, 3.00) - - settings.LabelSeparator().getFromRepository(self) - - - - self.executeTitle = 'Raft' - - def execute(self): - """Raft button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class RaftSkein: - """A class to raft a skein of extrusions.""" - def __init__(self): - self.addLineLayerStart = True - self.baseTemperature = None - self.beginLoop = None - self.boundaryLayers = [] - self.coolingRate = None - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.extrusionStart = True - self.extrusionTop = 0.0 - self.feedRateMinute = 961.0 - self.heatingRate = None - self.insetTable = {} - self.interfaceTemperature = None - self.isPerimeterPath = False - self.isStartupEarly = False - self.isSurroundingLoop = True - self.layerIndex = - 1 - self.layerStarted = False - self.layerThickness = 0.4 - self.lineIndex = 0 - self.lines = None - self.objectFirstLayerInfillTemperature = None - self.objectFirstLayerPerimeterTemperature = None - self.objectNextLayersTemperature = None - self.oldFlowRateInput = 1.0 - self.oldFlowRateOutputString = None - self.oldLocation = None - self.oldTemperatureOutputString = None - self.operatingFlowRate = None - self.operatingLayerEndLine = '( )' - self.operatingJump = None - self.orbitalFeedRatePerSecond = 2.01 - self.perimeterWidth = 0.6 - self.supportFeedRate = 20 - self.supportFlowRate = None - self.supportLayers = [] - self.supportLayersTemperature = None - self.supportedLayersTemperature = None - self.travelFeedRateMinute = None - - def addBaseLayer(self): - """Add a base layer.""" - baseLayerThickness = self.layerThickness * self.baseLayerThicknessOverLayerThickness - zCenter = self.extrusionTop + 0.5 * baseLayerThickness - z = zCenter + baseLayerThickness * self.repository.baseNozzleLiftOverBaseLayerThickness.value - if len(self.baseEndpoints) < 1: - print('This should never happen, the base layer has a size of zero.') - return - feedRateMultiplier = self.repository.baseFeedRateMultiplier.value - self.addLayerFromEndpoints( - self.baseEndpoints, - feedRateMultiplier, - self.repository.baseFlowRateMultiplier.value, - baseLayerThickness, - self.baseLayerThicknessOverLayerThickness, - self.baseStep, - z) - - def addBaseSegments(self, baseExtrusionWidth): - """Add the base segments.""" - baseOverhang = self.repository.infillOverhangOverExtrusionWidth.value * baseExtrusionWidth - self.baseEndpoints = getVerticalEndpoints(self.interfaceSegmentsTable, self.interfaceStep, baseOverhang, self.baseStep) - - def addEmptyLayerSupport( self, boundaryLayerIndex ): - """Add support material to a layer if it is empty.""" - supportLayer = SupportLayer([]) - self.supportLayers.append(supportLayer) - if len( self.boundaryLayers[ boundaryLayerIndex ].loops ) > 0: - return - aboveXIntersectionsTable = {} - euclidean.addXIntersectionsFromLoopsForTable( self.getInsetLoopsAbove(boundaryLayerIndex), aboveXIntersectionsTable, self.interfaceStep ) - belowXIntersectionsTable = {} - euclidean.addXIntersectionsFromLoopsForTable( self.getInsetLoopsBelow(boundaryLayerIndex), belowXIntersectionsTable, self.interfaceStep ) - supportLayer.xIntersectionsTable = euclidean.getIntersectionOfXIntersectionsTables( [ aboveXIntersectionsTable, belowXIntersectionsTable ] ) - - def addFlowRateLineIfDifferent( self, flowRateOutputString ): - """Add a line of flow rate if different.""" - if self.operatingFlowRate is None: - return - if flowRateOutputString == self.oldFlowRateOutputString: - return - if flowRateOutputString is not None: - self.distanceFeedRate.addLine('M108 S' + flowRateOutputString ) - self.oldFlowRateOutputString = flowRateOutputString - - def addFlowRateValueIfDifferent( self, flowRate ): - """Add a flow rate value if different.""" - if flowRate is not None: - self.addFlowRateLineIfDifferent( euclidean.getFourSignificantFigures( flowRate ) ) - - def addInterfaceLayer(self): - """Add an interface layer.""" - interfaceLayerThickness = self.layerThickness * self.interfaceLayerThicknessOverLayerThickness - zCenter = self.extrusionTop + 0.5 * interfaceLayerThickness - z = zCenter + interfaceLayerThickness * self.repository.interfaceNozzleLiftOverInterfaceLayerThickness.value - self.interfaceIntersectionsTableKeys.sort() - if len(self.interfaceEndpoints) < 1: - print('This should never happen, the interface layer has a size of zero.') - return - feedRateMultiplier = self.repository.interfaceFeedRateMultiplier.value - flowRateMultiplier = self.repository.interfaceFlowRateMultiplier.value - self.addLayerFromEndpoints( - self.interfaceEndpoints, - feedRateMultiplier, - flowRateMultiplier, - interfaceLayerThickness, - self.interfaceLayerThicknessOverLayerThickness, - self.interfaceStep, - z) - - def addInterfaceTables(self, interfaceExtrusionWidth): - """Add interface tables.""" - overhang = self.repository.infillOverhangOverExtrusionWidth.value * interfaceExtrusionWidth - self.interfaceEndpoints = [] - self.interfaceIntersectionsTableKeys = self.interfaceIntersectionsTable.keys() - self.interfaceSegmentsTable = {} - for yKey in self.interfaceIntersectionsTableKeys: - self.interfaceIntersectionsTable[yKey].sort() - y = yKey * self.interfaceStep - lineSegments = euclidean.getSegmentsFromXIntersections(self.interfaceIntersectionsTable[yKey], y) - xIntersectionIndexList = [] - for lineSegmentIndex in xrange(len(lineSegments)): - lineSegment = lineSegments[lineSegmentIndex] - endpointBegin = lineSegment[0] - endpointEnd = lineSegment[1] - endpointBegin.point = complex(self.baseStep * math.floor(endpointBegin.point.real / self.baseStep) - overhang, y) - endpointEnd.point = complex(self.baseStep * math.ceil(endpointEnd.point.real / self.baseStep) + overhang, y) - if endpointEnd.point.real > endpointBegin.point.real: - euclidean.addXIntersectionIndexesFromSegment(lineSegmentIndex, lineSegment, xIntersectionIndexList) - xIntersections = euclidean.getJoinOfXIntersectionIndexes(xIntersectionIndexList) - joinedSegments = euclidean.getSegmentsFromXIntersections(xIntersections, y) - if len(joinedSegments) > 0: - self.interfaceSegmentsTable[yKey] = joinedSegments - for joinedSegment in joinedSegments: - self.interfaceEndpoints += joinedSegment - - def addLayerFromEndpoints( - self, - endpoints, - feedRateMultiplier, - flowRateMultiplier, - layerLayerThickness, - layerThicknessRatio, - step, - z): - """Add a layer from endpoints and raise the extrusion top.""" - layerThicknessRatioSquared = layerThicknessRatio * layerThicknessRatio - feedRateMinute = self.feedRateMinute * feedRateMultiplier / layerThicknessRatioSquared - if len(endpoints) < 1: - return - aroundPixelTable = {} - aroundWidth = 0.25 * step - paths = euclidean.getPathsFromEndpoints(endpoints, 1.5 * step, aroundPixelTable, aroundWidth) - self.addLayerLine(z) - self.addFlowRateValueIfDifferent(flowRateMultiplier * self.oldFlowRateInput) - for path in paths: - simplifiedPath = euclidean.getSimplifiedPath(path, step) - self.distanceFeedRate.addGcodeFromFeedRateThreadZ(feedRateMinute, simplifiedPath, self.travelFeedRateMinute, z) - self.extrusionTop += layerLayerThickness - self.addFlowRateValueIfDifferent(self.oldFlowRateInput) - - def addLayerLine(self, z): - """Add the layer gcode line and close the last layer gcode block.""" - if self.layerStarted: - self.distanceFeedRate.addLine('()') - self.distanceFeedRate.addLine('( %s )' % self.distanceFeedRate.getRounded(z)) # Indicate that a new layer is starting. - if self.beginLoop is not None: - zBegin = self.extrusionTop + self.layerThickness - intercircle.addOrbitsIfLarge(self.distanceFeedRate , self.beginLoop, self.orbitalFeedRatePerSecond, self.temperatureChangeTimeBeforeRaft, zBegin) - self.beginLoop = None - self.layerStarted = True - - def addOperatingOrbits(self, boundaryLoops, pointComplex, temperatureChangeTime, z): - """Add the orbits before the operating layers.""" - if len(boundaryLoops) < 1: - return - insetBoundaryLoops = intercircle.getInsetLoopsFromLoops(self.perimeterWidth, boundaryLoops) - if len(insetBoundaryLoops) < 1: - insetBoundaryLoops = boundaryLoops - largestLoop = euclidean.getLargestLoop(insetBoundaryLoops) - if pointComplex is not None: - largestLoop = euclidean.getLoopStartingNearest(self.perimeterWidth, pointComplex, largestLoop) - intercircle.addOrbitsIfLarge(self.distanceFeedRate , largestLoop, self.orbitalFeedRatePerSecond, temperatureChangeTime, z) - - def addRaft(self): - """Add the raft.""" - if len(self.boundaryLayers) < 0: - print('this should never happen, there are no boundary layers in addRaft') - return - self.baseLayerThicknessOverLayerThickness = self.repository.baseLayerThicknessOverLayerThickness.value - baseExtrusionWidth = self.perimeterWidth * self.baseLayerThicknessOverLayerThickness - self.baseStep = baseExtrusionWidth / self.repository.baseInfillDensity.value - self.interfaceLayerThicknessOverLayerThickness = self.repository.interfaceLayerThicknessOverLayerThickness.value - interfaceExtrusionWidth = self.perimeterWidth * self.interfaceLayerThicknessOverLayerThickness - self.interfaceStep = interfaceExtrusionWidth / self.repository.interfaceInfillDensity.value - self.setCornersZ() - self.cornerMinimumComplex = self.cornerMinimum.dropAxis() - originalExtent = self.cornerMaximumComplex - self.cornerMinimumComplex - self.raftOutsetRadius = self.repository.raftMargin.value + (max(originalExtent.real, originalExtent.imag) * self.repository.raftAdditionalMarginOverLengthPercent.value / 100) + 0.001 - self.setBoundaryLayers() - outsetSeparateLoops = intercircle.getInsetSeparateLoopsFromLoops(-self.raftOutsetRadius, self.boundaryLayers[0].loops, 0.8) - self.interfaceIntersectionsTable = {} - euclidean.addXIntersectionsFromLoopsForTable(outsetSeparateLoops, self.interfaceIntersectionsTable, self.interfaceStep) - if len(self.supportLayers) > 0: - supportIntersectionsTable = self.supportLayers[0].xIntersectionsTable - euclidean.joinXIntersectionsTables(supportIntersectionsTable, self.interfaceIntersectionsTable) - self.addInterfaceTables(interfaceExtrusionWidth) - self.addRaftPerimeters() - self.baseIntersectionsTable = {} - complexRadius = complex(self.raftOutsetRadius, self.raftOutsetRadius) - self.complexHigh = complexRadius + self.cornerMaximumComplex - self.complexLow = self.cornerMinimumComplex - complexRadius - self.beginLoop = euclidean.getSquareLoopWiddershins(self.cornerMinimumComplex, self.cornerMaximumComplex) - if not intercircle.orbitsAreLarge(self.beginLoop, self.temperatureChangeTimeBeforeRaft): - self.beginLoop = None - if self.repository.baseLayers.value > 0: - self.addTemperatureLineIfDifferent(self.baseTemperature) - self.addBaseSegments(baseExtrusionWidth) - for baseLayerIndex in xrange(self.repository.baseLayers.value): - self.addBaseLayer() - if self.repository.interfaceLayers.value > 0: - self.addTemperatureLineIfDifferent(self.interfaceTemperature) - for interfaceLayerIndex in xrange(self.repository.interfaceLayers.value): - self.addInterfaceLayer() - self.operatingJump = self.extrusionTop + self.layerThickness * (self.repository.operatingNozzleLiftOverLayerThickness.value + 0.5) -# self.operatingJump = self.extrusionTop + self.layerThickness + self.repository.operatingNozzleLiftOverLayerThickness.value - for boundaryLayer in self.boundaryLayers: - if self.operatingJump is not None: - boundaryLayer.z += self.operatingJump - if self.repository.baseLayers.value > 0 or self.repository.interfaceLayers.value > 0: - boundaryZ = self.boundaryLayers[0].z - if self.layerStarted: - self.distanceFeedRate.addLine('()') - self.layerStarted = False - self.distanceFeedRate.addLine('( )') - self.addLayerLine(boundaryZ) - temperatureChangeTimeBeforeFirstLayer = self.getTemperatureChangeTime(self.objectFirstLayerPerimeterTemperature) - self.addTemperatureLineIfDifferent(self.objectFirstLayerPerimeterTemperature) - largestOutsetLoop = intercircle.getLargestInsetLoopFromLoop(euclidean.getLargestLoop(outsetSeparateLoops), -self.raftOutsetRadius) - intercircle.addOrbitsIfLarge(self.distanceFeedRate, largestOutsetLoop, self.orbitalFeedRatePerSecond, temperatureChangeTimeBeforeFirstLayer, boundaryZ) - self.addLineLayerStart = False - - def addRaftPerimeters(self): - """Add raft perimeters if there is a raft.""" - for supportLayer in self.supportLayers: - supportSegmentTable = supportLayer.supportSegmentTable - if len(supportSegmentTable) > 0: - outset = 0.5 * self.perimeterWidth - self.addRaftPerimetersByLoops(getLoopsBySegmentsDictionary(supportSegmentTable, self.interfaceStep), outset) - if self.repository.baseLayers.value < 1 and self.repository.interfaceLayers.value < 1: - return - outset = (1.0 + self.repository.infillOverhangOverExtrusionWidth.value) * self.perimeterWidth - self.addRaftPerimetersByLoops(getLoopsBySegmentsDictionary(self.interfaceSegmentsTable, self.interfaceStep), outset) - - def addRaftPerimetersByLoops(self, loops, outset): - """Add raft perimeters to the gcode for loops.""" - loops = intercircle.getInsetSeparateLoopsFromLoops(-outset, loops) - for loop in loops: - self.distanceFeedRate.addLine('()') - for point in loop: - roundedX = self.distanceFeedRate.getRounded(point.real) - roundedY = self.distanceFeedRate.getRounded(point.imag) - self.distanceFeedRate.addTagBracketedLine('raftPoint', 'X%s Y%s' % (roundedX, roundedY)) - self.distanceFeedRate.addLine('()') - - def addSegmentTablesToSupportLayers(self): - """Add segment tables to the support layers.""" - for supportLayer in self.supportLayers: - supportLayer.supportSegmentTable = {} - xIntersectionsTable = supportLayer.xIntersectionsTable - for xIntersectionsTableKey in xIntersectionsTable: - y = xIntersectionsTableKey * self.interfaceStep - supportLayer.supportSegmentTable[ xIntersectionsTableKey ] = euclidean.getSegmentsFromXIntersections( xIntersectionsTable[ xIntersectionsTableKey ], y ) - - def addSupportSegmentTable( self, layerIndex ): - """Add support segments from the boundary layers.""" - aboveLayer = self.boundaryLayers[ layerIndex + 1 ] - aboveLoops = aboveLayer.loops - supportLayer = self.supportLayers[layerIndex] - if len( aboveLoops ) < 1: - return - boundaryLayer = self.boundaryLayers[layerIndex] - rise = aboveLayer.z - boundaryLayer.z - outsetSupportLoops = intercircle.getInsetSeparateLoopsFromLoops( - self.minimumSupportRatio * rise, boundaryLayer.loops ) - numberOfSubSteps = 4 - subStepSize = self.interfaceStep / float( numberOfSubSteps ) - aboveIntersectionsTable = {} - euclidean.addXIntersectionsFromLoopsForTable( aboveLoops, aboveIntersectionsTable, subStepSize ) - outsetIntersectionsTable = {} - euclidean.addXIntersectionsFromLoopsForTable( outsetSupportLoops, outsetIntersectionsTable, subStepSize ) - euclidean.subtractXIntersectionsTable( aboveIntersectionsTable, outsetIntersectionsTable ) - for aboveIntersectionsTableKey in aboveIntersectionsTable.keys(): - supportIntersectionsTableKey = int( round( float( aboveIntersectionsTableKey ) / numberOfSubSteps ) ) - xIntersectionIndexList = [] - if supportIntersectionsTableKey in supportLayer.xIntersectionsTable: - euclidean.addXIntersectionIndexesFromXIntersections( 0, xIntersectionIndexList, supportLayer.xIntersectionsTable[ supportIntersectionsTableKey ] ) - euclidean.addXIntersectionIndexesFromXIntersections( 1, xIntersectionIndexList, aboveIntersectionsTable[ aboveIntersectionsTableKey ] ) - supportLayer.xIntersectionsTable[ supportIntersectionsTableKey ] = euclidean.getJoinOfXIntersectionIndexes( xIntersectionIndexList ) - - def addSupportLayerTemperature(self, endpoints, z): - """Add support layer and temperature before the object layer.""" - self.distanceFeedRate.addLine('()') - self.distanceFeedRate.addLinesSetAbsoluteDistanceMode(self.supportStartLines) - self.addTemperatureOrbits(endpoints, self.supportedLayersTemperature, z) - aroundPixelTable = {} - aroundWidth = 0.25 * self.interfaceStep - boundaryLoops = self.boundaryLayers[self.layerIndex].loops - halfSupportOutset = 0.5 * self.supportOutset - aroundBoundaryLoops = intercircle.getAroundsFromLoops(boundaryLoops, halfSupportOutset) - for aroundBoundaryLoop in aroundBoundaryLoops: - euclidean.addLoopToPixelTable(aroundBoundaryLoop, aroundPixelTable, aroundWidth) - paths = euclidean.getPathsFromEndpoints(endpoints, 1.5 * self.interfaceStep, aroundPixelTable, aroundWidth) - feedRateMinuteMultiplied = (self.supportFeedRate *60) - supportFlowRateMultiplied = self.supportFlowRate - if not self.layerIndex: - feedRateMinuteMultiplied = self.repository.objectFirstLayerFeedRateInfillMultiplier.value * 60 - supportFlowRateMultiplied = self.repository.objectFirstLayerFlowRateInfillMultiplier.value * self.repository.objectFirstLayerFeedRateInfillMultiplier.value - self.addFlowRateValueIfDifferent(supportFlowRateMultiplied) - for path in paths: - self.distanceFeedRate.addGcodeFromFeedRateThreadZ(feedRateMinuteMultiplied, path, self.travelFeedRateMinute, z) - self.addFlowRateLineIfDifferent(str(self.oldFlowRateInput)) - self.addTemperatureOrbits(endpoints, self.supportLayersTemperature, z) - self.distanceFeedRate.addLinesSetAbsoluteDistanceMode(self.supportEndLines) - self.distanceFeedRate.addLine('()') - - def addTemperatureLineIfDifferent(self, temperature): - """Add a line of temperature if different.""" - if temperature is None: - return - temperatureOutputString = euclidean.getRoundedToThreePlaces(temperature) - if temperatureOutputString == self.oldTemperatureOutputString: - return - if temperatureOutputString is not None: - self.distanceFeedRate.addLine('M104 S' + temperatureOutputString) # Set temperature. - self.oldTemperatureOutputString = temperatureOutputString - - def addTemperatureOrbits( self, endpoints, temperature, z ): - """Add the temperature and orbits around the support layer.""" - if self.layerIndex < 0: - return - boundaryLoops = self.boundaryLayers[self.layerIndex].loops - temperatureTimeChange = self.getTemperatureChangeTime( temperature ) - self.addTemperatureLineIfDifferent( temperature ) - if len( boundaryLoops ) < 1: - layerCornerHigh = complex(-987654321.0, -987654321.0) - layerCornerLow = complex(987654321.0, 987654321.0) - for endpoint in endpoints: - layerCornerHigh = euclidean.getMaximum( layerCornerHigh, endpoint.point ) - layerCornerLow = euclidean.getMinimum( layerCornerLow, endpoint.point ) - squareLoop = euclidean.getSquareLoopWiddershins( layerCornerLow, layerCornerHigh ) - intercircle.addOrbitsIfLarge( self.distanceFeedRate, squareLoop, self.orbitalFeedRatePerSecond, temperatureTimeChange, z ) - return - perimeterInset = 0.4 * self.perimeterWidth - insetBoundaryLoops = intercircle.getInsetLoopsFromLoops( perimeterInset, boundaryLoops ) - if len( insetBoundaryLoops ) < 1: - insetBoundaryLoops = boundaryLoops - largestLoop = euclidean.getLargestLoop( insetBoundaryLoops ) - intercircle.addOrbitsIfLarge( self.distanceFeedRate, largestLoop, self.orbitalFeedRatePerSecond, temperatureTimeChange, z ) - - def addToFillXIntersectionIndexTables( self, supportLayer ): - """Add fill segments from the boundary layers.""" - supportLoops = supportLayer.supportLoops - supportLayer.fillXIntersectionsTable = {} - if len(supportLoops) < 1: - return - euclidean.addXIntersectionsFromLoopsForTable( supportLoops, supportLayer.fillXIntersectionsTable, self.interfaceStep ) - - def extendXIntersections( self, loops, radius, xIntersectionsTable ): - """Extend the support segments.""" - xIntersectionsTableKeys = xIntersectionsTable.keys() - for xIntersectionsTableKey in xIntersectionsTableKeys: - lineSegments = euclidean.getSegmentsFromXIntersections( xIntersectionsTable[ xIntersectionsTableKey ], xIntersectionsTableKey ) - xIntersectionIndexList = [] - loopXIntersections = [] - euclidean.addXIntersectionsFromLoops( loops, loopXIntersections, xIntersectionsTableKey ) - for lineSegmentIndex in xrange( len( lineSegments ) ): - lineSegment = lineSegments[ lineSegmentIndex ] - extendedLineSegment = getExtendedLineSegment( radius, lineSegment, loopXIntersections ) - if extendedLineSegment is not None: - euclidean.addXIntersectionIndexesFromSegment( lineSegmentIndex, extendedLineSegment, xIntersectionIndexList ) - xIntersections = euclidean.getJoinOfXIntersectionIndexes( xIntersectionIndexList ) - if len( xIntersections ) > 0: - xIntersectionsTable[ xIntersectionsTableKey ] = xIntersections - else: - del xIntersectionsTable[ xIntersectionsTableKey ] - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the raft gcode.""" - self.repository = repository - self.minimumSupportRatio = math.tan( math.radians( repository.supportMinimumAngle.value ) ) - self.supportEndLines = settings.getLinesInAlterationsOrGivenDirectory(repository.nameOfSupportEndFile.value) - self.supportStartLines = settings.getLinesInAlterationsOrGivenDirectory(repository.nameOfSupportStartFile.value) - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - self.temperatureChangeTimeBeforeRaft = 0.0 - if self.repository.initialCircling.value: - maxBaseInterfaceTemperature = max(self.baseTemperature, self.interfaceTemperature) - firstMaxTemperature = max(maxBaseInterfaceTemperature, self.objectFirstLayerPerimeterTemperature) - self.temperatureChangeTimeBeforeRaft = self.getTemperatureChangeTime(firstMaxTemperature) - if repository.addRaftElevateNozzleOrbitSetAltitude.value: - self.addRaft() - self.addTemperatureLineIfDifferent( self.objectFirstLayerPerimeterTemperature ) - for line in self.lines[self.lineIndex :]: - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getElevatedBoundaryLine( self, splitLine ): - """Get elevated boundary gcode line.""" - location = gcodec.getLocationFromSplitLine(None, splitLine) - if self.operatingJump is not None: - location.z += self.operatingJump - return self.distanceFeedRate.getBoundaryLine( location ) - - def getInsetLoops( self, boundaryLayerIndex ): - """Inset the support loops if they are not already inset.""" - if boundaryLayerIndex not in self.insetTable: - self.insetTable[ boundaryLayerIndex ] = intercircle.getInsetSeparateLoopsFromLoops( self.quarterPerimeterWidth, self.boundaryLayers[ boundaryLayerIndex ].loops ) - return self.insetTable[ boundaryLayerIndex ] - - def getInsetLoopsAbove( self, boundaryLayerIndex ): - """Get the inset loops above the boundary layer index.""" - for aboveLayerIndex in xrange( boundaryLayerIndex + 1, len(self.boundaryLayers) ): - if len( self.boundaryLayers[ aboveLayerIndex ].loops ) > 0: - return self.getInsetLoops( aboveLayerIndex ) - return [] - - def getInsetLoopsBelow( self, boundaryLayerIndex ): - """Get the inset loops below the boundary layer index.""" - for belowLayerIndex in xrange( boundaryLayerIndex - 1, - 1, - 1 ): - if len( self.boundaryLayers[ belowLayerIndex ].loops ) > 0: - return self.getInsetLoops( belowLayerIndex ) - return [] - - def getRaftedLine( self, splitLine ): - """Get elevated gcode line with operating feed rate.""" - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) - feedRateMinuteMultiplied = self.feedRateMinute - self.oldLocation = location - z = location.z - if self.operatingJump is not None: - z += self.operatingJump - flowRate = self.oldFlowRateInput - temperature = self.objectNextLayersTemperature - if not self.layerIndex: - if self.isPerimeterPath: - feedRateMinuteMultiplied = self.repository.objectFirstLayerFeedRatePerimeterMultiplier.value * 60 - flowRate = self.repository.objectFirstLayerFlowRatePerimeterMultiplier.value * self.repository.objectFirstLayerFeedRatePerimeterMultiplier.value - temperature = self.objectFirstLayerPerimeterTemperature - else: - feedRateMinuteMultiplied = self.repository.objectFirstLayerFeedRateInfillMultiplier.value * 60 - flowRate = self.repository.objectFirstLayerFlowRateInfillMultiplier.value * self.repository.objectFirstLayerFeedRateInfillMultiplier.value - temperature = self.objectFirstLayerInfillTemperature - self.addFlowRateValueIfDifferent(flowRate) - self.addTemperatureLineIfDifferent(temperature) - return self.distanceFeedRate.getLinearGcodeMovementWithFeedRate(feedRateMinuteMultiplied, location.dropAxis(), z) - - def getStepsUntilEnd( self, begin, end, stepSize ): - """Get steps from the beginning until the end.""" - step = begin - steps = [] - while step < end: - steps.append( step ) - step += stepSize - return steps - - def getSupportEndpoints(self): - """Get the support layer segments.""" - if len(self.supportLayers) <= self.layerIndex: - return [] - supportSegmentTable = self.supportLayers[self.layerIndex].supportSegmentTable - if self.layerIndex % 2 == 1 and self.repository.supportCrossHatch.value: - return getVerticalEndpoints(supportSegmentTable, self.interfaceStep, 0.1 * self.perimeterWidth, self.interfaceStep) - return euclidean.getEndpointsFromSegmentTable(supportSegmentTable) - - def getTemperatureChangeTime( self, temperature ): - """Get the temperature change time.""" - if temperature is None: - return 0.0 - oldTemperature = 25.0 # typical chamber temperature - if self.oldTemperatureOutputString is not None: - oldTemperature = float( self.oldTemperatureOutputString ) - if temperature == oldTemperature: - return 0.0 - if temperature > oldTemperature: - return ( temperature - oldTemperature ) / self.heatingRate - return ( oldTemperature - temperature ) / abs( self.coolingRate ) - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '(': - self.baseTemperature = float(splitLine[1]) - elif firstWord == '(': - self.coolingRate = float(splitLine[1]) - elif firstWord == '()': - self.distanceFeedRate.addLine('( raft )') - elif firstWord == '(': - self.heatingRate = float(splitLine[1]) - elif firstWord == '(': - self.interfaceTemperature = float(splitLine[1]) - elif firstWord == '(': - return - elif firstWord == '(': - self.layerThickness = float(splitLine[1]) - elif firstWord == '(': - self.objectFirstLayerInfillTemperature = float(splitLine[1]) - elif firstWord == '(': - self.objectFirstLayerPerimeterTemperature = float(splitLine[1]) - elif firstWord == '(': - self.objectNextLayersTemperature = float(splitLine[1]) - elif firstWord == '(': - self.orbitalFeedRatePerSecond = float(splitLine[1]) - elif firstWord == '(': - self.feedRateMinute = 60.0 * float(splitLine[1]) - elif firstWord == '(': - self.oldFlowRateInput = float(splitLine[1]) - self.operatingFlowRate = self.oldFlowRateInput - self.supportFlowRate = self.supportFeedRate * self.repository.supportFlowRateOverOperatingFlowRate.value - elif firstWord == '(': - self.perimeterWidth = float(splitLine[1]) - self.quarterPerimeterWidth = 0.25 * self.perimeterWidth - self.supportOutset = self.perimeterWidth + self.perimeterWidth * self.repository.supportGapOverPerimeterExtrusionWidth.value - elif firstWord == '(': - self.supportLayersTemperature = float(splitLine[1]) - elif firstWord == '(': - self.supportedLayersTemperature = float(splitLine[1]) - elif firstWord == '(': - self.travelFeedRateMinute = 60.0 * float(splitLine[1]) - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the raft skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - if self.extrusionStart: - line = self.getRaftedLine(splitLine) - elif firstWord == 'M101': - if self.isStartupEarly: - self.isStartupEarly = False - return - elif firstWord == 'M108': - flowRateOutputString = splitLine[1][1 :] - self.addFlowRateLineIfDifferent( flowRateOutputString ) - self.oldFlowRateInput = float( flowRateOutputString ) - elif firstWord == '(': - line = self.getElevatedBoundaryLine(splitLine) - elif firstWord == '()': - self.extrusionStart = False - self.distanceFeedRate.addLine( self.operatingLayerEndLine ) - elif firstWord == '(': - settings.printProgress(self.layerIndex, 'raft') - self.layerIndex += 1 - boundaryLayer = None - layerZ = self.extrusionTop + float(splitLine[1]) - if len(self.boundaryLayers) > 0: - boundaryLayer = self.boundaryLayers[self.layerIndex] - layerZ = boundaryLayer.z - if self.operatingJump is not None: - line = '( %s )' % self.distanceFeedRate.getRounded( layerZ ) - if self.layerStarted and self.addLineLayerStart: - self.distanceFeedRate.addLine('()') - self.layerStarted = False - if self.layerIndex > len(self.supportLayers) + 1: - self.distanceFeedRate.addLine( self.operatingLayerEndLine ) - self.operatingLayerEndLine = '' - if self.addLineLayerStart: - self.distanceFeedRate.addLine(line) - self.addLineLayerStart = True - line = '' - endpoints = self.getSupportEndpoints() - if self.layerIndex == 1: - if len(endpoints) < 1: - temperatureChangeTimeBeforeNextLayers = self.getTemperatureChangeTime( self.objectNextLayersTemperature ) - self.addTemperatureLineIfDifferent( self.objectNextLayersTemperature ) - if self.repository.addRaftElevateNozzleOrbitSetAltitude.value and len( boundaryLayer.loops ) > 0: - self.addOperatingOrbits( boundaryLayer.loops, euclidean.getXYComplexFromVector3( self.oldLocation ), temperatureChangeTimeBeforeNextLayers, layerZ ) - if len(endpoints) > 0: - self.addSupportLayerTemperature( endpoints, layerZ ) - elif firstWord == '(' or firstWord == '()': - self.isPerimeterPath = True - elif firstWord == '()' or firstWord == '()': - self.isPerimeterPath = False - self.distanceFeedRate.addLine(line) - - def setBoundaryLayers(self): - """Set the boundary layers.""" - if self.repository.supportChoiceNone.value: - return - if len(self.boundaryLayers) < 2: - return - if self.repository.supportChoiceEmptyLayersOnly.value: - supportLayer = SupportLayer([]) - self.supportLayers.append(supportLayer) - for boundaryLayerIndex in xrange(1, len(self.boundaryLayers) -1): - self.addEmptyLayerSupport(boundaryLayerIndex) - self.truncateSupportSegmentTables() - self.addSegmentTablesToSupportLayers() - return - for boundaryLayer in self.boundaryLayers: - # thresholdRadius of 0.8 is needed to avoid the ripple inset bug http://hydraraptor.blogspot.com/2010/12/crackers.html - supportLoops = intercircle.getInsetSeparateLoopsFromLoops(-self.supportOutset, boundaryLayer.loops, 0.8) - supportLayer = SupportLayer(supportLoops) - self.supportLayers.append(supportLayer) - for supportLayerIndex in xrange(len(self.supportLayers) - 1): - self.addSupportSegmentTable(supportLayerIndex) - self.truncateSupportSegmentTables() - for supportLayerIndex in xrange(len(self.supportLayers) - 1): - boundaryLoops = self.boundaryLayers[supportLayerIndex].loops - self.extendXIntersections( boundaryLoops, self.supportOutset, self.supportLayers[supportLayerIndex].xIntersectionsTable) - for supportLayer in self.supportLayers: - self.addToFillXIntersectionIndexTables(supportLayer) - if self.repository.supportChoiceExteriorOnly.value: - for supportLayerIndex in xrange(1, len(self.supportLayers)): - self.subtractJoinedFill(supportLayerIndex) - for supportLayer in self.supportLayers: - euclidean.subtractXIntersectionsTable(supportLayer.xIntersectionsTable, supportLayer.fillXIntersectionsTable) - for supportLayerIndex in xrange(len(self.supportLayers) - 2, -1, -1): - xIntersectionsTable = self.supportLayers[supportLayerIndex].xIntersectionsTable - aboveXIntersectionsTable = self.supportLayers[supportLayerIndex + 1].xIntersectionsTable - euclidean.joinXIntersectionsTables(aboveXIntersectionsTable, xIntersectionsTable) - for supportLayerIndex in xrange(len(self.supportLayers)): - supportLayer = self.supportLayers[supportLayerIndex] - self.extendXIntersections(supportLayer.supportLoops, self.raftOutsetRadius, supportLayer.xIntersectionsTable) - for supportLayer in self.supportLayers: - euclidean.subtractXIntersectionsTable(supportLayer.xIntersectionsTable, supportLayer.fillXIntersectionsTable) - self.addSegmentTablesToSupportLayers() - - def setCornersZ(self): - """Set maximum and minimum corners and z.""" - boundaryLoop = None - boundaryLayer = None - layerIndex = - 1 - self.cornerMaximumComplex = complex(-912345678.0, -912345678.0) - self.cornerMinimum = Vector3(912345678.0, 912345678.0, 912345678.0) - self.firstLayerLoops = [] - for line in self.lines[self.lineIndex :]: - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == '()': - boundaryLoop = None - elif firstWord == '(': - location = gcodec.getLocationFromSplitLine(None, splitLine) - if boundaryLoop is None: - boundaryLoop = [] - boundaryLayer.loops.append(boundaryLoop) - boundaryLoop.append(location.dropAxis()) - self.cornerMaximumComplex = euclidean.getMaximum(self.cornerMaximumComplex, location.dropAxis()) - self.cornerMinimum.minimize(location) - elif firstWord == '(': - z = float(splitLine[1]) - boundaryLayer = euclidean.LoopLayer(z) - self.boundaryLayers.append(boundaryLayer) - elif firstWord == '(': - layerIndex += 1 - if self.repository.supportChoiceNone.value: - if layerIndex > 1: - return - - def subtractJoinedFill( self, supportLayerIndex ): - """Join the fill then subtract it from the support layer table.""" - supportLayer = self.supportLayers[supportLayerIndex] - fillXIntersectionsTable = supportLayer.fillXIntersectionsTable - belowFillXIntersectionsTable = self.supportLayers[ supportLayerIndex - 1 ].fillXIntersectionsTable - euclidean.joinXIntersectionsTables( belowFillXIntersectionsTable, supportLayer.fillXIntersectionsTable ) - euclidean.subtractXIntersectionsTable( supportLayer.xIntersectionsTable, supportLayer.fillXIntersectionsTable ) - - def truncateSupportSegmentTables(self): - """Truncate the support segments after the last support segment which contains elements.""" - for supportLayerIndex in xrange( len(self.supportLayers) - 1, - 1, - 1 ): - if len( self.supportLayers[supportLayerIndex].xIntersectionsTable ) > 0: - self.supportLayers = self.supportLayers[ : supportLayerIndex + 1 ] - return - self.supportLayers = [] - - -class SupportLayer: - """Support loops with segment tables.""" - def __init__( self, supportLoops ): - self.supportLoops = supportLoops - self.supportSegmentTable = {} - self.xIntersectionsTable = {} - - def __repr__(self): - """Get the string representation of this loop layer.""" - return '%s' % self.supportLoops - - -def main(): - """Display the raft dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/scale.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/scale.py deleted file mode 100644 index 608bef5..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/scale.py +++ /dev/null @@ -1,154 +0,0 @@ -#! /usr/bin/env python -""" -This page is in the table of contents. -Scale scales the carving to compensate for shrinkage after the extrusion has cooled. - -It is best to only change the XY Plane Scale, because that does not affect other variables. If you choose to change the Z Axis Scale, that increases the layer thickness so you must increase the feed rate in speed by the same amount and maybe some other variables which depend on layer thickness. - -==Operation== -The default 'Activate Scale' checkbox is off. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===XY Plane Scale=== -Default is 1.01. - -Defines the amount the xy plane of the carving will be scaled. The xy coordinates will be scaled, but the perimeterWidth is not changed, so this can be changed without affecting other variables. - -===Z Axis Scale=== -Default is one. - -Defines the amount the z axis of the carving will be scaled. The default is one because changing this changes many variables related to the layer thickness. For example, the feedRate should be multiplied by the Z Axis Scale because the layers would be farther apart.. - -===SVG Viewer=== -Default is webbrowser. - -If the 'SVG Viewer' is set to the default 'webbrowser', the scalable vector graphics file will be sent to the default browser to be opened. If the 'SVG Viewer' is set to a program name, the scalable vector graphics file will be sent to that program to be opened. - -==Examples== -The following examples scale the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and scale.py. - -> python scale.py -This brings up the scale dialog. - -> python scale.py Screw Holder Bottom.stl -The scale tool is parsing the file: -Screw Holder Bottom.stl -.. -The scale tool has created the file: -.. Screw Holder Bottom_scale.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.svg_reader import SVGReader -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from fabmetheus_utilities import svg_writer -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/02/05 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText(fileName, svgText='', repository=None): - """Scale and convert an svg file or svgText.""" - return getCraftedTextFromText(fileName, archive.getTextIfEmpty(fileName, svgText), repository) - -def getCraftedTextFromText(fileName, svgText, repository=None): - """Scale and convert an svgText.""" - if gcodec.isProcedureDoneOrFileIsEmpty(svgText, 'scale'): - return svgText - if repository is None: - repository = settings.getReadRepository(ScaleRepository()) - if repository.activateScale.value: - return ScaleSkein().getCraftedGcode(fileName, repository, svgText) - return svgText - -def getNewRepository(): - """Get new repository.""" - return ScaleRepository() - -def setLoopLayerScale(rotatedLoopLayer, xyPlaneScale, zAxisScale): - """Set the slice element scale.""" - for loop in rotatedLoopLayer.loops: - for pointIndex in xrange(len(loop)): - loop[pointIndex] *= xyPlaneScale - rotatedLoopLayer.z *= zAxisScale - -def writeOutput(fileName, shouldAnalyze=True): - """Scale the carving.""" - skeinforge_craft.writeSVGTextWithNounMessage(fileName, ScaleRepository(), shouldAnalyze) - - -class ScaleRepository: - """A class to handle the scale settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.scale.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName(fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Scale', self, '') - self.activateScale = settings.BooleanSetting().getFromValue('Activate Scale to finetune print size (try to find the fault somewhere else..):', self, False) - self.xyPlaneScale = settings.FloatSpin().getFromValue(0.90, 'XY Plane Scale (ratio):', self, 1.10, 1.00) - self.zAxisScale = settings.FloatSpin().getFromValue(0.90, 'Z Axis Scale (ratio):', self, 1.10, 1.0) - self.svgViewer = settings.StringSetting().getFromValue('SVG Viewer:', self, 'webbrowser') - self.executeTitle = 'Scale' - - def execute(self): - """Scale button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class ScaleSkein: - """A class to scale a skein of extrusions.""" - def getCraftedGcode(self, fileName, repository, svgText): - """Parse svgText and store the scale svgText.""" - svgReader = SVGReader() - svgReader.parseSVG('', svgText) - if svgReader.sliceDictionary is None: - print('Warning, nothing will be done because the sliceDictionary could not be found getCraftedGcode in preface.') - return '' - xyPlaneScale = repository.xyPlaneScale.value - zAxisScale = repository.zAxisScale.value - decimalPlacesCarried = int(svgReader.sliceDictionary['decimalPlacesCarried']) - layerThickness = zAxisScale * float(svgReader.sliceDictionary['layerThickness']) - perimeterWidth = float(svgReader.sliceDictionary['perimeterWidth']) - rotatedLoopLayers = svgReader.rotatedLoopLayers - for rotatedLoopLayer in rotatedLoopLayers: - setLoopLayerScale(rotatedLoopLayer, xyPlaneScale, zAxisScale) - cornerMaximum = Vector3(-912345678.0, -912345678.0, -912345678.0) - cornerMinimum = Vector3(912345678.0, 912345678.0, 912345678.0) - svg_writer.setSVGCarvingCorners(cornerMaximum, cornerMinimum, layerThickness, rotatedLoopLayers) - svgWriter = svg_writer.SVGWriter( - True, - cornerMaximum, - cornerMinimum, - decimalPlacesCarried, - layerThickness, - perimeterWidth) - commentElement = svg_writer.getCommentElement(svgReader.root) - procedureNameString = svgReader.sliceDictionary['procedureName'] + ',scale' - return svgWriter.getReplacedSVGTemplate(fileName, procedureNameString, rotatedLoopLayers, commentElement) - - -def main(): - """Display the scale dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/cutting.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/cutting.csv deleted file mode 100644 index ee1c1f3..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/cutting.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated cutting settings. -_Name Value -WindowPosition 0+400 -Profile Selection: End_Mill diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion.csv deleted file mode 100644 index 7d14791..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated extrusion settings. -_Name Value -WindowPosition 0+400 -Profile Selection: PLA diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/bottom.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/bottom.csv deleted file mode 100644 index 0a24bd9..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/bottom.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated bottom settings. -_Name Value -WindowPosition 700+0 -Open File for Bottom -Activate Bottom... and dont change anything else here!!! True -Additional Height (ratio): 0.5 -Altitude (mm): 0.0 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/carve.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/carve.csv deleted file mode 100644 index 860cdf5..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/carve.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated carve settings. -_Name Value -WindowPosition 700+0 -Open File for Carve C:/Users/Ahmet/Desktop/SF-ACT/skeinforge_application/test.stl -Layer Height = Extrusion Thickness (mm): 0.4 -Extrusion Width (mm): 0.6 -Print from Layer No:: 0 -Print up to Layer No: 912345678 -Infill in Direction of Bridge True -Correct Mesh True -Unproven Mesh False -SVG Viewer: webbrowser -Add Layer Template to SVG True -Extra Decimal Places (float): 2.0 -Import Coarseness (ratio): 1.0 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/chamber.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/chamber.csv deleted file mode 100644 index 2f941ca..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/chamber.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated chamber settings. -_Name Value -WindowPosition 700+0 -Open File for Chamber -Activate Printbed Temperature Control: False -Heated PrintBed Temperature (Celcius): 60.0 -Turn print Bed Heater Off at Shut Down True diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/clairvoyance.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/clairvoyance.csv deleted file mode 100644 index 8aadf4f..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/clairvoyance.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated clairvoyance settings. -_Name Value -WindowPosition 700+0 -Activate Clairvoyance False -Open File to Generate Clairvoyances for -Gcode Program: webbrowser diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/clip.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/clip.csv deleted file mode 100644 index c28580d..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/clip.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated clip settings. -_Name Value -WindowPosition 700+0 -Open File for Clip C:/Users/Ahmet/Desktop/SF-ACT/skeinforge_application/test.stl -Activate Clip..to clip the extrusion that overlaps when printing perimeters True -Clip Over Perimeter Width adjuster (decrease for bigger gap): 1.0 -Threshold for connecting inner loops (ratio): 2.5 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/comb.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/comb.csv deleted file mode 100644 index 08b5b23..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/comb.csv +++ /dev/null @@ -1,9 +0,0 @@ -Format is tab separated comb settings. -_Name Value -WindowPosition 700+0 -Open File for Comb -Activate Comb if you cant stop the extruder stringing by retraction -it will avoid moving over loops so the strings will be there -but not visible anymore. -Comb bends the extruder travel paths around holes in the slices, to avoid stringing. -so any start up ooze will be inside the shape. False diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/comment.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/comment.csv deleted file mode 100644 index c140205..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/comment.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated comment settings. -_Name Value -WindowPosition 700+0 -Activate Comment False -Open File to Write Comments for diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/cool.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/cool.csv deleted file mode 100644 index c372c48..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/cool.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated cool settings. -_Name Value -WindowPosition 700+0 -Open File for Cool C:/Users/Ahmet/Desktop/SF-ACT/skeinforge_application/test.stl -Activate Cool.. but use with a fan! True -Use Cool if layer takes shorter than(seconds): 10.0 -Turn Fan On at Beginning True -Turn Fan Off at Ending True -Execute when Cool starts: cool_start.gmc -Execute when Cool ends: cool_end.gmc -Orbiting around Object False -Slow Down during print True -Maximum Cool (Celcius): 2.0 -Bridge Cool (Celcius): 1.0 -Minimum Orbital Radius (millimeters): 10.0 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/dimension.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/dimension.csv deleted file mode 100644 index 412a894..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/dimension.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated dimension settings. -_Name Value -WindowPosition 700+0 -Open File for Dimension C:/Users/Ahmet/Desktop/SF-ACT/skeinforge_application/test.stl -Activate Volumetric Extrusion (Stepper driven Extruders) True -Filament Diameter (mm): 2.8 -Filament Packing Density (ratio) lower=more extrusion: 1.0 -Retraction Distance (millimeters): 1.0 -Restart Extra Distance (millimeters): 0.02 -Extruder Retraction Speed (mm/s): 20.0 -Force to retract when crossing over spaces True -Minimum Extrusion before Retraction (millimeters): 1.0 -Minimum Travelmove after Retraction (millimeters): 1.0 -in Absolute units (Sprinter, FiveD a.o.) True -in Relative units (Teacup a.o.) False diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/export.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/export.csv deleted file mode 100644 index 92c442b..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/export.csv +++ /dev/null @@ -1,20 +0,0 @@ -Format is tab separated export settings. -_Name Value -WindowPosition 979+26 -Open File for Export C:/Users/Ahmet/Desktop/SF-ACT/skeinforge_application/test.stl -Activate Export True -Add _export to filename (filename_export) True -Also Send Output To: -Do Not Delete Comments False -Delete Crafting Comments False -Delete All Comments True -Do Not Change Output True -gcode_small False -File Extension (gcode): gcode -Name of Replace File: replace.csv -Save Penultimate Gcode False -Archive Used Profile As Zip False -Export Profile Values As CSV File False -Add Profile Name to Filename False -Add Description to Filename False -Add Timestamp to Filename False diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/fill.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/fill.csv deleted file mode 100644 index 562b434..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/fill.csv +++ /dev/null @@ -1,34 +0,0 @@ -Format is tab separated fill settings. -_Name Value -WindowPosition 700+0 -Open File for Fill -Activate Fill: True -Infill Solidity (ratio): 0.35 -Extrusion Lines extra Spacing (Scaler): 1.0 -Infill Overlap over Perimeter (Scaler): 1.0 -Extra Shells on Alternating Solid Layer (layers): 0 -Extra Shells on Base (layers): 1 -Extra Shells on Sparse Layer (layers): 1 -Fully filled Layers (each top and bottom): 2 -Lower Left True -Nearest False -Infill > Loops > Perimeter False -Infill > Perimeter > Loops False -Loops > Infill > Perimeter False -Loops > Perimeter > Infill False -Perimeter > Infill > Loops False -Perimeter > Loops > Infill True -Line True -Grid Circular False -Grid Hexagonal False -Grid Rectangular False -Diaphragm at every ...th Layer: 100 -Diaphragm Thickness (layers): 0 -Grid Circle Separation over Perimeter Width (ratio): 0.2 -Grid Extra Overlap (ratio): 0.1 -Grid Junction Separation Band Height (layers): 10 -Grid Junction Separation over Octogon Radius At End (ratio): 0.0 -Grid Junction Separation over Octogon Radius At Middle (ratio): 0.0 -Infill Begin Rotation (degrees): 45.0 -Infill Begin Rotation Repeat (layers): 1 -Infill Odd Layer Extra Rotation (degrees): 90.0 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/home.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/home.csv deleted file mode 100644 index d0cb002..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/home.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated home settings. -_Name Value -WindowPosition 700+0 -Open File for Home -Activate Home ... Not needed True -Name of Homing File: homing.gmc diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/inset.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/inset.csv deleted file mode 100644 index 6c3d57c..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/inset.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated inset settings. -_Name Value -WindowPosition 700+0 -Open File for Inset -Bridge Width Multiplier (ratio): 1.0 -Prefer Loops False -Prefer Perimeter True -Overlap Removal(Scaler): 1.0 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/interpret.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/interpret.csv deleted file mode 100644 index 76cdc59..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/interpret.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated interpret settings. -_Name Value -WindowPosition 700+0 -Open File for Interpret -Activate Interpret False -Print Interpretion False -Text Program: webbrowser diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/jitter.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/jitter.csv deleted file mode 100644 index 781738d..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/jitter.csv +++ /dev/null @@ -1,6 +0,0 @@ -Format is tab separated jitter settings. -_Name Value -WindowPosition 700+0 -Open File for Jitter -Activate Jitter to have your perimeter and loop endpoints scattered False -Jitter Over Perimeter Width (ratio): 2.0 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/lash.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/lash.csv deleted file mode 100644 index 32ccb3b..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/lash.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated lash settings. -_Name Value -WindowPosition 700+0 -Open File for Lash -Activate Lash if you have backlash in your axes. -But its better to fix the mechanical problem! False -X Backlash (mm): 0.0 -Y Backlash (mm): 0.0 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/limit.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/limit.csv deleted file mode 100644 index 9671405..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/limit.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated limit settings. -_Name Value -WindowPosition 700+0 -Open File for Limit -Activate Limit if your Firmware is unable to Limiting your Z-Speed. False -Maximum Initial Feed Rate (mm/s): 5.0 -Maximum Z Feed Rate (mm/s): 5.0 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/multiply.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/multiply.csv deleted file mode 100644 index 269d53f..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/multiply.csv +++ /dev/null @@ -1,10 +0,0 @@ -Format is tab separated multiply settings. -_Name Value -WindowPosition 700+0 -Open File for Multiply -Activate Multiply: True -Center X (mm): 100.0 -Center Y (mm): 100.0 -Number of Columns (integer): 1 -Number of Rows (integer): 1 -Separation over Perimeter Width (ratio): 15.0 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/polyfile.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/polyfile.csv deleted file mode 100644 index 6e7d9bb..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/polyfile.csv +++ /dev/null @@ -1,5 +0,0 @@ -Format is tab separated polyfile settings. -_Name Value -WindowPosition 700+0 -Execute All Unmodified Files in a Directory False -Execute File True diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/preface.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/preface.csv deleted file mode 100644 index d265dba..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/preface.csv +++ /dev/null @@ -1,10 +0,0 @@ -Format is tab separated preface settings. -_Name Value -WindowPosition 700+0 -Open File for Preface -Meta: -Name of End File: end.gcode -Name of Start File: start.gcode -Set Positioning to Absolute True -Set Units to Millimeters True -Start at Home False diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/raft.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/raft.csv deleted file mode 100644 index c3a1934..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/raft.csv +++ /dev/null @@ -1,38 +0,0 @@ -Format is tab separated raft settings. -_Name Value -WindowPosition 700+0 -Open File for Raft -Activate Raft True -Add Raft, Elevate Nozzle, Orbit: True -None True -Empty Layers Only False -Everywhere False -Exterior Only False -Add support if flatter than (degrees): 50.0 -Cross Hatch instead of Lines False -Interface/Support Lines Density (ratio): 0.25 -Interface/Support Layer Thickness over Layer Thickness: 1.0 -Support Feed Rate mm/sec: 15.0 -Support Flow Rate (scaler): 1.0 -Support Gap over Perimeter Extrusion Width (ratio): 1.0 -Raft/Support extension in (%): 5.0 -Raft/Support extension in(mm): 2.0 -Name of Support End File: support_end.gcode -Name of Support Start File: support_start.gcode -Extra Nozzle clearance over Object(ratio): 0.0 -Feed Rate Infill Multiplier (ratio): 0.35 -Feed Rate Perimeter Multiplier (ratio): 0.35 -Flow Rate Infill Multiplier (ratio): 0.35 -Flow Rate Perimeter Multiplier (ratio): 0.35 -Interface Layers (integer): 0 -Interface Feed Rate Multiplier (ratio): 1.0 -Interface Flow Rate Multiplier (ratio): 1.0 -Interface Nozzle Lift over Interface Layer Thickness (ratio): 0.45 -Base Layers (integer): 0 -Base Feed Rate Multiplier (ratio): 0.5 -Base Flow Rate Multiplier (ratio): 0.5 -Base Infill Density (ratio): 0.5 -Base Layer Thickness over Layer Thickness: 2.0 -Base Nozzle Lift over Base Layer Thickness (ratio): 0.4 -Initial Circling: False -Infill Overhang over Extrusion Width (ratio): 3.0 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/scale.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/scale.csv deleted file mode 100644 index a479f8b..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/scale.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated scale settings. -_Name Value -WindowPosition 700+0 -Open File for Scale -Activate Scale to finetune print size (try to find the fault somewhere else..): False -XY Plane Scale (ratio): 1.0 -Z Axis Scale (ratio): 1.0 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/skeinforge_help.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/skeinforge_help.csv deleted file mode 100644 index 6447399..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/skeinforge_help.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated skeinforge help settings. -_Name Value -WindowPosition 600+0 -Wiki Manual Primary True diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/skirt.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/skirt.csv deleted file mode 100644 index 80cd328..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/skirt.csv +++ /dev/null @@ -1,8 +0,0 @@ -Format is tab separated skirt settings. -_Name Value -WindowPosition 700+0 -Open File for Skirt -Activate Skirt: True -Convex: True -Gap over Perimeter Width (ratio): 5.0 -Layers To (index): 3 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/speed.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/speed.csv deleted file mode 100644 index e2685f3..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/speed.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated speed settings. -_Name Value -WindowPosition 700+0 -Open File for Speed -Activate Speed: True -Add Flow Rate: True -Main Feed Rate (mm/s): 60.0 -Main Flow Rate (scaler): 1.0 -Feed Rate ratio for Orbiting move (ratio): 0.5 -Perimeter Feed Rate (mm/s): 30.0 -Perimeter Flow Rate (scaler): 1.0 -Bridge Feed Rate (ratio): 1.0 -Bridge Flow Rate (scaler): 1.0 -Travel Feed Rate (mm/s): 130.0 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/statistic.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/statistic.csv deleted file mode 100644 index 4a1f127..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/statistic.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated statistic settings. -_Name Value -WindowPosition 700+0 -Activate Statistic True -Machine Time ($/hour): 1.0 -Material ($/kg): 20.0 -Density (kg/m3): 930.0 -Extrusion Diameter over Thickness (ratio): 1.25 -Open File to Generate Statistics for -Print Statistics True -Save Statistics False diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/stretch.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/stretch.csv deleted file mode 100644 index 5bc618d..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/stretch.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated stretch settings. -_Name Value -WindowPosition 700+0 -Open File for Stretch -Activate Stretch to correct for diameter shrink in small diameter holes False -Cross Limit Distance Over Perimeter Width (ratio): 5.0 -Loop Stretch Over Perimeter Width (ratio): 0.11 -Path Stretch Over Perimeter Width (ratio): 0.0 -Perimeter Inside Stretch Over Perimeter Width (ratio): 0.32 -Perimeter Outside Stretch Over Perimeter Width (ratio): 0.1 -Stretch From Distance Over Perimeter Width (ratio): 2.0 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/temperature.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/temperature.csv deleted file mode 100644 index ce2ef6e..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/temperature.csv +++ /dev/null @@ -1,14 +0,0 @@ -Format is tab separated temperature settings. -_Name Value -WindowPosition 700+0 -Open File for Temperature -Activate Temperature: False -Cooling Rate (Celcius/second): 3.0 -Heating Rate (Celcius/second): 3.0 -Base Temperature (Celcius): 210.0 -Interface Temperature (Celcius): 210.0 -Object First Layer Infill Temperature (Celcius): 210.0 -Object First Layer Perimeter Temperature (Celcius): 210.0 -Object Next Layers Temperature (Celcius): 210.0 -Support Layers Temperature (Celcius): 210.0 -Supported Layers Temperature (Celcius): 210.0 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/vectorwrite.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/vectorwrite.csv deleted file mode 100644 index e03372b..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/vectorwrite.csv +++ /dev/null @@ -1,11 +0,0 @@ -Format is tab separated vectorwrite settings. -_Name Value -WindowPosition 700+0 -Activate Vectorwrite False -Open File to Write Vector Graphics for -Add Loops True -Add Paths True -Add Perimeters True -Layers From (index): 0 -Layers To (index): 912345678 -SVG Viewer: webbrowser diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/wipe.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/wipe.csv deleted file mode 100644 index a539e18..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/extrusion/PLA/wipe.csv +++ /dev/null @@ -1,15 +0,0 @@ -Format is tab separated wipe settings. -_Name Value -WindowPosition 700+0 -Open File for Wipe -Activate Wipe False -Location Arrival X (mm): -70.0 -Location Arrival Y (mm): -50.0 -Location Arrival Z (mm): 50.0 -Location Departure X (mm): -70.0 -Location Departure Y (mm): -40.0 -Location Departure Z (mm): 50.0 -Location Wipe X (mm): -70.0 -Location Wipe Y (mm): -70.0 -Location Wipe Z (mm): 50.0 -Wipe Period (layers): 3 diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/milling.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/milling.csv deleted file mode 100644 index 5dd4bbc..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/milling.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated milling settings. -_Name Value -WindowPosition 0+400 -Profile Selection: End_Mill diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/skeinforge_profile.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/skeinforge_profile.csv deleted file mode 100644 index 48bb0a0..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/skeinforge_profile.csv +++ /dev/null @@ -1,7 +0,0 @@ -Format is tab separated skeinforge profile settings. -_Name Value -WindowPosition 0+200 -cutting False -extrusion True -milling False -winding False diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/winding.csv b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/winding.csv deleted file mode 100644 index a20384b..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/sfact_profiles/profiles/winding.csv +++ /dev/null @@ -1,4 +0,0 @@ -Format is tab separated winding settings. -_Name Value -WindowPosition 0+400 -Profile Selection: free_wire diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/skin.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/skin.py deleted file mode 100644 index d0f12bb..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/skin.py +++ /dev/null @@ -1,213 +0,0 @@ -""" -This page is in the table of contents. -Skin is a script to smooth the surface skin as described at: -http://adventuresin3-dprinting.blogspot.com/2011/05/skinning.html - -The skin manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Skin - - -==Operation== -The default 'Activate Skin' checkbox is off. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Examples== -The following examples skin the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and skin.py. - -> python skin.py -This brings up the skin dialog. - -> python skin.py Screw Holder Bottom.stl -The skin tool is parsing the file: -Screw Holder Bottom.stl -.. -The skin tool has created the file: -.. Screw Holder Bottom_skin.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. - -import __init__ -import math - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText(fileName, gcodeText, repository=None): - """Skin a gcode linear move text.""" - return getCraftedTextFromText(archive.getTextIfEmpty(fileName, gcodeText), repository) - -def getCraftedTextFromText(gcodeText, repository=None): - """Skin a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty(gcodeText, 'skin'): - return gcodeText - if repository is None: - repository = settings.getReadRepository(SkinRepository()) - if not repository.activateSkin.value: - return gcodeText - return SkinSkein().getCraftedGcode(gcodeText, repository) - -def getNewRepository(): - """Get new repository.""" - return SkinRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Skin a gcode linear move file. Chain skin the gcode if it is not already skinned.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'skin', shouldAnalyze) - - -class SkinRepository: - """A class to handle the skin settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.skin.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Skin', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Skin') - self.activateSkin = settings.BooleanSetting().getFromValue('Activate Skin: this is experimental. \nIt prints the perimeters and loops only at half the layer height that is specified under carve.', self, False ) - self.clipOverPerimeterWidth = settings.FloatSpin().getFromValue(0.50, 'Clip Over Perimeter Width (scaler):', self, 1.50, 1.00) - self.layersFrom = settings.IntSpin().getSingleIncrementFromValue(0, 'Do Not Skin the first ... Layers:', self, 912345678, 3) - self.executeTitle = 'Skin' - - def execute(self): - """Skin button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class SkinSkein: - """A class to skin a skein of extrusions.""" - def __init__(self): - """Initialize.""" - self.boundaryLayerIndex = -1 - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.feedRateMinute = 959.0 - self.lineIndex = 0 - self.lines = None - self.oldFlowRate = None - self.oldLocation = None - self.perimeter = None - self.travelFeedRateMinute = 957.0 - - def addFlowRateLine(self, flowRate): - """Add a flow rate line.""" - self.distanceFeedRate.addLine('M108 S' + euclidean.getFourSignificantFigures(flowRate)) - - def addPerimeterLoop(self, thread, z): - """Add the perimeter loop to the gcode.""" - self.distanceFeedRate.addGcodeFromFeedRateThreadZ(self.feedRateMinute, thread, self.travelFeedRateMinute, z) - - def addSkinnedPerimeter(self): - """Add skinned perimeter.""" - if self.perimeter is None: - return - self.perimeter = self.perimeter[: -1] - innerPerimeter = intercircle.getLargestInsetLoopFromLoop(self.perimeter, self.quarterPerimeterWidth) - innerPerimeter = self.getClippedSimplifiedLoopPathByLoop(innerPerimeter) - outerPerimeter = intercircle.getLargestInsetLoopFromLoop(self.perimeter, -self.quarterPerimeterWidth) - outerPerimeter = self.getClippedSimplifiedLoopPathByLoop(outerPerimeter) - lowerZ = self.oldLocation.z - self.quarterLayerThickness - higherZ = self.oldLocation.z + self.quarterLayerThickness - self.addFlowRateLine(0.25 * self.oldFlowRate) - self.addPerimeterLoop(innerPerimeter, lowerZ) - self.addPerimeterLoop(outerPerimeter, lowerZ) - self.addPerimeterLoop(innerPerimeter, higherZ) - self.addPerimeterLoop(outerPerimeter, higherZ) - self.addFlowRateLine(self.oldFlowRate) - - def getClippedSimplifiedLoopPathByLoop(self, loop): - """Get clipped and simplified loop path from a loop.""" - loopPath = loop + [loop[0]] - return euclidean.getClippedSimplifiedLoopPath(self.clipLength, loopPath, self.halfPerimeterWidth) - - def getCraftedGcode( self, gcodeText, repository ): - """Parse gcode text and store the skin gcode.""" - self.lines = archive.getTextLines(gcodeText) - self.repository = repository - self.parseInitialization() - for self.lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[self.lineIndex] - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( skin )') - return - elif firstWord == '(': - - self.quarterLayerThickness = 0.25 * float(splitLine[1]) - elif firstWord == '(': - self.oldFlowRate = float(splitLine[1]) - elif firstWord == '(': - perimeterWidth = float(splitLine[1]) - self.halfPerimeterWidth = 0.5 * perimeterWidth - self.quarterPerimeterWidth = 0.25 * perimeterWidth - self.clipLength = (self.quarterLayerThickness - (self.repository.clipOverPerimeterWidth.value * self.quarterLayerThickness * (math.pi/4)))*4 - elif firstWord == '(': - self.travelFeedRateMinute = 60.0 * float(splitLine[1]) - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the skin skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == '()': - self.boundaryLayerIndex = max(0, self.boundaryLayerIndex) - elif firstWord == 'G1': - self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - self.oldLocation = location - if self.perimeter is not None: - self.perimeter.append(location.dropAxis()) - return - elif firstWord == '(': - if self.boundaryLayerIndex > -1: - self.boundaryLayerIndex += 1 - elif firstWord == 'M101' or firstWord == 'M103': - if self.perimeter is not None: - return - elif firstWord == 'M108': - self.oldFlowRate = gcodec.getDoubleAfterFirstLetter(splitLine[1]) - elif firstWord == '(': - if self.boundaryLayerIndex >= self.repository.layersFrom.value: - self.perimeter = [] - elif firstWord == '()': - self.addSkinnedPerimeter() - self.perimeter = None - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the skin dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor(getNewRepository()) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/skirt.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/skirt.py deleted file mode 100644 index 9a2681f..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/skirt.py +++ /dev/null @@ -1,342 +0,0 @@ -""" -This page is in the table of contents. -Skirt is a script to give the extruder some extra time to begin extruding properly before beginning the object, and to put a baffle around the model in order to keep the extrusion warm. - -It is loosely based on Lenbook's outline plugin: -http://www.thingiverse.com/thing:4918 - -it is also loosely based on the outline that Nophead sometimes uses: -http://hydraraptor.blogspot.com/2010/01/hot-metal-and-serendipity.html - -and also loosely based on the baffles that Nophead made to keep corners warm: -http://hydraraptor.blogspot.com/2010/09/some-corners-like-it-hot.html - -If you want only an outline, set 'Layers To' to one. This gives the extruder some extra time to begin extruding properly before beginning your object, and gives you an early verification of where your object will be extruded. - -If you also want an insulating skirt around the entire object, set 'Layers To' to a huge number, like 9876554321. This will additionally make an insulating baffle around the object; to prevent moving air from cooling the object, which increases warping, especially in corners. - -==Operation== -The default 'Activate Skirt' checkbox is off. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Gap over Perimeter Width=== -Default is three. - -Defines the ratio of the gap between the object and the skirt over the perimeter width. If the ratio is too low, the skirt will connect to the object, if the ratio is too high, the skirt willl not provide much insulation for the object. - -====Layers To==== -Default is a one. - -Defines the number of layers of the skirt. If you want only an outline, set 'Layers To' to one. If you want an insulating skirt around the entire object, set 'Layers To' to a huge number, like 9876554321. - -==Examples== -The following examples skirt the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and skirt.py. - -> python skirt.py -This brings up the skirt dialog. - -> python skirt.py Screw Holder Bottom.stl -The skirt tool is parsing the file: -Screw Holder Bottom.stl -.. -The skirt tool has created the file: -.. Screw Holder Bottom_skirt.gcode - -""" - - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.geometry.solids import triangle_mesh -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import intercircle -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText(fileName, text='', repository=None): - """Skirt the fill file or text.""" - return getCraftedTextFromText(archive.getTextIfEmpty(fileName, text), repository) - -def getCraftedTextFromText(gcodeText, repository=None): - """Skirt the fill text.""" - if gcodec.isProcedureDoneOrFileIsEmpty(gcodeText, 'skirt'): - return gcodeText - if repository is None: - repository = settings.getReadRepository(SkirtRepository()) - if not repository.activateSkirt.value: - return gcodeText - return SkirtSkein().getCraftedGcode(gcodeText, repository) - -def getNewRepository(): - """Get new repository.""" - return SkirtRepository() - -def getOuterLoops(loops): - """Get widdershins outer loops.""" - outerLoops = [] - for loop in loops: - if not euclidean.isPathInsideLoops(outerLoops, loop): - outerLoops.append(loop) - intercircle.directLoops(True, outerLoops) - return outerLoops - -def writeOutput(fileName, shouldAnalyze=True): - """Skirt a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'skirt', shouldAnalyze) - - -class LoopCrossDictionary: - """Loop with a horizontal and vertical dictionary.""" - def __init__(self): - """Initialize LoopCrossDictionary.""" - self.loop = [] - self.horizontalDictionary = None - self.verticalDictionary = None - - def __repr__(self): - """Get the string representation of this LoopCrossDictionary.""" - return str(self.__dict__) - - -class SkirtRepository: - """A class to handle the skirt settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.skirt.html', self) - self.fileNameInput = settings.FileNameInput().getFromFileName( - fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Skirt', self, '') - self.activateSkirt = settings.BooleanSetting().getFromValue('Activate Skirt:', self, True) - self.convex = settings.BooleanSetting().getFromValue('Convex:', self, True) - self.gapOverPerimeterWidth = settings.FloatSpin().getFromValue( - 1.0, 'Gap over Perimeter Width (ratio):', self, 10.0, 5.0) - self.layersTo = settings.IntSpin().getSingleIncrementFromValue(0, 'Layers To (index):', self, 912345678, 3) - self.executeTitle = 'Skirt' - - def execute(self): - """Skirt button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode( - self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class SkirtSkein: - """A class to skirt a skein of extrusions.""" - def __init__(self): - """Initialize variables.""" - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.feedRateMinute = 961.0 - self.isExtruderActive = False - self.isSupportLayer = False - self.layerCount = settings.LayerCount() - self.layerIndex = -1 - self.lineIndex = 0 - self.lines = None - self.oldFlowRateInput = None - self.oldLocation = None - self.oldTemperatureInput = None - self.skirtFlowRate = None - self.skirtTemperature = None - self.travelFeedRateMinute = 957.0 - self.unifiedLoop = LoopCrossDictionary() - - def addFlowRateLineIfDifferent(self, flowRate): - """Add a line of temperature if different.""" - if flowRate is None or flowRate == self.oldFlowRateInput: - return - self.distanceFeedRate.addLine('M108 S' + euclidean.getFourSignificantFigures(flowRate)) - self.oldFlowRateInput = flowRate - - def addSkirt(self, z): - """At skirt at z to gcode output.""" - self.setSkirtFeedFlowTemperature() - self.distanceFeedRate.addLine('()') - oldFlowRate = self.oldFlowRateInput - oldTemperature = self.oldTemperatureInput - self.addTemperatureLineIfDifferent(self.skirtTemperature) - self.addFlowRateLineIfDifferent(self.skirtFlowRate) - for outsetLoop in self.outsetLoops: - closedLoop = outsetLoop + [outsetLoop[0]] - self.distanceFeedRate.addGcodeFromFeedRateThreadZ(self.feedRateMinute, closedLoop, self.travelFeedRateMinute, z) - self.addFlowRateLineIfDifferent(oldFlowRate) - self.addTemperatureLineIfDifferent(oldTemperature) - self.distanceFeedRate.addLine('()') - - def addTemperatureLineIfDifferent(self, temperature): - """Add a line of temperature if different.""" - if temperature is None or temperature == self.oldTemperatureInput: - return - self.distanceFeedRate.addLine('M104 S' + euclidean.getRoundedToThreePlaces(temperature)) - self.oldTemperatureInput = temperature - - def createSegmentDictionaries(self, loopCrossDictionary): - """Create horizontal and vertical segment dictionaries.""" - loopCrossDictionary.horizontalDictionary = self.getHorizontalXIntersectionsTable(loopCrossDictionary.loop) - flippedLoop = euclidean.getDiagonalFlippedLoop(loopCrossDictionary.loop) - loopCrossDictionary.verticalDictionary = self.getHorizontalXIntersectionsTable(flippedLoop) - - def createSkirtLoops(self): - """Create the skirt loops.""" - points = euclidean.getPointsByHorizontalDictionary(self.perimeterWidth, self.unifiedLoop.horizontalDictionary) - points += euclidean.getPointsByVerticalDictionary(self.perimeterWidth, self.unifiedLoop.verticalDictionary) - loops = triangle_mesh.getDescendingAreaOrientedLoops(points, points, 2.5 * self.perimeterWidth) - outerLoops = getOuterLoops(loops) - outsetLoops = intercircle.getInsetSeparateLoopsFromLoops(-self.skirtOutset, outerLoops) - self.outsetLoops = getOuterLoops(outsetLoops) - if self.repository.convex.value: - self.outsetLoops = [euclidean.getLoopConvex(euclidean.getConcatenatedList(self.outsetLoops))] - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the skirt gcode.""" - self.repository = repository - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - self.parseBoundaries() - self.createSkirtLoops() - for self.lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[self.lineIndex] - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getHorizontalXIntersectionsTable(self, loop): - """Get the horizontal x intersections table from the loop.""" - horizontalXIntersectionsTable = {} - euclidean.addXIntersectionsFromLoopForTable(loop, horizontalXIntersectionsTable, self.perimeterWidth) - return horizontalXIntersectionsTable - - def parseBoundaries(self): - """Parse the boundaries and union them.""" - self.createSegmentDictionaries(self.unifiedLoop) - if self.repository.layersTo.value < 1: - return - loopCrossDictionary = None - layerIndex = -1 - for line in self.lines[self.lineIndex :]: - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == '()' or firstWord == '()': - self.createSegmentDictionaries(loopCrossDictionary) - self.unifyLayer(loopCrossDictionary) - loopCrossDictionary = None - elif firstWord == '(' or firstWord == '(': - location = gcodec.getLocationFromSplitLine(None, splitLine) - if loopCrossDictionary is None: - loopCrossDictionary = LoopCrossDictionary() - loopCrossDictionary.loop.append(location.dropAxis()) - elif firstWord == '(': - layerIndex += 1 - if layerIndex > self.repository.layersTo.value: - return - self.layerCount.printProgressIncrement('skirt') - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addTagBracketedLine('procedureName', 'skirt') - return - elif firstWord == '(': - self.oldTemperatureInput = float(splitLine[1]) - self.skirtTemperature = self.oldTemperatureInput - elif firstWord == '(': - self.feedRateMinute = 60.0 * float(splitLine[1]) - elif firstWord == '(': - self.oldFlowRateInput = float(splitLine[1]) - self.skirtFlowRate = self.oldFlowRateInput - elif firstWord == '(': - self.perimeterWidth = float(splitLine[1]) - self.skirtOutset = (self.repository.gapOverPerimeterWidth.value + 0.5) * self.perimeterWidth - self.distanceFeedRate.addTagRoundedLine('skirtOutset', self.skirtOutset) - elif firstWord == '(': - self.travelFeedRateMinute = 60.0 * float(splitLine[1]) - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the skirt skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == '()' or firstWord == '()' or firstWord == '(': - return - self.distanceFeedRate.addLine(line) - if firstWord == 'G1': - self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) - elif firstWord == '(': - self.layerIndex += 1 - if self.layerIndex < self.repository.layersTo.value: - self.addSkirt(float(splitLine[1])) - elif firstWord == 'M101': - self.isExtruderActive = True - elif firstWord == 'M103': - self.isExtruderActive = False - elif firstWord == 'M104': - self.oldTemperatureInput = gcodec.getDoubleAfterFirstLetter(splitLine[1]) - self.skirtTemperature = self.oldTemperatureInput - elif firstWord == 'M108': - self.oldFlowRateInput = gcodec.getDoubleAfterFirstLetter(splitLine[1]) - self.skirtFlowRate = self.oldFlowRateInput - elif firstWord == '()': - self.isSupportLayer = True - elif firstWord == '()': - self.isSupportLayer = False - - def setSkirtFeedFlowTemperature(self): - """Set the skirt feed rate, flow rate and temperature to that of the next extrusion.""" - isExtruderActive = self.isExtruderActive - isSupportLayer = self.isSupportLayer - for lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1': - self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine) - if isExtruderActive: - if not isSupportLayer: - return - elif firstWord == 'M101': - isExtruderActive = True - elif firstWord == 'M103': - isExtruderActive = False - elif firstWord == 'M104': - self.skirtTemperature = gcodec.getDoubleAfterFirstLetter(splitLine[1]) - elif firstWord == 'M108': - self.skirtFlowRate = gcodec.getDoubleAfterFirstLetter(splitLine[1]) - elif firstWord == '()': - isSupportLayer = True - elif firstWord == '()': - isSupportLayer = False - - def unifyLayer(self, loopCrossDictionary): - """Union the loopCrossDictionary with the unifiedLoop.""" - euclidean.joinXIntersectionsTables(loopCrossDictionary.horizontalDictionary, self.unifiedLoop.horizontalDictionary) - euclidean.joinXIntersectionsTables(loopCrossDictionary.verticalDictionary, self.unifiedLoop.verticalDictionary) - - -def main(): - """Display the skirt dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor(getNewRepository()) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/speed.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/speed.py deleted file mode 100644 index 8fd38de..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/speed.py +++ /dev/null @@ -1,284 +0,0 @@ -""" -This page is in the table of contents. -Speed is a script to set the feed rate, and flow rate. - -The speed manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Speed - -==Operation== -The default 'Activate Speed' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. The speed script sets the feed rate, and flow rate. - -==Settings== -===Add Flow Rate=== -Default is on. - -When selected, the flow rate will be added to the gcode. - -===Bridge=== -====Bridge Feed Rate Multiplier==== -Default is one. - -Defines the ratio of the feed rate on the bridge layers over the feed rate of the typical non bridge layers. - -====Bridge Flow Rate Multiplier==== -Default is one. - -Defines the ratio of the flow rate on the bridge layers over the flow rate of the typical non bridge layers. - -===Duty Cyle=== -====Duty Cyle at Beginning==== -Default is one, which will set the extruder motor to full current. - -Defines the duty cycle of the stepper motor pulse width modulation by adding an M113 command toward the beginning of the gcode text. If the hardware has the option of using a potentiometer to set the duty cycle, to select the potentiometer option set 'Duty Cyle at Beginning' to an empty string. To turn off the extruder, set the 'Duty Cyle at Beginning' to zero. - -====Duty Cyle at Ending==== -Default is zero, which will turn off the extruder motor. - -Defines the duty cycle of the stepper motor pulse width modulation by adding an M113 command toward the ending of the gcode text. If the hardware has the option of using a potentiometer to set the duty cycle, to select the potentiometer option set 'Duty Cyle at Beginning' to an empty string. To turn off the extruder, set the 'Duty Cyle at Ending' to zero. - -===Feed Rate=== -Default is sixteen millimeters per second. - -Defines the operating feed rate. - -===Flow Rate Setting=== -Default is 210. - -Defines the operating flow rate. - -===Orbital Feed Rate over Operating Feed Rate=== -Default is 0.5. - -Defines the speed of the orbit compared to the operating extruder speed. If you want the orbit to be very short, set the "Orbital Feed Rate over Operating Feed Rate" setting to a low value like 0.1. - -===Perimeter=== -To have higher build quality on the outside at the expense of slower build speed, a typical setting for the 'Perimeter Feed Rate over Operating Feed Rate' would be 0.5. To go along with that, if you are using a speed controlled extruder, the 'Perimeter Flow Rate over Operating Flow Rate' should also be 0.5. If you are using Pulse Width Modulation to control the speed, then you'll probably need a slightly higher ratio because there is a minimum voltage 'Flow Rate PWM Setting' required for the extruder motor to turn. The flow rate PWM ratio would be determined by trial and error, with the first trial being: -Perimeter Flow Rate over Operating Flow Rate ~ Perimeter Feed Rate over Operating Feed Rate * ( Flow Rate PWM Setting - Minimum Flow Rate PWM Setting ) + Minimum Flow Rate PWM Setting - -====Perimeter Feed Rate over Operating Feed Rate==== -Default is one. - -Defines the ratio of the feed rate of the perimeter over the feed rate of the infill. - -====Perimeter Flow Rate over Operating Feed Rate==== -Default is one. - -Defines the ratio of the flow rate of the perimeter over the flow rate of the infill. - -===Travel Feed Rate=== -Default is sixteen millimeters per second. - -Defines the feed rate when the extruder is off. The 'Travel Feed Rate' could be set as high as the extruder can be moved, it is not limited by the maximum extrusion rate. - -==Examples== -The following examples speed the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and speed.py. - -> python speed.py -This brings up the speed dialog. - -> python speed.py Screw Holder Bottom.stl -The speed tool is parsing the file: -Screw Holder Bottom.stl -.. -The speed tool has created the file: -.. Screw Holder Bottom_speed.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, text='', repository=None): - """Speed the file or text.""" - return getCraftedTextFromText(archive.getTextIfEmpty(fileName, text), repository) - -def getCraftedTextFromText(gcodeText, repository=None): - """Speed a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'speed'): - return gcodeText - if repository is None: - repository = settings.getReadRepository( SpeedRepository() ) - if not repository.activateSpeed.value: - return gcodeText - return SpeedSkein().getCraftedGcode(gcodeText, repository) - -def getNewRepository(): - """Get new repository.""" - return SpeedRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Speed a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'speed', shouldAnalyze) - - -class SpeedRepository: - """A class to handle the speed settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.speed.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Speed', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Speed') - self.activateSpeed = settings.BooleanSetting().getFromValue('Activate Speed:', self, True ) - self.addFlowRate = settings.BooleanSetting().getFromValue('Add Flow Rate:', self, True ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Main Feedrate Settings -', self ) - self.feedRatePerSecond = settings.FloatSpin().getFromValue( 20.0, 'Main Feed Rate (mm/s):', self, 140.0, 60.0 ) - self.flowRateSetting = settings.FloatSpin().getFromValue( 0.5, 'Main Flow Rate (scaler):', self, 1.5, 1.0 ) - self.orbitalFeedRateOverOperatingFeedRate = settings.FloatSpin().getFromValue( 0.1, 'Feed Rate ratio for Orbiting move (ratio):', self, 0.9, 0.5 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Perimeter Printing -', self ) - self.perimeterFeedRateOverOperatingFeedRate = settings.FloatSpin().getFromValue( 20.0, 'Perimeter Feed Rate (mm/s):', self, 80.0, 30.0 ) - self.perimeterFlowRateOverOperatingFlowRate = settings.FloatSpin().getFromValue( 0.5, 'Perimeter Flow Rate (scaler):', self, 1.5, 1.0 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Bridge Layers -', self ) - self.bridgeFeedRateMultiplier = settings.FloatSpin().getFromValue( 0.5, 'Bridge Feed Rate (ratio):', self, 1.5, 1.0 ) - self.bridgeFlowRateMultiplier = settings.FloatSpin().getFromValue( 0.5, 'Bridge Flow Rate (scaler):', self, 1.3, 1.0 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelSeparator().getFromRepository(self) - self.travelFeedRatePerSecond = settings.FloatSpin().getFromValue( 40.0, 'Travel Feed Rate (mm/s):', self, 200.0, 130.0 ) - self.executeTitle = 'Speed' - - def execute(self): - """Speed button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class SpeedSkein: - """A class to speed a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.feedRatePerSecond = 16.0 - self.isBridgeLayer = False - self.isExtruderActive = False - self.isPerimeterPath = False - self.lineIndex = 0 - self.lines = None - self.oldFlowRateString = None - - def addFlowRateLineIfNecessary(self): - """Add flow rate line.""" - flowRateString = self.getFlowRateString() - if flowRateString != self.oldFlowRateString: - self.distanceFeedRate.addLine('M108 S' + flowRateString ) - self.oldFlowRateString = flowRateString - - def addParameterString( self, firstWord, parameterWord ): - """Add parameter string.""" - if parameterWord == '': - self.distanceFeedRate.addLine(firstWord) - return - self.distanceFeedRate.addParameter( firstWord, parameterWord ) - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the speed gcode.""" - self.repository = repository - self.feedRatePerSecond = repository.feedRatePerSecond.value - self.travelFeedRateMinute = 60.0 * self.repository.travelFeedRatePerSecond.value - self.lines = archive.getTextLines(gcodeText) - self.parseInitialization() - for line in self.lines[self.lineIndex :]: - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getFlowRateString(self): - """Get the flow rate string.""" - if not self.repository.addFlowRate.value: - return None - flowRate = self.repository.flowRateSetting.value * self.feedRatePerSecond - if self.isBridgeLayer: - flowRate *= self.repository.bridgeFlowRateMultiplier.value * self.repository.bridgeFeedRateMultiplier.value - if self.isPerimeterPath: - flowRate = self.repository.perimeterFlowRateOverOperatingFlowRate.value * self.repository.perimeterFeedRateOverOperatingFeedRate.value - return euclidean.getFourSignificantFigures( flowRate ) - - def getSpeededLine(self, line, splitLine): - """Get gcode line with feed rate.""" - if gcodec.getIndexOfStartingWithSecond('F', splitLine) > 0: - return line - feedRateMinute = 60.0 * self.feedRatePerSecond - if self.isBridgeLayer: - feedRateMinute *= self.repository.bridgeFeedRateMultiplier.value - if self.isPerimeterPath: - feedRateMinute = self.repository.perimeterFeedRateOverOperatingFeedRate.value * 60 - self.addFlowRateLineIfNecessary() - if not self.isExtruderActive: - feedRateMinute = self.travelFeedRateMinute - return self.distanceFeedRate.getLineWithFeedRate(feedRateMinute, line, splitLine) - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '(': - self.layerThickness = float(splitLine[1]) - elif firstWord == '()': - self.distanceFeedRate.addLine('( speed )') - return - elif firstWord == '(': - self.absolutePerimeterWidth = abs(float(splitLine[1])) - self.distanceFeedRate.addTagBracketedLine('operatingFeedRatePerSecond', self.feedRatePerSecond ) - if self.repository.addFlowRate.value: - self.distanceFeedRate.addTagBracketedLine('operatingFlowRate', self.repository.flowRateSetting.value ) - orbitalFeedRatePerSecond = self.feedRatePerSecond * self.repository.orbitalFeedRateOverOperatingFeedRate.value - self.distanceFeedRate.addTagBracketedLine('orbitalFeedRatePerSecond', orbitalFeedRatePerSecond ) - self.distanceFeedRate.addTagBracketedLine('travelFeedRatePerSecond', self.repository.travelFeedRatePerSecond.value ) - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the speed skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == '()': - self.distanceFeedRate.addLine(line) - return - elif firstWord == 'G1': - line = self.getSpeededLine(line, splitLine) - elif firstWord == 'M101': - self.isExtruderActive = True - elif firstWord == 'M103': - self.isExtruderActive = False - elif firstWord == '(': - self.isBridgeLayer = True - elif firstWord == '(': - self.isBridgeLayer = False - self.addFlowRateLineIfNecessary() - elif firstWord == '(' or firstWord == '()': - self.isPerimeterPath = True - elif firstWord == '()' or firstWord == '()': - self.isPerimeterPath = False - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the speed dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/stretch.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/stretch.py deleted file mode 100644 index 09badb7..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/stretch.py +++ /dev/null @@ -1,411 +0,0 @@ -""" -This page is in the table of contents. -Stretch is a script to stretch the threads to partially compensate for filament shrinkage when extruded. - -The stretch manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Stretch - -All the defaults assume that the thread sequence choice setting in fill is the perimeter being extruded first, then the loops, then the infill. If the thread sequence choice is different, the optimal thread parameters will also be different. In general, if the infill is extruded first, the infill would have to be stretched more so that even after the filament shrinkage, it would still be long enough to connect to the loop or perimeter. - -==Operation== -The default 'Activate Stretch' checkbox is off. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Loop Stretch Over Perimeter Width=== -Default is 0.1. - -Defines the ratio of the maximum amount the loop aka inner shell threads will be stretched compared to the perimeter width, in general this value should be the same as the 'Perimeter Outside Stretch Over Perimeter Width' setting. - -===Path Stretch Over Perimeter Width=== -Default is zero. - -Defines the ratio of the maximum amount the threads which are not loops, like the infill threads, will be stretched compared to the perimeter width. - -===Perimeter=== -====Perimeter Inside Stretch Over Perimeter Width==== -Default is 0.32. - -Defines the ratio of the maximum amount the inside perimeter thread will be stretched compared to the perimeter width, this is the most important setting in stretch. The higher the value the more it will stretch the perimeter and the wider holes will be. If the value is too small, the holes could be drilled out after fabrication, if the value is too high, the holes would be too wide and the part would have to junked. - -====Perimeter Outside Stretch Over Perimeter Width==== -Default is 0.1. - -Defines the ratio of the maximum amount the outside perimeter thread will be stretched compared to the perimeter width, in general this value should be around a third of the 'Perimeter Inside Stretch Over Perimeter Width' setting. - -===Stretch from Distance over Perimeter Width=== -Default is two. - -In general, stretch will widen holes and push corners out. The algorithm works by checking at each turning point on the extrusion path what the direction of the thread is at a distance of 'Stretch from Distance over Perimeter Width' times the perimeter width, on both sides, and moves the thread in the opposite direction. The magnitude of the stretch increases with the amount that the direction of the two threads is similar and by the '..Stretch Over Perimeter Width' ratio. In practice the filament contraction will be similar but different from the algorithm, so even once the optimal parameters are determined, the stretch script will not be able to eliminate the inaccuracies caused by contraction, but it should reduce them. - -==Examples== -The following examples stretch the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and stretch.py. - -> python stretch.py -This brings up the stretch dialog. - -> python stretch.py Screw Holder Bottom.stl -The stretch tool is parsing the file: -Screw Holder Bottom.stl -.. -The stretch tool has created the file: -.. Screw Holder Bottom_stretch.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -#maybe speed up feedRate option -def getCraftedText( fileName, gcodeText, stretchRepository = None ): - """Stretch a gcode linear move text.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, gcodeText), stretchRepository ) - -def getCraftedTextFromText( gcodeText, stretchRepository = None ): - """Stretch a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'stretch'): - return gcodeText - if stretchRepository is None: - stretchRepository = settings.getReadRepository( StretchRepository() ) - if not stretchRepository.activateStretch.value: - return gcodeText - return StretchSkein().getCraftedGcode( gcodeText, stretchRepository ) - -def getNewRepository(): - """Get new repository.""" - return StretchRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Stretch a gcode linear move file. Chain stretch the gcode if it is not already stretched.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'stretch', shouldAnalyze) - - -class LineIteratorBackward: - """Backward line iterator class.""" - def __init__( self, isLoop, lineIndex, lines ): - self.firstLineIndex = None - self.isLoop = isLoop - self.lineIndex = lineIndex - self.lines = lines - - def getIndexBeforeNextDeactivate(self): - """Get index two lines before the deactivate command.""" - for lineIndex in xrange( self.lineIndex + 1, len(self.lines) ): - line = self.lines[lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - 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.') - raise StopIteration, "You've reached the end of the line." - - def getNext(self): - """Get next line going backward or raise exception.""" - while self.lineIndex > 3: - if self.lineIndex == self.firstLineIndex: - raise StopIteration, "You've reached the end of the line." - if self.firstLineIndex is None: - self.firstLineIndex = self.lineIndex - nextLineIndex = self.lineIndex - 1 - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'M103': - if self.isLoop: - nextLineIndex = self.getIndexBeforeNextDeactivate() - else: - raise StopIteration, "You've reached the end of the line." - if firstWord == 'G1': - if self.isBeforeExtrusion(): - if self.isLoop: - nextLineIndex = self.getIndexBeforeNextDeactivate() - else: - raise StopIteration, "You've reached the end of the line." - else: - self.lineIndex = nextLineIndex - return line - self.lineIndex = nextLineIndex - raise StopIteration, "You've reached the end of the line." - - def isBeforeExtrusion(self): - """Determine if index is two or more before activate command.""" - linearMoves = 0 - for lineIndex in xrange( self.lineIndex + 1, len(self.lines) ): - line = self.lines[lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1': - linearMoves += 1 - if firstWord == 'M101': - return linearMoves > 0 - if firstWord == 'M103': - return False - print('This should never happen in isBeforeExtrusion in stretch, no activate command was found for this thread.') - return False - - -class LineIteratorForward: - """Forward line iterator class.""" - def __init__( self, isLoop, lineIndex, lines ): - self.firstLineIndex = None - self.isLoop = isLoop - self.lineIndex = lineIndex - self.lines = lines - - def getIndexJustAfterActivate(self): - """Get index just after the activate command.""" - for lineIndex in xrange( self.lineIndex - 1, 3, - 1 ): - line = self.lines[lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - 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.') - raise StopIteration, "You've reached the end of the line." - - def getNext(self): - """Get next line or raise exception.""" - while self.lineIndex < len(self.lines): - if self.lineIndex == self.firstLineIndex: - raise StopIteration, "You've reached the end of the line." - if self.firstLineIndex is None: - self.firstLineIndex = self.lineIndex - nextLineIndex = self.lineIndex + 1 - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'M103': - if self.isLoop: - nextLineIndex = self.getIndexJustAfterActivate() - else: - raise StopIteration, "You've reached the end of the line." - self.lineIndex = nextLineIndex - if firstWord == 'G1': - return line - raise StopIteration, "You've reached the end of the line." - - -class StretchRepository: - """A class to handle the stretch settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.stretch.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Stretch', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Stretch') - self.activateStretch = settings.BooleanSetting().getFromValue('Activate Stretch to correct for diameter shrink in small diameter holes', self, False ) - self.crossLimitDistanceOverPerimeterWidth = settings.FloatSpin().getFromValue( 3.0, 'Cross Limit Distance Over Perimeter Width (ratio):', self, 10.0, 5.0 ) - self.loopStretchOverPerimeterWidth = settings.FloatSpin().getFromValue( 0.05, 'Loop Stretch Over Perimeter Width (ratio):', self, 0.25, 0.11 ) - self.pathStretchOverPerimeterWidth = settings.FloatSpin().getFromValue( 0.0, 'Path Stretch Over Perimeter Width (ratio):', self, 0.2, 0.0 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Perimeter -', self ) - self.perimeterInsideStretchOverPerimeterWidth = settings.FloatSpin().getFromValue( 0.12, 'Perimeter Inside Stretch Over Perimeter Width (ratio):', self, 0.52, 0.32 ) - self.perimeterOutsideStretchOverPerimeterWidth = settings.FloatSpin().getFromValue( 0.05, 'Perimeter Outside Stretch Over Perimeter Width (ratio):', self, 0.25, 0.1 ) - settings.LabelSeparator().getFromRepository(self) - self.stretchFromDistanceOverPerimeterWidth = settings.FloatSpin().getFromValue( 1.0, 'Stretch From Distance Over Perimeter Width (ratio):', self, 3.0, 2.0 ) - self.executeTitle = 'Stretch' - - def execute(self): - """Stretch button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class StretchSkein: - """A class to stretch a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.extruderActive = False - self.feedRateMinute = 959.0 - self.isLoop = False - self.lineIndex = 0 - self.lines = None - self.oldLocation = None - self.perimeterWidth = 0.4 - - def getCraftedGcode( self, gcodeText, stretchRepository ): - """Parse gcode text and store the stretch gcode.""" - self.lines = archive.getTextLines(gcodeText) - self.stretchRepository = stretchRepository - self.parseInitialization() - for self.lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[self.lineIndex] - self.parseStretch(line) - return self.distanceFeedRate.output.getvalue() - - def getCrossLimitedStretch( self, crossLimitedStretch, crossLineIterator, locationComplex ): - """Get cross limited relative stretch for a location.""" - try: - line = crossLineIterator.getNext() - except StopIteration: - return crossLimitedStretch - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - pointComplex = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine).dropAxis() - pointMinusLocation = locationComplex - pointComplex - pointMinusLocationLength = abs( pointMinusLocation ) - if pointMinusLocationLength <= self.crossLimitDistanceFraction: - return crossLimitedStretch - parallelNormal = pointMinusLocation / pointMinusLocationLength - parallelStretch = euclidean.getDotProduct( parallelNormal, crossLimitedStretch ) * parallelNormal - if pointMinusLocationLength > self.crossLimitDistance: - return parallelStretch - crossNormal = complex( parallelNormal.imag, - parallelNormal.real ) - crossStretch = euclidean.getDotProduct( crossNormal, crossLimitedStretch ) * crossNormal - crossPortion = ( self.crossLimitDistance - pointMinusLocationLength ) / self.crossLimitDistanceRemainder - return parallelStretch + crossStretch * crossPortion - - def getRelativeStretch( self, locationComplex, lineIterator ): - """Get relative stretch for a location.""" - lastLocationComplex = locationComplex - oldTotalLength = 0.0 - pointComplex = locationComplex - totalLength = 0.0 - while 1: - try: - line = lineIterator.getNext() - except StopIteration: - locationMinusPoint = locationComplex - pointComplex - locationMinusPointLength = abs( locationMinusPoint ) - if locationMinusPointLength > 0.0: - return locationMinusPoint / locationMinusPointLength - return complex() - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = splitLine[0] - pointComplex = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine).dropAxis() - locationMinusPoint = lastLocationComplex - pointComplex - locationMinusPointLength = abs( locationMinusPoint ) - totalLength += locationMinusPointLength - if totalLength >= self.stretchFromDistance: - distanceFromRatio = ( self.stretchFromDistance - oldTotalLength ) / locationMinusPointLength - totalPoint = distanceFromRatio * pointComplex + ( 1.0 - distanceFromRatio ) * lastLocationComplex - locationMinusTotalPoint = locationComplex - totalPoint - return locationMinusTotalPoint / self.stretchFromDistance - lastLocationComplex = pointComplex - oldTotalLength = totalLength - - def getStretchedLine( self, splitLine ): - """Get stretched gcode line.""" - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine ) - self.oldLocation = location - if self.extruderActive and self.threadMaximumAbsoluteStretch > 0.0: - return self.getStretchedLineFromIndexLocation( self.lineIndex - 1, self.lineIndex + 1, location ) - if self.isJustBeforeExtrusion() and self.threadMaximumAbsoluteStretch > 0.0: - return self.getStretchedLineFromIndexLocation( self.lineIndex - 1, self.lineIndex + 1, location ) - return self.lines[self.lineIndex] - - def getStretchedLineFromIndexLocation( self, indexPreviousStart, indexNextStart, location ): - """Get stretched gcode line from line index and location.""" - crossIteratorForward = LineIteratorForward( self.isLoop, indexNextStart, self.lines ) - crossIteratorBackward = LineIteratorBackward( self.isLoop, indexPreviousStart, self.lines ) - iteratorForward = LineIteratorForward( self.isLoop, indexNextStart, self.lines ) - iteratorBackward = LineIteratorBackward( self.isLoop, indexPreviousStart, self.lines ) - locationComplex = location.dropAxis() - relativeStretch = self.getRelativeStretch( locationComplex, iteratorForward ) + self.getRelativeStretch( locationComplex, iteratorBackward ) - relativeStretch *= 0.8 -# print('relativeStretch') -# print( relativeStretch ) - relativeStretch = self.getCrossLimitedStretch( relativeStretch, crossIteratorForward, locationComplex ) - relativeStretch = self.getCrossLimitedStretch( relativeStretch, crossIteratorBackward, locationComplex ) -# print( relativeStretch ) - relativeStretchLength = abs( relativeStretch ) - if relativeStretchLength > 1.0: - relativeStretch /= relativeStretchLength - absoluteStretch = relativeStretch * self.threadMaximumAbsoluteStretch - stretchedPoint = location.dropAxis() + absoluteStretch - return self.distanceFeedRate.getLinearGcodeMovementWithFeedRate( self.feedRateMinute, stretchedPoint, location.z ) - - def isJustBeforeExtrusion(self): - """Determine if activate command is before linear move command.""" - for lineIndex in xrange( self.lineIndex + 1, len(self.lines) ): - line = self.lines[lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - if firstWord == 'G1' or firstWord == 'M103': - return False - if firstWord == 'M101': - return True -# print('This should never happen in isJustBeforeExtrusion in stretch, no activate or deactivate command was found for this thread.') - return False - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( stretch )') - return - elif firstWord == '(': - perimeterWidth = float(splitLine[1]) - self.crossLimitDistance = self.perimeterWidth * self.stretchRepository.crossLimitDistanceOverPerimeterWidth.value - self.loopMaximumAbsoluteStretch = self.perimeterWidth * self.stretchRepository.loopStretchOverPerimeterWidth.value - self.pathAbsoluteStretch = self.perimeterWidth * self.stretchRepository.pathStretchOverPerimeterWidth.value - self.perimeterInsideAbsoluteStretch = self.perimeterWidth * self.stretchRepository.perimeterInsideStretchOverPerimeterWidth.value - self.perimeterOutsideAbsoluteStretch = self.perimeterWidth * self.stretchRepository.perimeterOutsideStretchOverPerimeterWidth.value - self.stretchFromDistance = self.stretchRepository.stretchFromDistanceOverPerimeterWidth.value * perimeterWidth - self.threadMaximumAbsoluteStretch = self.pathAbsoluteStretch - self.crossLimitDistanceFraction = 0.333333333 * self.crossLimitDistance - self.crossLimitDistanceRemainder = self.crossLimitDistance - self.crossLimitDistanceFraction - self.distanceFeedRate.addLine(line) - - def parseStretch(self, line): - """Parse a gcode line and add it to the stretch skein.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - line = self.getStretchedLine(splitLine) - elif firstWord == 'M101': - self.extruderActive = True - elif firstWord == 'M103': - self.extruderActive = False - self.setStretchToPath() - elif firstWord == '(': - self.isLoop = True - self.threadMaximumAbsoluteStretch = self.loopMaximumAbsoluteStretch - elif firstWord == '()': - self.setStretchToPath() - elif firstWord == '(': - self.isLoop = True - self.threadMaximumAbsoluteStretch = self.perimeterInsideAbsoluteStretch - if splitLine[1] == 'outer': - self.threadMaximumAbsoluteStretch = self.perimeterOutsideAbsoluteStretch - elif firstWord == '()': - self.setStretchToPath() - self.distanceFeedRate.addLine(line) - - def setStretchToPath(self): - """Set the thread stretch to path stretch and is loop false.""" - self.isLoop = False - self.threadMaximumAbsoluteStretch = self.pathAbsoluteStretch - - -def main(): - """Display the stretch dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/temperature.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/temperature.py deleted file mode 100644 index 36bae66..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/temperature.py +++ /dev/null @@ -1,197 +0,0 @@ -""" -This page is in the table of contents. -Temperature is a script to set the temperature for the object and raft. - -==Operation== -The default 'Activate Temperature' checkbox is on. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Rate=== -The default cooling rate and heating rate for the extruder were both been derived from bothacker's graph at: -http://bothacker.com/wp-content/uploads/2009/09/18h5m53s9.29.2009.png - -====Cooling Rate==== -Default is three degrees Celcius per second. - -Defines the cooling rate of the extruder. - -====Heating Rate==== -Default is ten degrees Celcius per second. - -Defines the heating rate of the extruder. - -===Temperature=== -====Base Temperature==== -Default for ABS is two hundred degrees Celcius. - -Defines the raft base temperature. - -====Interface Temperature==== -Default for ABS is two hundred degrees Celcius. - -Defines the raft interface temperature. - -====Object First Layer Infill Temperature==== -Default for ABS is 195 degrees Celcius. - -Defines the infill temperature of the first layer of the object. - -====Object First Layer Perimeter Temperature==== -Default for ABS is two hundred and twenty degrees Celcius. - -Defines the perimeter temperature of the first layer of the object. - -====Object Next Layers Temperature==== -Default for ABS is two hundred and thirty degrees Celcius. - -Defines the temperature of the next layers of the object. - -====Support Layers Temperature==== -Default for ABS is two hundred degrees Celcius. - -Defines the support layers temperature. - -====Supported Layers Temperature==== -Default for ABS is two hundred and thirty degrees Celcius. - -Defines the temperature of the supported layers of the object, those layers which are right above a support layer. - -==Examples== -The following examples add temperature information to the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and temperature.py. - -> python temperature.py -This brings up the temperature dialog. - -> python temperature.py Screw Holder Bottom.stl -The temperature tool is parsing the file: -Screw Holder Bottom.stl -.. -The temperature tool has created the file: -.. Screw Holder Bottom_temperature.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, text='', repository=None): - """Temperature the file or text.""" - return getCraftedTextFromText(archive.getTextIfEmpty(fileName, text), repository) - -def getCraftedTextFromText(gcodeText, repository=None): - """Temperature a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'temperature'): - return gcodeText - if repository is None: - repository = settings.getReadRepository( TemperatureRepository() ) - if not repository.activateTemperature.value: - return gcodeText - return TemperatureSkein().getCraftedGcode(gcodeText, repository) - -def getNewRepository(): - """Get new repository.""" - return TemperatureRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Temperature a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'temperature', shouldAnalyze) - - -class TemperatureRepository: - """A class to handle the temperature settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.temperature.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Temperature', self, '') - self.activateTemperature = settings.BooleanSetting().getFromValue('Activate Temperature:', self, False ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Rate -', self ) - self.coolingRate = settings.FloatSpin().getFromValue( 1.0, 'Cooling Rate (Celcius/second):', self, 20.0, 3.0 ) - self.heatingRate = settings.FloatSpin().getFromValue( 1.0, 'Heating Rate (Celcius/second):', self, 20.0, 3.0 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Temperature - Defaults are for PLA', self ) - self.baseTemperature = settings.FloatSpin().getFromValue( 150.0, 'Base Temperature (Celcius):', self, 240.0, 210.0 ) - self.interfaceTemperature = settings.FloatSpin().getFromValue( 150.0, 'Interface Temperature (Celcius):', self, 240.0, 210.0 ) - self.objectFirstLayerInfillTemperature = settings.FloatSpin().getFromValue( 150.0, 'Object First Layer Infill Temperature (Celcius):', self, 240.0, 210.0 ) - self.objectFirstLayerPerimeterTemperature = settings.FloatSpin().getFromValue( 150.0, 'Object First Layer Perimeter Temperature (Celcius):', self, 240.0, 210.0 ) - self.objectNextLayersTemperature = settings.FloatSpin().getFromValue( 150.0, 'Object Next Layers Temperature (Celcius):', self, 240.0, 210.0 ) - self.supportLayersTemperature = settings.FloatSpin().getFromValue( 150.0, 'Support Layers Temperature (Celcius):', self, 240.0, 210.0 ) - self.supportedLayersTemperature = settings.FloatSpin().getFromValue( 150.0, 'Supported Layers Temperature (Celcius):', self, 240.0, 210.0 ) - self.executeTitle = 'Temperature' - - def execute(self): - """Temperature button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class TemperatureSkein: - """A class to temperature a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.lineIndex = 0 - self.lines = None - - def getCraftedGcode(self, gcodeText, repository): - """Parse gcode text and store the temperature gcode.""" - self.repository = repository - self.lines = archive.getTextLines(gcodeText) - if self.repository.coolingRate.value < 0.1: - print('The cooling rate should be more than 0.1, any cooling rate less than 0.1 will be treated as 0.1.') - self.repository.coolingRate.value = 0.1 - if self.repository.heatingRate.value < 0.1: - print('The heating rate should be more than 0.1, any heating rate less than 0.1 will be treated as 0.1.') - self.repository.heatingRate.value = 0.1 - self.parseInitialization() - self.distanceFeedRate.addLines( self.lines[self.lineIndex :] ) - return self.distanceFeedRate.output.getvalue() - - def parseInitialization(self): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( temperature )') - return - elif firstWord == '(': - self.distanceFeedRate.addTagBracketedLine('coolingRate', self.repository.coolingRate.value ) - self.distanceFeedRate.addTagBracketedLine('heatingRate', self.repository.heatingRate.value ) - self.distanceFeedRate.addTagBracketedLine('baseTemperature', self.repository.baseTemperature.value ) - self.distanceFeedRate.addTagBracketedLine('interfaceTemperature', self.repository.interfaceTemperature.value ) - self.distanceFeedRate.addTagBracketedLine('objectFirstLayerInfillTemperature', self.repository.objectFirstLayerInfillTemperature.value ) - self.distanceFeedRate.addTagBracketedLine('objectFirstLayerPerimeterTemperature', self.repository.objectFirstLayerPerimeterTemperature.value ) - self.distanceFeedRate.addTagBracketedLine('objectNextLayersTemperature', self.repository.objectNextLayersTemperature.value ) - self.distanceFeedRate.addTagBracketedLine('supportLayersTemperature', self.repository.supportLayersTemperature.value ) - self.distanceFeedRate.addTagBracketedLine('supportedLayersTemperature', self.repository.supportedLayersTemperature.value ) - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the temperature dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/wipe.py b/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/wipe.py deleted file mode 100644 index 9fe88a7..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/craft_plugins/wipe.py +++ /dev/null @@ -1,266 +0,0 @@ -""" -This page is in the table of contents. -At the beginning of a layer, depending on the settings, wipe will move the nozzle with the extruder off to the arrival point, then to the wipe point, then to the departure point, then back to the layer. - -The wipe path is machine specific, so you'll probably have to change all the default locations. - -The wipe manual page is at: -http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Wipe - -==Operation== -The default 'Activate Wipe' checkbox is off. When it is on, the functions described below will work, when it is off, the functions will not be called. - -==Settings== -===Location Arrival=== -====Location Arrival X==== -Default is minus seventy millimeters. - -Defines the x coordinate of the arrival location. - -====Location Arrival Y==== -Default is minus fifty millimeters. - -Defines the y coordinate of the arrival location. - -====Location Arrival Z==== -Default is fifty millimeters. - -Defines the z coordinate of the arrival location. - -===Location Departure=== -====Location Departure X==== -Default is minus seventy millimeters. - -Defines the x coordinate of the departure location. - -====Location Departure Y==== -Default is minus forty millimeters. - -Defines the y coordinate of the departure location. - -====Location Departure Z==== -Default is fifty millimeters. - -Defines the z coordinate of the departure location. - -===Location Wipe=== -====Location Wipe X==== -Default is minus seventy millimeters. - -Defines the x coordinate of the wipe location. - -====Location Wipe Y==== -Default is minus seventy millimeters. - -Defines the y coordinate of the wipe location. - -====Location Wipe Z==== -Default is fifty millimeters. - -Defines the z coordinate of the wipe location. - -===Wipe Period=== -Default is three. - -Defines the number of layers between wipes. Wipe will always wipe just before layer zero, afterwards it will wipe every "Wipe Period" layers. With the default of three, wipe will wipe just before layer zero, layer three, layer six and so on. - -==Examples== -The following examples wipe the file Screw Holder Bottom.stl. The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and wipe.py. - -> python wipe.py -This brings up the wipe dialog. - -> python wipe.py Screw Holder Bottom.stl -The wipe tool is parsing the file: -Screw Holder Bottom.stl -.. -The wipe tool has created the file: -.. Screw Holder Bottom_wipe.gcode - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities.vector3 import Vector3 -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_craft -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftedText( fileName, text, wipeRepository = None ): - """Wipe a gcode linear move text.""" - return getCraftedTextFromText( archive.getTextIfEmpty(fileName, text), wipeRepository ) - -def getCraftedTextFromText( gcodeText, wipeRepository = None ): - """Wipe a gcode linear move text.""" - if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'wipe'): - return gcodeText - if wipeRepository is None: - wipeRepository = settings.getReadRepository( WipeRepository() ) - if not wipeRepository.activateWipe.value: - return gcodeText - return WipeSkein().getCraftedGcode( gcodeText, wipeRepository ) - -def getNewRepository(): - """Get new repository.""" - return WipeRepository() - -def writeOutput(fileName, shouldAnalyze=True): - """Wipe a gcode linear move file.""" - skeinforge_craft.writeChainTextWithNounMessage(fileName, 'wipe', shouldAnalyze) - - -class WipeRepository: - """A class to handle the wipe settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.wipe.html', self ) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Wipe', self, '') - self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Wipe') - self.activateWipe = settings.BooleanSetting().getFromValue('Activate Wipe', self, False ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Location Arrival -', self ) - self.locationArrivalX = settings.FloatSpin().getFromValue( - 100.0, 'Location Arrival X (mm):', self, 300.0, 0.0 ) - self.locationArrivalY = settings.FloatSpin().getFromValue( - 100.0, 'Location Arrival Y (mm):', self, 300.0, 5.0 ) - self.locationArrivalZ = settings.FloatSpin().getFromValue( - 100.0, 'Location Arrival Z (mm):', self, 300.0, 0.0 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Location Departure -', self ) - self.locationDepartureX = settings.FloatSpin().getFromValue( - 100.0, 'Location Departure X (mm):', self, 300.0, 5.0 ) - self.locationDepartureY = settings.FloatSpin().getFromValue( - 100.0, 'Location Departure Y (mm):', self, 300.0, 0.0 ) - self.locationDepartureZ = settings.FloatSpin().getFromValue( - 100.0, 'Location Departure Z (mm):', self, 300.0, 0.0 ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Location Wipe -', self ) - self.locationWipeX = settings.FloatSpin().getFromValue( - 100.0, 'Location Wipe X (mm):', self, 300.0, 0.0 ) - self.locationWipeY = settings.FloatSpin().getFromValue( - 100.0, 'Location Wipe Y (mm):', self, 300.0, 0.0 ) - self.locationWipeZ = settings.FloatSpin().getFromValue( - 100.0, 'Location Wipe Z (mm):', self, 300.0, 0.0 ) - settings.LabelSeparator().getFromRepository(self) - self.wipePeriod = settings.IntSpin().getFromValue( 1, 'Wipe Period (layers):', self, 50000, 33333 ) - self.executeTitle = 'Wipe' - - def execute(self): - """Wipe button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled) - for fileName in fileNames: - writeOutput(fileName) - - -class WipeSkein: - """A class to wipe a skein of extrusions.""" - def __init__(self): - self.distanceFeedRate = gcodec.DistanceFeedRate() - self.extruderActive = False - self.highestZ = None - self.layerIndex = - 1 - self.lineIndex = 0 - self.lines = None - self.oldLocation = None - self.shouldWipe = False - self.travelFeedRateMinute = 957.0 - - def addHop( self, begin, end ): - """Add hop to highest point.""" - beginEndDistance = begin.distance(end) - if beginEndDistance < 3.0 * self.absolutePerimeterWidth: - return - alongWay = self.absolutePerimeterWidth / beginEndDistance - closeToOldLocation = euclidean.getIntermediateLocation( alongWay, begin, end ) - closeToOldLocation.z = self.highestZ - self.distanceFeedRate.addLine( self.getLinearMoveWithFeedRate( self.travelFeedRateMinute, closeToOldLocation ) ) - closeToOldArrival = euclidean.getIntermediateLocation( alongWay, end, begin ) - closeToOldArrival.z = self.highestZ - self.distanceFeedRate.addLine( self.getLinearMoveWithFeedRate( self.travelFeedRateMinute, closeToOldArrival ) ) - - def addWipeTravel( self, splitLine ): - """Add the wipe travel gcode.""" - location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - self.highestZ = max( self.highestZ, location.z ) - if not self.shouldWipe: - return - self.shouldWipe = False - if self.extruderActive: - self.distanceFeedRate.addLine('M103') - if self.oldLocation is not None: - self.addHop( self.oldLocation, self.locationArrival ) - self.distanceFeedRate.addLine( self.getLinearMoveWithFeedRate( self.travelFeedRateMinute, self.locationArrival ) ) - self.distanceFeedRate.addLine( self.getLinearMoveWithFeedRate( self.travelFeedRateMinute, self.locationWipe ) ) - self.distanceFeedRate.addLine( self.getLinearMoveWithFeedRate( self.travelFeedRateMinute, self.locationDeparture ) ) - self.addHop( self.locationDeparture, location ) - if self.extruderActive: - self.distanceFeedRate.addLine('M101') - - def getCraftedGcode( self, gcodeText, wipeRepository ): - """Parse gcode text and store the wipe gcode.""" - self.lines = archive.getTextLines(gcodeText) - self.wipePeriod = wipeRepository.wipePeriod.value - self.parseInitialization( wipeRepository ) - self.locationArrival = Vector3( wipeRepository.locationArrivalX.value, wipeRepository.locationArrivalY.value, wipeRepository.locationArrivalZ.value ) - self.locationDeparture = Vector3( wipeRepository.locationDepartureX.value, wipeRepository.locationDepartureY.value, wipeRepository.locationDepartureZ.value ) - self.locationWipe = Vector3( wipeRepository.locationWipeX.value, wipeRepository.locationWipeY.value, wipeRepository.locationWipeZ.value ) - for self.lineIndex in xrange(self.lineIndex, len(self.lines)): - line = self.lines[self.lineIndex] - self.parseLine(line) - return self.distanceFeedRate.output.getvalue() - - def getLinearMoveWithFeedRate( self, feedRate, location ): - """Get a linear move line with the feedRate.""" - return self.distanceFeedRate.getLinearGcodeMovementWithFeedRate( feedRate, location.dropAxis(), location.z ) - - def parseInitialization( self, wipeRepository ): - """Parse gcode initialization and store the parameters.""" - for self.lineIndex in xrange(len(self.lines)): - line = self.lines[self.lineIndex] - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - firstWord = gcodec.getFirstWord(splitLine) - self.distanceFeedRate.parseSplitLine(firstWord, splitLine) - if firstWord == '()': - self.distanceFeedRate.addLine('( wipe )') - return - elif firstWord == '(': - self.absolutePerimeterWidth = abs(float(splitLine[1])) - elif firstWord == '(': - self.travelFeedRateMinute = 60.0 * float(splitLine[1]) - self.distanceFeedRate.addLine(line) - - def parseLine(self, line): - """Parse a gcode line and add it to the bevel gcode.""" - splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) - if len(splitLine) < 1: - return - firstWord = splitLine[0] - if firstWord == 'G1': - self.addWipeTravel(splitLine) - self.oldLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine) - elif firstWord == '(': - settings.printProgress(self.layerIndex, 'wipe') - self.layerIndex += 1 - if not self.layerIndex % self.wipePeriod: - self.shouldWipe = True - elif firstWord == 'M101': - self.extruderActive = True - elif firstWord == 'M103': - self.extruderActive = False - self.distanceFeedRate.addLine(line) - - -def main(): - """Display the wipe dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/help.py b/skeinforge/skeinforge_application/skeinforge_plugins/help.py deleted file mode 100644 index b55ff8f..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/help.py +++ /dev/null @@ -1,82 +0,0 @@ -""" -This page is in the table of contents. -Help has buttons and menu items to open help, blog and forum pages in your primary browser. - - -==Link Buttons== -===Announcements=== -====Fabmetheus Blog==== -The skeinforge announcements blog and the place to post questions, bugs and skeinforge requests. - -===Documentation=== -====Index of Local Documentation==== -The list of the pages in the documentation folder. - -====Wiki Manual==== -The skeinforge wiki with pictures and charts. It is the best and most readable source of skeinforge information and you are welcome to contribute. - -====Skeinforge Overview==== -A general description of skeinforge, has answers to frequently asked questions and has many links to skeinforge, fabrication and python pages. It is also the help page of the skeinforge tool. - -===Forums=== -====Bits from Bytes Printing Board==== -Board about printing questions, problems and solutions. Most of the people on that forum use the rapman, but many of the solutions apply to any reprap. - -====Bits from Bytes Software Board==== -Board about software, and has some skeinforge threads. - -====Skeinforge Contributions Thread==== -Forum thread about how to contribute to skeinforge development. - -====Skeinforge Settings Thread==== -Forum thread for people to post, download and discuss skeinforge settings. - -==Settings== -===Wiki Manual Primary=== -Default is on. - -The help menu has an item for each button on the help page. Also, at the very top, it has a link to the local documentation and if there is a separate page for that tool in the wiki manual, a link to that page on the manual. If the 'Wiki Manual Primary' checkbutton is selected and there is a separate wiki manual page, the wiki page will be the primary document page, otherwise the local page will be primary. The help button (? symbol button) on the tool page will open the primary page, as will pressing . For example, if you click the the help button from the chamber tool, which has a separate page in the wiki, and 'Wiki Manual Primary' is selected, the wiki manual chamber page will be opened. Clicking F1 will also open the wiki manual chamber page. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_help -import os - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addToMenu( master, menu, repository, window ): - """Add a tool plugin menu.""" - path = settings.getPathInFabmetheusFromFileNameHelp( repository.fileNameHelp ) - capitalizedBasename = os.path.basename(path).capitalize() - helpRepository = settings.getReadRepository( skeinforge_help.HelpRepository() ) - if repository.openWikiManualHelpPage is not None and helpRepository.wikiManualPrimary.value: - menu.add_command( label = 'Local ' + capitalizedBasename, command = repository.openLocalHelpPage ) - else: - settings.addAcceleratorCommand('', repository.openLocalHelpPage, master, menu, 'Local ' + capitalizedBasename ) - if repository.openWikiManualHelpPage is not None: - if helpRepository.wikiManualPrimary.value: - settings.addAcceleratorCommand('', repository.openWikiManualHelpPage, master, menu, 'Wiki Manual ' + capitalizedBasename ) - else: - menu.add_command( label = 'Wiki Manual ' + capitalizedBasename, command = repository.openWikiManualHelpPage ) - menu.add_separator() - settings.addMenuEntitiesToMenu( menu, helpRepository.menuEntities ) - -def getNewRepository(): - """Get new repository.""" - return skeinforge_help.HelpRepository() - -def main(): - """Display the help dialog.""" - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/meta.py b/skeinforge/skeinforge_application/skeinforge_plugins/meta.py deleted file mode 100644 index 9635272..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/meta.py +++ /dev/null @@ -1,34 +0,0 @@ -""" -This page is in the table of contents. -Meta is a script to access the plugins which handle meta information. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_meta - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addToMenu( master, menu, repository, window ): - """Add a tool plugin menu.""" - settings.addPluginsParentToMenu( skeinforge_meta.getPluginsDirectoryPath(), menu, __file__, skeinforge_meta.getPluginFileNames() ) - -def getNewRepository(): - """Get new repository.""" - return skeinforge_meta.MetaRepository() - - -def main(): - """Display the meta dialog.""" - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/meta_plugins/__init__.py b/skeinforge/skeinforge_application/skeinforge_plugins/meta_plugins/__init__.py deleted file mode 100644 index 1121e8a..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/meta_plugins/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/meta_plugins/description.py b/skeinforge/skeinforge_application/skeinforge_plugins/meta_plugins/description.py deleted file mode 100644 index 2c71db7..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/meta_plugins/description.py +++ /dev/null @@ -1,51 +0,0 @@ -""" -This page is in the table of contents. -Description is a script to store a description of the profile. - -==Settings== -===Description Text=== -Default is empty. - -The suggested format is a description, followed by a link to a profile post or web page. - -==Example== -Example of using description follows below. - -> python description.py -This brings up the description dialog. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_profile - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewRepository(): - """Get new repository.""" - return DescriptionRepository() - - -class DescriptionRepository: - """A class to handle the description settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.meta_plugins.description.html', self) - description = 'Write your description of the profile here.\n\nSuggested format is a description, followed by a link to the profile post or web page.' - self.descriptionText = settings.TextSetting().getFromValue('Description Text:', self, description ) - - -def main(): - """Display the file or directory dialog.""" - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/meta_plugins/polyfile.py b/skeinforge/skeinforge_application/skeinforge_plugins/meta_plugins/polyfile.py deleted file mode 100644 index 9493f80..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/meta_plugins/polyfile.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -This page is in the table of contents. -Polyfile is a script to choose whether the skeinforge toolchain will operate on one file or all the files in a directory. - -==Settings== -===Polyfile Choice=== -Default is 'Execute File', - -====Execute File==== -When selected, the toolchain will operate on only the chosen file. - -====Execute All Unmodified Files in a Directory'==== -When selected, the toolchain will operate on all the unmodifed files in the directory that the chosen file is in. - -==Example== -Example of using polyfile follows below. - -> python polyfile.py -This brings up the polyfile dialog. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewRepository(): - """Get new repository.""" - return skeinforge_polyfile.PolyfileRepository() - - -def main(): - """Display the file or directory dialog.""" - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/profile.py b/skeinforge/skeinforge_application/skeinforge_plugins/profile.py deleted file mode 100644 index 9a7ca42..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/profile.py +++ /dev/null @@ -1,115 +0,0 @@ -""" -This page is in the table of contents. -Profile is a script to set the craft types setting for the skeinforge chain. - -Profile presents the user with a choice of the craft types in the profile_plugins folder. The chosen craft type is used to determine the craft type profile for the skeinforge chain. The default craft type is extrusion. - -The setting is the selection. If you hit 'Save and Close' the selection will be saved, if you hit 'Cancel' the selection will not be saved. - -To change the profile setting, in a shell in the profile folder type: -> python profile.py - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import os - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addSubmenus( craftTypeName, menu, pluginFileName, pluginPath, profileRadioVar ): - """Add a tool plugin menu.""" - submenu = settings.Tkinter.Menu( menu, tearoff = 0 ) - menu.add_cascade( label = pluginFileName.capitalize(), menu = submenu ) - settings.ToolDialog().addPluginToMenu( submenu, pluginPath ) - submenu.add_separator() - pluginModule = skeinforge_profile.getCraftTypePluginModule( pluginFileName ) - profilePluginSettings = settings.getReadRepository( pluginModule.getNewRepository() ) - isSelected = ( craftTypeName == pluginFileName ) - for profileName in profilePluginSettings.profileList.value: - value = isSelected and profileName == profilePluginSettings.profileListbox.value - ProfileMenuRadio( pluginFileName, submenu, profileName, profileRadioVar, value ) - -def addToProfileMenu( menu ): - """Add a profile menu.""" - settings.ToolDialog().addPluginToMenu( menu, __file__[ : __file__.rfind('.') ] ) - menu.add_separator() - directoryPath = skeinforge_profile.getPluginsDirectoryPath() - pluginFileNames = skeinforge_profile.getPluginFileNames() - craftTypeName = skeinforge_profile.getCraftTypeName() - profileRadioVar = settings.Tkinter.StringVar() - for pluginFileName in pluginFileNames: - addSubmenus( craftTypeName, menu, pluginFileName, os.path.join( directoryPath, pluginFileName ), profileRadioVar ) - -def addToMenu( master, menu, repository, window ): - """Add a tool plugin menu.""" - ProfileMenuSaveListener( menu, window ) - -def getNewRepository(): - """Get new repository.""" - return skeinforge_profile.ProfileRepository() - - -class ProfileMenuRadio: - """A class to display a profile menu radio button.""" - def __init__( self, profilePluginFileName, menu, name, radioVar, value ): - """Create a profile menu radio.""" - self.activate = False - self.menu = menu - self.name = name - self.profileJoinName = profilePluginFileName + '.& /' + name - self.profilePluginFileName = profilePluginFileName - self.radioVar = radioVar - menu.add_radiobutton( label = name.replace('_', ' '), command = self.clickRadio, value = self.profileJoinName, variable = self.radioVar ) - self.menuLength = menu.index( settings.Tkinter.END ) - if value: - self.radioVar.set( self.profileJoinName ) - self.menu.invoke( self.menuLength ) - self.activate = True - - def clickRadio(self): - """Workaround for Tkinter bug, invoke and set the value when clicked.""" - if not self.activate: - return - self.radioVar.set( self.profileJoinName ) - pluginModule = skeinforge_profile.getCraftTypePluginModule( self.profilePluginFileName ) - profilePluginSettings = settings.getReadRepository( pluginModule.getNewRepository() ) - profilePluginSettings.profileListbox.value = self.name - settings.writeSettings( profilePluginSettings ) - profileSettings = skeinforge_profile.getReadProfileRepository() - plugins = profileSettings.craftRadios - for plugin in plugins: - plugin.value = ( plugin.name == self.profilePluginFileName ) - settings.writeSettings( profileSettings ) - skeinforge_profile.updateProfileSaveListeners() - - -class ProfileMenuSaveListener: - """A class to update a profile menu.""" - def __init__( self, menu, window ): - """Set the menu.""" - self.menu = menu - addToProfileMenu( menu ) - euclidean.addElementToListDictionaryIfNotThere( self, window, settings.globalProfileSaveListenerListTable ) - - def save(self): - """Profile has been saved and profile menu should be updated.""" - settings.deleteMenuItems( self.menu ) - addToProfileMenu( self.menu ) - - -def main(): - """Display the profile dialog.""" - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/profile_plugins/__init__.py b/skeinforge/skeinforge_application/skeinforge_plugins/profile_plugins/__init__.py deleted file mode 100644 index 1121e8a..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/profile_plugins/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 3 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/profile_plugins/cutting.py b/skeinforge/skeinforge_application/skeinforge_plugins/profile_plugins/cutting.py deleted file mode 100644 index 94b9eb8..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/profile_plugins/cutting.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -This page is in the table of contents. -Cutting is a script to set the cutting profile for the skeinforge chain. - -The displayed craft sequence is the sequence in which the tools craft the model and export the output. - -On the cutting dialog, clicking the 'Add Profile' button will duplicate the selected profile and give it the name in the input field. For example, if laser is selected and the name laser_10mm is in the input field, clicking the 'Add Profile' button will duplicate laser and save it as laser_10mm. The 'Delete Profile' button deletes the selected profile. - -The profile selection is the setting. If you hit 'Save and Close' the selection will be saved, if you hit 'Cancel' the selection will not be saved. However; adding and deleting a profile is a permanent action, for example 'Cancel' will not bring back any deleted profiles. - -To change the cutting profile, in a shell in the profile_plugins folder type: -> python cutting.py - -""" - - -from __future__ import absolute_import -import __init__ -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftSequence(): - """Get the cutting craft sequence.""" - return 'chop preface outset multiply whittle drill lift flow feed home lash fillet limit unpause export'.split() - -def getNewRepository(): - """Get new repository.""" - return CuttingRepository() - - -class CuttingRepository: - """A class to handle the cutting settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsSetCraftProfile( getCraftSequence(), 'end_mill', self, 'skeinforge_plugins.profile_plugins.cutting.html') - - -def main(): - """Display the export dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/profile_plugins/extrusion.py b/skeinforge/skeinforge_application/skeinforge_plugins/profile_plugins/extrusion.py deleted file mode 100644 index e3678f1..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/profile_plugins/extrusion.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -This page is in the table of contents. -Extrusion is a script to set the extrusion profile for the skeinforge chain. - -The displayed craft sequence is the sequence in which the tools craft the model and export the output. - -On the extrusion dialog, clicking the 'Add Profile' button will duplicate the selected profile and give it the name in the input field. For example, if ABS is selected and the name ABS_black is in the input field, clicking the 'Add Profile' button will duplicate ABS and save it as ABS_black. The 'Delete Profile' button deletes the selected profile. - -The profile selection is the setting. If you hit 'Save and Close' the selection will be saved, if you hit 'Cancel' the selection will not be saved. However; adding and deleting a profile is a permanent action, for example 'Cancel' will not bring back any deleted profiles. - -To change the extrusion profile, in a shell in the profile_plugins folder type: -> python extrusion.py - -""" - - -from __future__ import absolute_import -import __init__ -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftSequence(): - """Get the extrusion craft sequence.""" - return 'carve scale bottom preface inset fill multiply speed temperature raft skirt chamber jitter clip stretch skin comb cool wipe lash limit dimension export'.split() - -def getNewRepository(): - """Get new repository.""" - return ExtrusionRepository() - - -class ExtrusionRepository: - """A class to handle the export settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsSetCraftProfile( getCraftSequence(), 'PLA', self, 'skeinforge_plugins.profile_plugins.extrusion.html') - - -def main(): - """Display the export dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == '__main__': - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/profile_plugins/milling.py b/skeinforge/skeinforge_application/skeinforge_plugins/profile_plugins/milling.py deleted file mode 100644 index 0e11a63..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/profile_plugins/milling.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -This page is in the table of contents. -Milling is a script to set the milling profile for the skeinforge chain. - -The displayed craft sequence is the sequence in which the tools craft the model and export the output. - -On the milling dialog, clicking the 'Add Profile' button will duplicate the selected profile and give it the name in the input field. For example, if laser is selected and the name laser_10mm is in the input field, clicking the 'Add Profile' button will duplicate laser and save it as laser_10mm. The 'Delete Profile' button deletes the selected profile. - -The profile selection is the setting. If you hit 'Save and Close' the selection will be saved, if you hit 'Cancel' the selection will not be saved. However; adding and deleting a profile is a permanent action, for example 'Cancel' will not bring back any deleted profiles. - -To change the milling profile, in a shell in the profile_plugins folder type: -> python milling.py - -""" - - -from __future__ import absolute_import -import __init__ -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftSequence(): - """Get the milling craft sequence.""" - return 'chop preface outset mill multiply drill lift flow feed home lash fillet limit unpause export'.split() - -def getNewRepository(): - """Get new repository.""" - return MillingRepository() - - -class MillingRepository: - """A class to handle the milling settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsSetCraftProfile( getCraftSequence(), 'end_mill', self, 'skeinforge_plugins.profile_plugins.milling.html') - - -def main(): - """Display the export dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_plugins/profile_plugins/winding.py b/skeinforge/skeinforge_application/skeinforge_plugins/profile_plugins/winding.py deleted file mode 100644 index 4e246f2..0000000 --- a/skeinforge/skeinforge_application/skeinforge_plugins/profile_plugins/winding.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -This page is in the table of contents. -Winding is a script to set the winding profile for the skeinforge chain. - -The displayed craft sequence is the sequence in which the tools craft the model and export the output. - -On the winding dialog, clicking the 'Add Profile' button will duplicate the selected profile and give it the name in the input field. For example, if laser is selected and the name laser_10mm is in the input field, clicking the 'Add Profile' button will duplicate laser and save it as laser_10mm. The 'Delete Profile' button deletes the selected profile. - -The profile selection is the setting. If you hit 'Save and Close' the selection will be saved, if you hit 'Cancel' the selection will not be saved. However; adding and deleting a profile is a permanent action, for example 'Cancel' will not bring back any deleted profiles. - -To change the winding profile, in a shell in the profile_plugins folder type: -> python winding.py - -""" - - -from __future__ import absolute_import -import __init__ -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getCraftSequence(): - """Get the winding craft sequence.""" - return 'cleave preface coil flow feed home lash fillet limit unpause export'.split() - -def getNewRepository(): - """Get new repository.""" - return WindingRepository() - - -class WindingRepository: - """A class to handle the winding settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsSetCraftProfile( getCraftSequence(), 'free_wire', self, 'skeinforge_plugins.profile_plugins.winding.html') - - -def main(): - """Display the export dialog.""" - if len(sys.argv) > 1: - writeOutput(' '.join(sys.argv[1 :])) - else: - settings.startMainLoopFromConstructor( getNewRepository() ) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_utilities/__init__.py b/skeinforge/skeinforge_application/skeinforge_utilities/__init__.py deleted file mode 100644 index 2dc8ddc..0000000 --- a/skeinforge/skeinforge_application/skeinforge_utilities/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -#This is required to workaround the python import bug where relative imports don't work if the module is imported as a main module. -import os -import sys -numberOfLevelsDeepInPackageHierarchy = 2 -packageFilePath = os.path.abspath(__file__) -for level in range( numberOfLevelsDeepInPackageHierarchy + 1 ): - packageFilePath = os.path.dirname( packageFilePath ) -if packageFilePath not in sys.path: - sys.path.insert( 0, packageFilePath ) diff --git a/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_analyze.py b/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_analyze.py deleted file mode 100644 index a4e79d5..0000000 --- a/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_analyze.py +++ /dev/null @@ -1,80 +0,0 @@ -""" -Analyze is a script to access the plugins which analyze a gcode file. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import archive -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import sys -import traceback - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewRepository(): - """Get new repository.""" - return AnalyzeRepository() - -def getPluginFileNames(): - """Get analyze plugin fileNames.""" - return archive.getPluginFileNamesFromDirectoryPath( getPluginsDirectoryPath() ) - -def getPluginsDirectoryPath(): - """Get the plugins directory path.""" - return archive.getSkeinforgePluginsPath('analyze_plugins') - -def writeOutput(fileName, fileNamePenultimate, fileNameSuffix, filePenultimateWritten, gcodeText=''): - """Analyze a gcode file.""" - gcodeText = archive.getTextIfEmpty(fileName, gcodeText) - pluginFileNames = getPluginFileNames() - window = None - for pluginFileName in pluginFileNames: - analyzePluginsDirectoryPath = getPluginsDirectoryPath() - pluginModule = archive.getModuleWithDirectoryPath( analyzePluginsDirectoryPath, pluginFileName ) - if pluginModule is not None: - try: - newWindow = pluginModule.writeOutput(fileName, fileNamePenultimate, fileNameSuffix, - filePenultimateWritten, gcodeText ) - if newWindow is not None: - window = newWindow - except: - print('Warning, the tool %s could not analyze the output.' % pluginFileName ) - print('Exception traceback in writeOutput in skeinforge_analyze:') - traceback.print_exc(file=sys.stdout) - return window - - -class AnalyzeRepository: - """A class to handle the analyze settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_utilities.skeinforge_analyze.html', self) - self.fileNameInput = settings.FileNameInput().getFromFileName( [ ('Gcode text files', '*.gcode') ], 'Open File for Analyze', self, '') - importantFileNames = ['skeiniso', 'skeinlayer', 'statistic'] - settings.getRadioPluginsAddPluginFrame( getPluginsDirectoryPath(), importantFileNames, getPluginFileNames(), self ) - self.executeTitle = 'Analyze' - - def execute(self): - """Analyze button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode( self.fileNameInput.value, [], self.fileNameInput.wasCancelled ) - for fileName in fileNames: - writeOutput( fileName, fileName ) - - -def main(): - """Write analyze output.""" - fileName = ' '.join(sys.argv[1 :]) - settings.startMainLoopFromWindow(writeOutput(fileName, fileName)) - - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_craft.py b/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_craft.py deleted file mode 100644 index 4840557..0000000 --- a/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_craft.py +++ /dev/null @@ -1,226 +0,0 @@ -""" -Craft is a script to access the plugins which craft a gcode file. - -The plugin buttons which are commonly used are bolded and the ones which are rarely used have normal font weight. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_analyze -from skeinforge_application.skeinforge_utilities import skeinforge_polyfile -from skeinforge_application.skeinforge_utilities import skeinforge_profile -import os -import sys -import time - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getChainText( fileName, procedure ): - """Get a crafted shape file.""" - text='' - if fileName.endswith('.gcode') or fileName.endswith('.svg'): - text = archive.getFileText(fileName) - procedures = getProcedures( procedure, text ) - return getChainTextFromProcedures( fileName, procedures, text ) - -def getChainTextFromProcedures(fileName, procedures, text): - """Get a crafted shape file from a list of procedures.""" - lastProcedureTime = time.time() - for procedure in procedures: - craftModule = getCraftModule(procedure) - if craftModule is not None: - text = craftModule.getCraftedText(fileName, text) - if text == '': - print('Warning, the text was not recognized in getChainTextFromProcedures in skeinforge_craft for') - print(fileName) - return '' - if gcodec.isProcedureDone( text, procedure ): - print('%s procedure took %s.' % (procedure.capitalize(), euclidean.getDurationString(time.time() - lastProcedureTime))) - lastProcedureTime = time.time() - return text - -def getCraftModule(fileName): - """Get craft module.""" - return archive.getModuleWithDirectoryPath( getPluginsDirectoryPath(), fileName ) - -def getLastModule(): - """Get the last tool.""" - craftSequence = getReadCraftSequence() - if len( craftSequence ) < 1: - return None - return getCraftModule( craftSequence[-1] ) - -def getNewRepository(): - """Get new repository.""" - return CraftRepository() - -def getPluginsDirectoryPath(): - """Get the plugins directory path.""" - return archive.getSkeinforgePluginsPath('craft_plugins') - -def getPluginFileNames(): - """Get craft plugin fileNames.""" - craftSequence = getReadCraftSequence() - craftSequence.sort() - return craftSequence - -def getProcedures( procedure, text ): - """Get the procedures up to and including the given procedure.""" - craftSequence = getReadCraftSequence() - sequenceIndexPlusOneFromText = getSequenceIndexPlusOneFromText(text) - sequenceIndexFromProcedure = getSequenceIndexFromProcedure(procedure) - return craftSequence[ sequenceIndexPlusOneFromText : sequenceIndexFromProcedure + 1 ] - -def getReadCraftSequence(): - """Get profile sequence.""" - return skeinforge_profile.getCraftTypePluginModule().getCraftSequence() - -def getSequenceIndexFromProcedure(procedure): - """Get the profile sequence index of the procedure. Return None if the procedure is not in the sequence""" - craftSequence = getReadCraftSequence() - if procedure not in craftSequence: - return 0 - return craftSequence.index(procedure) - -def getSequenceIndexPlusOneFromText(fileText): - """Get the profile sequence index of the file plus one. Return zero if the procedure is not in the file""" - craftSequence = getReadCraftSequence() - for craftSequenceIndex in xrange( len( craftSequence ) - 1, - 1, - 1 ): - procedure = craftSequence[ craftSequenceIndex ] - if gcodec.isProcedureDone( fileText, procedure ): - return craftSequenceIndex + 1 - return 0 - -def writeChainTextWithNounMessage(fileName, procedure, shouldAnalyze=True): - """Get and write a crafted shape file.""" - print('') - print('The %s tool is parsing the file:' % procedure) - print(os.path.basename(fileName)) - print('') - startTime = time.time() - fileNameSuffix = fileName[: fileName.rfind('.')] + '_' + procedure + '.gcode' - craftText = getChainText(fileName, procedure) - if craftText == '': - print('Warning, there was no text output in writeChainTextWithNounMessage in skeinforge_craft for:') - print(fileName) - return - archive.writeFileText(fileNameSuffix, craftText) - window = None - if shouldAnalyze: - window = skeinforge_analyze.writeOutput(fileName, fileNameSuffix, fileNameSuffix, True, craftText) - print('') - print('The %s tool has created the file:' % procedure) - print(fileNameSuffix) - print('') - print('It took %s to craft the file.' % euclidean.getDurationString(time.time() - startTime)) - return window - -def writeOutput(fileName, shouldAnalyze=True): - """Craft a gcode file with the last module.""" - pluginModule = getLastModule() - if pluginModule is not None: - return pluginModule.writeOutput(fileName, shouldAnalyze) - -def writeSVGTextWithNounMessage(fileName, repository, shouldAnalyze=True): - """Get and write an svg text and print messages.""" - print('') - print('The %s tool is parsing the file:' % repository.lowerName) - print(os.path.basename(fileName)) - print('') - startTime = time.time() - fileNameSuffix = fileName[: fileName.rfind('.')] + '_' + repository.lowerName + '.svg' - craftText = getChainText(fileName, repository.lowerName) - if craftText == '': - return - archive.writeFileText(fileNameSuffix, craftText) - print('') - print('The %s tool has created the file:' % repository.lowerName) - print(fileNameSuffix) - print('') - print('It took %s to craft the file.' % euclidean.getDurationString(time.time() - startTime)) - if shouldAnalyze: - settings.getReadRepository(repository) - settings.openSVGPage(fileNameSuffix, repository.svgViewer.value) - - -class CraftRadioButtonsSaveListener: - """A class to update the craft radio buttons.""" - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - euclidean.addElementToListDictionaryIfNotThere( self, self.repository.repositoryDialog, settings.globalProfileSaveListenerListTable ) - self.gridPosition = gridPosition.getCopy() - self.gridPosition.row = gridPosition.rowStart - self.gridPosition.increment() - self.setRadioButtons() - - def getFromRadioPlugins( self, radioPlugins, repository ): - """Initialize.""" - self.name = 'CraftRadioButtonsSaveListener' - self.radioPlugins = radioPlugins - self.repository = repository - repository.displayEntities.append(self) - return self - - def save(self): - """Profile has been saved and craft radio plugins should be updated.""" - self.setRadioButtons() - - def setRadioButtons(self): - """Profile has been saved and craft radio plugins should be updated.""" - activeRadioPlugins = [] - craftSequence = skeinforge_profile.getCraftTypePluginModule().getCraftSequence() - gridPosition = self.gridPosition.getCopy() - isRadioPluginSelected = False - settings.getReadRepository(self.repository) - for radioPlugin in self.radioPlugins: - if radioPlugin.name in craftSequence: - activeRadioPlugins.append(radioPlugin) - radioPlugin.incrementGridPosition(gridPosition) - if radioPlugin.value: - radioPlugin.setSelect() - isRadioPluginSelected = True - else: - radioPlugin.radiobutton.grid_remove() - if not isRadioPluginSelected: - radioPluginNames = self.repository.importantFileNames + [activeRadioPlugins[0].name] - settings.getSelectedRadioPlugin(radioPluginNames , activeRadioPlugins).setSelect() - self.repository.pluginFrame.update() - - -class CraftRepository: - """A class to handle the craft settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_utilities.skeinforge_craft.html', self) - self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Craft', self, '') - self.importantFileNames = ['carve', 'chop', 'feed', 'flow', 'lift', 'raft', 'speed'] - allCraftNames = archive.getPluginFileNamesFromDirectoryPath(getPluginsDirectoryPath()) - self.radioPlugins = settings.getRadioPluginsAddPluginFrame(getPluginsDirectoryPath(), self.importantFileNames, allCraftNames, self) - CraftRadioButtonsSaveListener().getFromRadioPlugins(self.radioPlugins, self) - self.executeTitle = 'Craft' - - def execute(self): - """Craft button has been clicked.""" - fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode( self.fileNameInput.value, [], self.fileNameInput.wasCancelled ) - for fileName in fileNames: - writeOutput(fileName) - - -def main(): - """Write craft output.""" - writeOutput(' '.join(sys.argv[1 :]), False) - -if __name__ == "__main__": - main() diff --git a/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_help.py b/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_help.py deleted file mode 100644 index 81e47af..0000000 --- a/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_help.py +++ /dev/null @@ -1,66 +0,0 @@ -""" -Help has buttons and menu items to open help, blog and forum pages in your primary browser. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_profile - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getNewRepository(): - """Get new repository.""" - return HelpRepository() - - -class HelpRepository: - """A class to handle the help settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_utilities.skeinforge_help.html', self) - settings.LabelDisplay().getFromName('- Announcements -', self ) - settings.LabelDisplay().getFromName('Fabmetheus Blog, Announcements & Questions:', self ) - settings.HelpPage().getFromNameAfterHTTP('fabmetheus.blogspot.com/', 'Fabmetheus Blog', self ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Documentation -', self ) - settings.LabelDisplay().getFromName('Local Documentation Table of Contents: ', self ) - settings.HelpPage().getFromNameSubName('Contents', self, 'contents.html') - settings.LabelDisplay().getFromName('Wiki Manual with Pictures & Charts: ', self ) - settings.HelpPage().getFromNameAfterHTTP('fabmetheus.crsndoo.com/wiki/index.php/Skeinforge', 'Wiki Manual', self ) - settings.LabelDisplay().getFromName('Skeinforge Overview: ', self ) - settings.HelpPage().getFromNameSubName('Skeinforge Overview', self, 'skeinforge_application.skeinforge.html') - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Forums -', self ) - settings.LabelDisplay().getFromName('Bits from Bytes Software Board:', self ) - settings.HelpPage().getFromNameAfterWWW('bitsfrombytes.com/fora/user/index.php?board=4.0', 'Bits from Bytes Software Board', self ) - settings.LabelDisplay().getFromName('Makerbot Operators:', self ) - settings.HelpPage().getFromNameAfterHTTP('groups.google.com/group/makerbot', 'Makerbot Operators', self ) - settings.LabelDisplay().getFromName('Skeinforge Contributions Thread:', self ) - settings.HelpPage().getFromNameAfterHTTP('dev.forums.reprap.org/read.php?12,27562', 'Skeinforge Contributions Thread', self ) - settings.LabelDisplay().getFromName('Skeinforge Settings Thread:', self ) - settings.HelpPage().getFromNameAfterHTTP('dev.forums.reprap.org/read.php?12,27434', 'Skeinforge Settings Thread', self ) - settings.LabelDisplay().getFromName('Skeinforge Troubleshooting Thread:', self ) - settings.HelpPage().getFromNameAfterHTTP('forums.reprap.org/list.php?154', 'Skeinforge Troubleshooting Thread', self ) - settings.LabelSeparator().getFromRepository(self) - settings.LabelDisplay().getFromName('- Search -', self ) - settings.LabelDisplay().getFromName('Reprap Search:', self ) - settings.HelpPage().getFromNameAfterHTTP('members.axion.net/~enrique/search_reprap.html', 'Reprap Search', self ) - settings.LabelDisplay().getFromName('Skeinforge Search:', self ) - settings.HelpPage().getFromNameAfterHTTP('members.axion.net/~enrique/search_skeinforge.html', 'Skeinforge Search', self ) - settings.LabelDisplay().getFromName('Web Search:', self ) - settings.HelpPage().getFromNameAfterHTTP('members.axion.net/~enrique/search_web.html', 'Web Search', self ) - settings.LabelSeparator().getFromRepository(self) - self.wikiManualPrimary = settings.BooleanSetting().getFromValue('Wiki Manual Primary', self, True ) - self.wikiManualPrimary.setUpdateFunction( self.save ) - - def save(self): - """Write the entities.""" - settings.writeSettingsPrintMessage(self) diff --git a/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_meta.py b/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_meta.py deleted file mode 100644 index 73371b5..0000000 --- a/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_meta.py +++ /dev/null @@ -1,40 +0,0 @@ -""" -Meta is a script to access the plugins which handle meta information. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import archive -from fabmetheus_utilities import gcodec -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_profile - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getPluginFileNames(): - """Get meta plugin file names.""" - return archive.getPluginFileNamesFromDirectoryPath( getPluginsDirectoryPath() ) - -def getPluginsDirectoryPath(): - """Get the plugins directory path.""" - return archive.getSkeinforgePluginsPath('meta_plugins') - -def getNewRepository(): - """Get new repository.""" - return MetaRepository() - - -class MetaRepository: - """A class to handle the meta settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_utilities.skeinforge_meta.html', self) - importantFileNames = ['polyfile'] - settings.getRadioPluginsAddPluginFrame( getPluginsDirectoryPath(), importantFileNames, getPluginFileNames(), self ) diff --git a/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_polyfile.py b/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_polyfile.py deleted file mode 100644 index 5a53be0..0000000 --- a/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_polyfile.py +++ /dev/null @@ -1,70 +0,0 @@ -""" -Polyfile is a script to choose whether the skeinforge toolchain will operate on one file or all the files in a directory. - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import archive -from fabmetheus_utilities import settings -from skeinforge_application.skeinforge_utilities import skeinforge_profile - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def getFileOrGcodeDirectory( fileName, wasCancelled, words = [] ): - """Get the gcode files in the directory the file is in if directory setting is true. Otherwise, return the file in a list.""" - if isEmptyOrCancelled( fileName, wasCancelled ): - return [] - if isDirectorySetting(): - dotIndex = fileName.rfind('.') - if dotIndex < 0: - print('The file name should have a suffix, like myfile.xml.') - print('Since the file name does not have a suffix, nothing will be done') - suffix = fileName[ dotIndex + 1 : ] - return archive.getFilesWithFileTypeWithoutWords( suffix, words, fileName ) - return [ fileName ] - -def getFileOrDirectoryTypes( fileName, fileTypes, wasCancelled ): - """Get the gcode files in the directory the file is in if directory setting is true. Otherwise, return the file in a list.""" - if isEmptyOrCancelled( fileName, wasCancelled ): - return [] - if isDirectorySetting(): - return archive.getFilesWithFileTypesWithoutWords( fileTypes, [], fileName ) - return [ fileName ] - -def getFileOrDirectoryTypesUnmodifiedGcode(fileName, fileTypes, wasCancelled): - """Get the gcode files in the directory the file is in if directory setting is true. Otherwise, return the file in a list.""" - if isEmptyOrCancelled(fileName, wasCancelled): - return [] - if isDirectorySetting(): - return archive.getFilesWithFileTypesWithoutWords(fileTypes, [], fileName) - return [fileName] - -def getNewRepository(): - """Get new repository.""" - return PolyfileRepository() - -def isDirectorySetting(): - """Determine if the directory setting is true.""" - return settings.getReadRepository( PolyfileRepository() ).directorySetting.value - -def isEmptyOrCancelled( fileName, wasCancelled ): - """Determine if the fileName is empty or the dialog was cancelled.""" - return str(fileName) == '' or str(fileName) == '()' or wasCancelled - - -class PolyfileRepository: - """A class to handle the polyfile settings.""" - def __init__(self): - """Set the default settings, execute title & settings fileName.""" - skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_utilities.skeinforge_plugins.polyfile.html', self) - self.directoryOrFileChoiceLabel = settings.LabelDisplay().getFromName('Directory or File Choice: ', self ) - directoryLatentStringVar = settings.LatentStringVar() - self.directorySetting = settings.Radio().getFromRadio( directoryLatentStringVar, 'Execute All Unmodified Files in a Directory', self, False ) - self.fileSetting = settings.Radio().getFromRadio( directoryLatentStringVar, 'Execute File', self, True ) diff --git a/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_profile.py b/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_profile.py deleted file mode 100644 index f1ba02c..0000000 --- a/skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_profile.py +++ /dev/null @@ -1,416 +0,0 @@ -""" -Profile is a script to set the craft types setting for the skeinforge chain. - -Profile presents the user with a choice of the craft types in the profile_plugins folder. The chosen craft type is used to determine the craft type profile for the skeinforge chain. The default craft type is extrusion. - -The setting is the selection. If you hit 'Save and Close' the selection will be saved, if you hit 'Cancel' the selection will not be saved. - -To change the profile setting, in a shell in the profile folder type: -> python profile.py - -""" - -from __future__ import absolute_import -#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module. -import __init__ - -from fabmetheus_utilities import archive -from fabmetheus_utilities import euclidean -from fabmetheus_utilities import settings -import os -import shutil - - -__author__ = 'Enrique Perez (perez_enrique@yahoo.com)' -__date__ = '$Date: 2008/21/04 $' -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - - -def addListsSetCraftProfile( craftSequence, defaultProfile, repository, fileNameHelp ): - """Set the craft profile repository.""" - settings.addListsToRepository(fileNameHelp, repository) - repository.craftSequenceLabel = settings.LabelDisplay().getFromName('Craft Sequence: ', repository ) - craftToolStrings = [] - for craftTool in craftSequence[ : - 1 ]: - craftToolStrings.append( settings.getEachWordCapitalized( craftTool ) + '->') - craftToolStrings.append( settings.getEachWordCapitalized( craftSequence[-1] ) ) - for craftToolStringIndex in xrange( 0, len( craftToolStrings ), 5 ): - craftLine = ' '.join( craftToolStrings[ craftToolStringIndex : craftToolStringIndex + 5 ] ) - settings.LabelDisplay().getFromName( craftLine, repository ) - settings.LabelDisplay().getFromName('', repository ) - repository.profileList = ProfileList().getFromName('Profile List:', repository ) - repository.profileListbox = ProfileListboxSetting().getFromListSetting( repository.profileList, 'Profile Selection:', repository, defaultProfile ) - repository.addListboxSelection = AddProfile().getFromProfileListboxSettingRepository( repository.profileListbox, repository ) - repository.deleteListboxSelection = DeleteProfile().getFromProfileListboxSettingRepository( repository.profileListbox, repository ) - directoryName = archive.getProfilesPath() - archive.makeDirectory(directoryName) - repository.windowPosition.value = '0+400' - -def addListsToCraftTypeRepository(fileNameHelp, repository): - """Add the value to the lists.""" - settings.addListsToRepositoryByFunction(fileNameHelp, getProfileDirectory, repository) - dotsMinusOne = fileNameHelp.count('.') - 1 - x = 0 - xAddition = 400 - for step in xrange(dotsMinusOne): - x += xAddition - xAddition /= 2 - repository.windowPosition.value = '%s+0' % x - -def cancelAll(): - """Cancel all the dialogs.""" - for globalRepositoryDialogValue in settings.getGlobalRepositoryDialogValues(): - globalRepositoryDialogValue.cancel() - -def getCraftTypeName(subName=''): - """Get the craft type from the profile.""" - profileSettings = getReadProfileRepository() - craftTypeName = settings.getSelectedPluginName( profileSettings.craftRadios ) - if subName == '': - return craftTypeName - return os.path.join( craftTypeName, subName ) - -def getCraftTypePluginModule( craftTypeName = ''): - """Get the craft type plugin module.""" - if craftTypeName == '': - craftTypeName = getCraftTypeName() - profilePluginsDirectoryPath = getPluginsDirectoryPath() - return archive.getModuleWithDirectoryPath( profilePluginsDirectoryPath, craftTypeName ) - -def getNewRepository(): - """Get new repository.""" - return ProfileRepository() - -def getPluginFileNames(): - """Get analyze plugin fileNames.""" - return archive.getPluginFileNamesFromDirectoryPath( getPluginsDirectoryPath() ) - -def getPluginsDirectoryPath(): - """Get the plugins directory path.""" - return archive.getSkeinforgePluginsPath('profile_plugins') - -def getProfileDirectory(): - """Get the profile directory.""" - craftTypeName = getCraftTypeName() - return os.path.join( craftTypeName, getProfileName( craftTypeName ) ) - -def getProfileName( craftTypeName ): - """Get the profile name from the craft type name.""" - craftTypeSettings = getCraftTypePluginModule( craftTypeName ).getNewRepository() - settings.getReadRepository( craftTypeSettings ) - return craftTypeSettings.profileListbox.value - -def getReadProfileRepository(): - """Get the read profile repository.""" - return settings.getReadRepository( ProfileRepository() ) - -def updateProfileSaveListeners(): - """Call the save function of all the update profile save listeners.""" - for globalProfileSaveListener in euclidean.getListTableElements( settings.globalProfileSaveListenerListTable ): - globalProfileSaveListener.save() - cancelAll() - - -class AddProfile: - """A class to add a profile.""" - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - gridPosition.increment() - self.entry = settings.Tkinter.Entry( gridPosition.master ) - self.entry.bind('', self.addSelectionWithEvent ) - self.entry.grid( row = gridPosition.row, column = 1, columnspan = 3, sticky = settings.Tkinter.W ) - self.addButton = settings.Tkinter.Button( gridPosition.master, activebackground = 'black', activeforeground = 'white', text = 'Add Profile', command = self.addSelection ) - self.addButton.grid( row = gridPosition.row, column = 0 ) - - def addSelection(self): - """Add the selection of a listbox setting.""" - entryText = self.entry.get() - if entryText == '': - print('To add to the profiles, enter the material name.') - return - self.profileListboxSetting.listSetting.setValueToFolders() - if entryText in self.profileListboxSetting.listSetting.value: - print('There is already a profile by the name of %s, so no profile will be added.' % entryText ) - return - self.entry.delete( 0, settings.Tkinter.END ) - craftTypeProfileDirectory = archive.getProfilesPath( self.profileListboxSetting.listSetting.craftTypeName ) - destinationDirectory = os.path.join( craftTypeProfileDirectory, entryText ) - shutil.copytree( self.profileListboxSetting.getSelectedFolder(), destinationDirectory ) - self.profileListboxSetting.listSetting.setValueToFolders() - self.profileListboxSetting.value = entryText - self.profileListboxSetting.setStateToValue() - - def addSelectionWithEvent(self, event): - """Add the selection of a listbox setting, given an event.""" - self.addSelection() - - def getFromProfileListboxSettingRepository( self, profileListboxSetting, repository ): - """Initialize.""" - self.profileListboxSetting = profileListboxSetting - self.repository = repository - repository.displayEntities.append(self) - return self - - -class DeleteProfile( AddProfile ): - """A class to delete the selection of a listbox profile.""" - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - gridPosition.increment() - self.deleteButton = settings.Tkinter.Button( gridPosition.master, activebackground = 'black', activeforeground = 'white', text = "Delete Profile", command = self.deleteSelection ) - self.deleteButton.grid( row = gridPosition.row, column = 0 ) - - def deleteSelection(self): - """Delete the selection of a listbox setting.""" - DeleteProfileDialog( self.profileListboxSetting, settings.Tkinter.Tk() ) - - -class DeleteProfileDialog: - """A dialog to delete a profile.""" - def __init__(self, profileListboxSetting, root): - """Display a delete dialog.""" - self.profileListboxSetting = profileListboxSetting - self.root = root - root.title('Delete Warning') - rowIndex = 0 - self.label = settings.Tkinter.Label(self.root, text = 'Do you want to delete the profile?') - self.label.grid(row = rowIndex, column = 0, columnspan = 3, sticky = settings.Tkinter.W) - rowIndex += 1 - columnIndex = 1 - deleteButton = settings.Tkinter.Button(root, activebackground = 'black', activeforeground = 'red', command = self.delete, fg = 'red', text = 'Delete') - deleteButton.grid(row = rowIndex, column = columnIndex) - columnIndex += 1 - noButton = settings.Tkinter.Button(root, activebackground = 'black', activeforeground = 'darkgreen', command = self.no, fg = 'darkgreen', text = 'Do Nothing') - noButton.grid(row = rowIndex, column = columnIndex) - - def delete(self): - """Delete the selection of a listbox setting.""" - self.profileListboxSetting.setToDisplay() - self.profileListboxSetting.listSetting.setValueToFolders() - if self.profileListboxSetting.value not in self.profileListboxSetting.listSetting.value: - return - lastSelectionIndex = 0 - currentSelectionTuple = self.profileListboxSetting.listbox.curselection() - if len(currentSelectionTuple) > 0: - lastSelectionIndex = int(currentSelectionTuple[0]) - else: - print('No profile is selected, so no profile will be deleted.') - return - craftTypeName = self.profileListboxSetting.listSetting.craftTypeName - settings.deleteDirectory(archive.getProfilesPath(craftTypeName), self.profileListboxSetting.value) - settings.deleteDirectory(settings.getProfilesDirectoryInAboveDirectory(craftTypeName), self.profileListboxSetting.value) - self.profileListboxSetting.listSetting.setValueToFolders() - if len(self.profileListboxSetting.listSetting.value) < 1: - defaultSettingsDirectory = archive.getProfilesPath(os.path.join(craftTypeName, self.profileListboxSetting.defaultValue)) - archive.makeDirectory(defaultSettingsDirectory) - self.profileListboxSetting.listSetting.setValueToFolders() - lastSelectionIndex = min(lastSelectionIndex, len(self.profileListboxSetting.listSetting.value) - 1) - self.profileListboxSetting.value = self.profileListboxSetting.listSetting.value[lastSelectionIndex] - self.profileListboxSetting.setStateToValue() - self.no() - - def no(self): - """The dialog was closed.""" - self.root.destroy() - - -class ProfileList: - """A class to list the profiles.""" - def getFromName( self, name, repository ): - """Initialize.""" - self.craftTypeName = repository.lowerName - self.name = name - self.repository = repository - self.setValueToFolders() - return self - - def setValueToFolders(self): - """Set the value to the folders in the profiles directories.""" - self.value = settings.getFolders( archive.getProfilesPath( self.craftTypeName ) ) - defaultFolders = settings.getFolders( settings.getProfilesDirectoryInAboveDirectory( self.craftTypeName ) ) - for defaultFolder in defaultFolders: - if defaultFolder not in self.value: - self.value.append( defaultFolder ) - self.value.sort() - - -class ProfileListboxSetting( settings.StringSetting ): - """A class to handle the profile listbox.""" - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" -#http://www.pythonware.com/library/tkinter/introduction/x5453-patterns.htm - self.root = gridPosition.master - gridPosition.increment() - from fabmetheus_utilities.hidden_scrollbar import HiddenScrollbar - scrollbar = HiddenScrollbar( gridPosition.master ) - self.listbox = settings.Tkinter.Listbox( gridPosition.master, selectmode = settings.Tkinter.SINGLE, yscrollcommand = scrollbar.set ) - self.listbox.bind('', self.buttonReleaseOne ) - gridPosition.master.bind('', self.focusIn ) - scrollbar.config( command = self.listbox.yview ) - self.listbox.grid( row = gridPosition.row, column = 0, sticky = settings.Tkinter.N + settings.Tkinter.S ) - scrollbar.grid( row = gridPosition.row, column = 1, sticky = settings.Tkinter.N + settings.Tkinter.S ) - self.setStateToValue() - self.repository.saveListenerTable['updateProfileSaveListeners'] = updateProfileSaveListeners - - def buttonReleaseOne(self, event): - """Button one released.""" - self.setValueToIndex( self.listbox.nearest(event.y) ) - - def focusIn(self, event): - """The root has gained focus.""" - settings.getReadRepository(self.repository) - self.setStateToValue() - - def getFromListSetting( self, listSetting, name, repository, value ): - """Initialize.""" - self.getFromValueOnly( name, repository, value ) - self.listSetting = listSetting - repository.displayEntities.append(self) - repository.preferences.append(self) - return self - - def getSelectedFolder(self): - """Get the selected folder.""" - settingProfileSubfolder = settings.getSubfolderWithBasename( self.value, archive.getProfilesPath( self.listSetting.craftTypeName ) ) - if settingProfileSubfolder is not None: - return settingProfileSubfolder - toolProfileSubfolder = settings.getSubfolderWithBasename( self.value, settings.getProfilesDirectoryInAboveDirectory( self.listSetting.craftTypeName ) ) - return toolProfileSubfolder - - def setStateToValue(self): - """Set the listbox items to the list setting.""" - self.listbox.delete( 0, settings.Tkinter.END ) - for item in self.listSetting.value: - self.listbox.insert( settings.Tkinter.END, item ) - if self.value == item: - self.listbox.select_set( settings.Tkinter.END ) - - def setToDisplay(self): - """Set the selection value to the listbox selection.""" - currentSelectionTuple = self.listbox.curselection() - if len( currentSelectionTuple ) > 0: - self.setValueToIndex( int( currentSelectionTuple[0] ) ) - - def setValueToIndex( self, index ): - """Set the selection value to the index.""" - valueString = self.listbox.get( index ) - self.setValueToString( valueString ) - - def setValueToString( self, valueString ): - """Set the value to the value string.""" - self.value = valueString - if self.getSelectedFolder() is None: - self.value = self.defaultValue - if self.getSelectedFolder() is None: - if len( self.listSetting.value ) > 0: - self.value = self.listSetting.value[0] - - -class ProfilePluginRadioButtonsSaveListener: - """A class to update the profile radio buttons.""" - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - euclidean.addElementToListDictionaryIfNotThere( self, self.repository.repositoryDialog, settings.globalProfileSaveListenerListTable ) - - def getFromRadioPlugins( self, radioPlugins, repository ): - """Initialize.""" - self.name = 'ProfilePluginRadioButtonsSaveListener' - self.radioPlugins = radioPlugins - self.repository = repository - repository.displayEntities.append(self) - return self - - def save(self): - """Profile has been saved and profile radio plugins should be updated.""" - craftTypeName = getCraftTypeName() - for radioPlugin in self.radioPlugins: - if radioPlugin.name == craftTypeName: - if radioPlugin.setSelect(): - self.repository.pluginFrame.update() - return - - -class ProfileRepository: - """A class to handle the profile entities.""" - def __init__(self): - """Set the default entities, execute title & repository fileName.""" - settings.addListsToRepository('skeinforge_application.skeinforge_utilities.skeinforge_profile.html', self) - importantFileNames = ['extrusion'] - self.craftRadios = settings.getRadioPluginsAddPluginFrame( getPluginsDirectoryPath(), importantFileNames, getPluginFileNames(), self ) - ProfilePluginRadioButtonsSaveListener().getFromRadioPlugins( self.craftRadios, self ) - for craftRadio in self.craftRadios: - craftRadio.updateFunction = self.updateRelay - directoryName = archive.getProfilesPath() - archive.makeDirectory(directoryName) - self.windowPosition.value = '0+200' - self.pluginFrame = None - self.windowPosition = None - - def updateRelay(self): - """Update the plugin frame then the ProfileSaveListeners.""" - self.pluginFrame.update() - updateProfileSaveListeners() - - -class ProfileSelectionMenuRadio: - """A class to display a profile selection menu radio button.""" - def addToDialog( self, gridPosition ): - """Add this to the dialog.""" - self.activate = False - self.menuButtonDisplay.setToNameAddToDialog( self.valueName, gridPosition ) - self.menuButtonDisplay.menu.add_radiobutton( label = self.valueName, command = self.clickRadio, value = self.valueName, variable = self.menuButtonDisplay.radioVar ) - self.menuLength = self.menuButtonDisplay.menu.index( settings.Tkinter.END ) - if self.value: - self.menuButtonDisplay.radioVar.set( self.valueName ) - self.menuButtonDisplay.menu.invoke( self.menuLength ) - euclidean.addElementToListDictionaryIfNotThere( self.repository, self.repository.repositoryDialog, settings.globalProfileSaveListenerListTable ) - self.activate = True - - def clickRadio(self): - """Workaround for Tkinter bug, invoke and set the value when clicked.""" - if not self.activate: - return - settings.saveAll() - self.menuButtonDisplay.radioVar.set( self.valueName ) - pluginModule = getCraftTypePluginModule() - profilePluginSettings = settings.getReadRepository( pluginModule.getNewRepository() ) - profilePluginSettings.profileListbox.value = self.name - settings.writeSettings( profilePluginSettings ) - updateProfileSaveListeners() - - def getFromMenuButtonDisplay( self, menuButtonDisplay, name, repository, value ): - """Initialize.""" - self.setToMenuButtonDisplay( menuButtonDisplay, name, repository, value ) - self.valueName = name.replace('_', ' ') - return self - - def setToMenuButtonDisplay( self, menuButtonDisplay, name, repository, value ): - """Initialize.""" - self.menuButtonDisplay = menuButtonDisplay - self.menuButtonDisplay.menuRadios.append(self) - self.name = name - self.repository = repository - self.value = value - repository.displayEntities.append(self) - - -class ProfileTypeMenuRadio( ProfileSelectionMenuRadio ): - """A class to display a profile type menu radio button.""" - def clickRadio(self): - """Workaround for Tkinter bug, invoke and set the value when clicked.""" - if not self.activate: - return - settings.saveAll() - self.menuButtonDisplay.radioVar.set( self.valueName ) - profileSettings = getReadProfileRepository() - plugins = profileSettings.craftRadios - for plugin in plugins: - plugin.value = ( plugin.name == self.name ) - settings.writeSettings( profileSettings ) - updateProfileSaveListeners() - - def getFromMenuButtonDisplay( self, menuButtonDisplay, name, repository, value ): - """Initialize.""" - self.setToMenuButtonDisplay( menuButtonDisplay, name, repository, value ) - self.valueName = settings.getEachWordCapitalized( name ) - return self diff --git a/skeinforge/skeinforge_application/terminal.sh b/skeinforge/skeinforge_application/terminal.sh deleted file mode 100644 index 3826bf6..0000000 --- a/skeinforge/skeinforge_application/terminal.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# -# Script to open the bash terminal in this directory. -# -# Usage: set the executable property to true if it isn't already. Then double click the file. -# -echo 'Directory listing:' -echo '' -ls -echo '' -echo 'To run a python script (.py) listed above, try typing something like:' -echo 'python filename' -echo '' -echo 'For example, in the skeinforge_application directory you could run skeinforge by typing:' -echo 'python skeinforge.py' -echo '' -echo 'To skeinforge the test.stl file from the command line, in the skeinforge_application directory you could type:' -echo 'python skeinforge.py test.stl' -echo '' -echo 'To run a script in a subdirectory, append the directory path. For example, to run skeinforge from the top directory you could type:' -echo 'python skeinforge_application/skeinforge.py' -echo '' -bash - diff --git a/skeinforge/skeinforge_application/test.stl b/skeinforge/skeinforge_application/test.stl deleted file mode 100644 index f372a18..0000000 --- a/skeinforge/skeinforge_application/test.stl +++ /dev/null @@ -1,2886 +0,0 @@ -solid "Screw_Holder_Bottom"; Produced by Art of Illusion 2.4, Fri Oct 16 16:42:04 PDT 2009 -facet normal 0 -0.831469612304 0.555570233017 - outer loop - vertex 54.002309837942 24.804173569059 0.110046151702 - vertex 48.011309837942 24.804173569059 0.110046151702 - vertex 54.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 24.730643081307 0 - vertex 14.883210818105 25.830303993361 0 - vertex 15.262563132924 25.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 60 23 0 - vertex 54.002309837942 24.730643081307 0 - vertex 60 40 0 - endloop -endfacet -facet normal 0 0.831469612301 0.555570233022 - outer loop - vertex 54.002309837942 15.269356918694 0 - vertex 48.011309837942 15.269356918694 0 - vertex 54.002309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.464705848856 10 0 - vertex 15.830303993361 11.883210818105 0 - vertex 16.5 11.75 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 30 0 - vertex 43.737436867076 27.737436867076 0 - vertex 43.169696006639 28.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 43.169696006639 15.116789181895 0 - vertex 42.5 15.25 0 - vertex 41.422110817733 17 0 - endloop -endfacet -facet normal 0 -0.831469612304 0.555570233017 - outer loop - vertex 48.011309837942 24.730643081307 0 - vertex 54.002309837942 24.730643081307 0 - vertex 48.011309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 30 0 - vertex 43.169696006639 28.116789181895 0 - vertex 42.5 28.25 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 60 40 0 - vertex 52 30 0 - vertex 52 40 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.883210818105 14.169696006639 0 - vertex 14.75 13.5 0 - vertex 12.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.883210818105 27.169696006639 0 - vertex 14.042553191489 30 0 - vertex 15.262563132924 27.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.464705848856 10 0 - vertex 16.5 11.75 0 - vertex 17.169696006639 11.883210818105 0 - endloop -endfacet -facet normal 0 0.831469612301 0.555570233022 - outer loop - vertex 48.011309837942 15.195826430941 0.110046151702 - vertex 54.002309837942 15.195826430941 0.110046151702 - vertex 48.011309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.042553191489 30 0 - vertex 17.169696006639 28.116789181895 0 - vertex 16.5 28.25 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 15.269356918694 0 - vertex 14.75 13.5 0 - vertex 14.883210818105 12.830303993361 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 54.002309837942 17 0 - vertex 60 17 0 - vertex 54.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 10 0 - vertex 42.5 11.75 0 - vertex 43.169696006639 11.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 15.269356918694 0 - vertex 15.262563132924 14.737436867076 0 - vertex 14.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 10 0 - vertex 14.464705848856 10 0 - vertex 42.5 11.75 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.042553191489 30 0 - vertex 15.830303993361 28.116789181895 0 - vertex 15.262563132924 27.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.464705848856 10 0 - vertex 15.262563132924 12.262563132924 0 - vertex 15.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.042553191489 30 0 - vertex 16.5 28.25 0 - vertex 15.830303993361 28.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 54.002309837942 24.730643081307 0 - vertex 60 23 0 - vertex 54.002309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 23 0 - vertex 16.5 24.75 0 - vertex 17.169696006639 24.883210818105 0 - endloop -endfacet -facet normal 0 0.831469612301 0.555570233022 - outer loop - vertex 6.011309837942 15.269356918694 0 - vertex 6.011309837942 15.195826430941 0.110046151702 - vertex 12.002309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.75 26.5 0 - vertex 12.002309837942 24.730643081307 0 - vertex 14.883210818105 27.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 30 0 - vertex 60 40 0 - vertex 54.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.422110817733 17 0 - vertex 48.011309837942 17 0 - vertex 43.169696006639 15.116789181895 0 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 14.75 13.5 0 - vertex 14.883210818105 12.830303993361 0.77775 - vertex 14.883210818105 12.830303993361 0 - endloop -endfacet -facet normal -0 -0 -1 - outer loop - vertex 6.011309837942 17 0 - vertex 6.011309837942 15.269356918694 0 - vertex 0 17 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.422110817733 17 0 - vertex 41.830303993361 15.116789181895 0 - vertex 41.262563132924 14.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.169696006639 11.883210818105 0 - vertex 17.737436867076 12.262563132924 0 - vertex 41.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 6.011309837942 15.269356918694 0 - vertex 0 10 0 - vertex 0 17 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.883210818105 25.830303993361 0 - vertex 12.002309837942 24.730643081307 0 - vertex 14.75 26.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 24.730643081307 0 - vertex 52 30 0 - vertex 54.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 17 0 - vertex 43.737436867076 14.737436867076 0 - vertex 43.169696006639 15.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 42.5 15.25 0 - vertex 41.830303993361 15.116789181895 0 - vertex 41.422110817733 17 0 - endloop -endfacet -facet normal -0 -0 -1 - outer loop - vertex 12.002309837942 15.269356918694 0 - vertex 14.883210818105 12.830303993361 0 - vertex 6.011309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 0 23 0 - vertex 0 30 0 - vertex 6.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0.831469612301 0.555570233022 - outer loop - vertex 12.002309837942 15.269356918694 0 - vertex 6.011309837942 15.269356918694 0 - vertex 12.002309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 54.002309837942 15.269356918694 0 - vertex 60 17 0 - vertex 52 10 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 6.011309837942 23 0 - vertex 0 23 0 - vertex 6.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 14.169696006639 0 - vertex 48.011309837942 15.269356918694 0 - vertex 44.25 13.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.116789181895 27.169696006639 0 - vertex 41.262563132924 25.262563132924 0 - vertex 18.25 26.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.116789181895 25.830303993361 0 - vertex 18.25 26.5 0 - vertex 41.830303993361 24.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.737436867076 14.737436867076 0 - vertex 41.262563132924 14.737436867076 0 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal -0 -0 -1 - outer loop - vertex 41.262563132924 25.262563132924 0 - vertex 41.830303993361 24.883210818105 0 - vertex 18.25 26.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.737436867076 25.262563132924 0 - vertex 18.116789181895 25.830303993361 0 - vertex 41.830303993361 24.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.737436867076 12.262563132924 0 - vertex 18.116789181895 12.830303993361 0 - vertex 40.883210818105 12.830303993361 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.737436867076 12.262563132924 0 - vertex 41.262563132924 12.262563132924 0 - vertex 41.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.262563132924 27.737436867076 0 - vertex 17.169696006639 28.116789181895 0 - vertex 41.830303993361 28.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 42.5 11.75 0 - vertex 14.464705848856 10 0 - vertex 17.169696006639 11.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.25 26.5 0 - vertex 44.116789181895 27.169696006639 0 - vertex 48.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 40.883210818105 12.830303993361 0 - vertex 41.262563132924 12.262563132924 0 - vertex 17.737436867076 12.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.169696006639 24.883210818105 0 - vertex 17.737436867076 25.262563132924 0 - vertex 41.830303993361 24.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 12.830303993361 0 - vertex 44.25 13.5 0 - vertex 48.011309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.116789181895 12.830303993361 0 - vertex 40.75 13.5 0 - vertex 40.883210818105 12.830303993361 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.25 13.5 0 - vertex 18.116789181895 14.169696006639 0 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.262563132924 14.737436867076 0 - vertex 17.737436867076 14.737436867076 0 - vertex 17.169696006639 15.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.116789181895 14.169696006639 0 - vertex 17.737436867076 14.737436867076 0 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 25.830303993361 0 - vertex 44.25 26.5 0 - vertex 48.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 14.883210818105 14.169696006639 0.77775 - vertex 14.75 13.5 0.77775 - vertex 14.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 14.75 13.5 0.77775 - vertex 14.75 13.5 0 - vertex 14.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 41.830303993361 28.116789181895 0 - vertex 42.5 28.25 0.77775 - vertex 41.830303993361 28.116789181895 0.77775 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 15.830303993361 24.883210818105 0.77775 - vertex 15.830303993361 24.883210818105 0 - vertex 15.262563132924 25.262563132924 0 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 16.5 28.25 0 - vertex 17.169696006639 28.116789181895 0.77775 - vertex 16.5 28.25 0.77775 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 43.169696006639 24.883210818105 0 - vertex 42.5 24.75 0.77775 - vertex 43.169696006639 24.883210818105 0.77775 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 16.5 28.25 0.77775 - vertex 15.830303993361 28.116789181895 0.77775 - vertex 16.5 28.25 0 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 15.830303993361 28.116789181895 0.77775 - vertex 15.830303993361 28.116789181895 0 - vertex 16.5 28.25 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 0 23 0 - vertex 6.011309837942 23 0.77775 - vertex 0 23 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 60 0 0.77775 - vertex 52 10 0.77775 - vertex 52 0 0.77775 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 40.883210818105 27.169696006639 0 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 40.75 26.5 0 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 17.169696006639 24.883210818105 0.77775 - vertex 17.169696006639 24.883210818105 0 - vertex 16.5 24.75 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 52 0 0 - vertex 52 0 0.77775 - vertex 52 10 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 34.416922535211 17 0.77775 - vertex 40.883210818105 12.830303993361 0.77775 - vertex 40.75 13.5 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 12.002309837942 24.936988122232 0.77775 - vertex 12.002309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 42.5 24.75 0 - vertex 41.830303993361 24.883210818105 0.77775 - vertex 42.5 24.75 0.77775 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 60 0 0 - vertex 60 0 0.77775 - vertex 52 0 0 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 15.830303993361 28.116789181895 0.77775 - vertex 15.262563132924 27.737436867076 0.77775 - vertex 15.830303993361 28.116789181895 0 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 15.262563132924 27.737436867076 0.77775 - vertex 15.262563132924 27.737436867076 0 - vertex 15.830303993361 28.116789181895 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 6.011309837942 17 0.77775 - vertex 6.011309837942 17 0 - vertex 0 17 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 17 0 - vertex 48.011309837942 17 0.77775 - vertex 48.011309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 0 - outer loop - vertex 18.25 26.5 0 - vertex 18.25 26.5 0.77775 - vertex 18.116789181895 27.169696006639 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.262563132924 14.737436867076 0.77775 - vertex 15.830303993361 15.116789181895 0.77775 - vertex 15.455907969142 17 0.77775 - endloop -endfacet -facet normal 0 0.980785280403 0.195090322015 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 54.002309837942 15.195826430941 0.110046151702 - vertex 48.011309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 0 - outer loop - vertex 44.25 26.5 0 - vertex 44.25 26.5 0.77775 - vertex 44.116789181895 27.169696006639 0.77775 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 52 10 0 - vertex 15.306548743796 10 0.77775 - vertex 14.464705848856 10 0 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 40.75 26.5 0.77775 - vertex 40.883210818105 25.830303993361 0 - vertex 40.75 26.5 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 15.063011877768 0.77775 - vertex 48.011309837942 15.195826430941 0.110046151702 - vertex 48.011309837942 15.269356918694 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 44.116789181895 27.169696006639 0.77775 - vertex 43.737436867076 27.737436867076 0.77775 - vertex 44.116789181895 27.169696006639 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 43.737436867076 27.737436867076 0.77775 - vertex 43.737436867076 27.737436867076 0 - vertex 44.116789181895 27.169696006639 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 52 10 0 - vertex 52 10 0.77775 - vertex 15.306548743796 10 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 23 0.77775 - vertex 6.011309837942 23 0 - vertex 6.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 34.416922535211 17 0.77775 - vertex 40.883210818105 14.169696006639 0.77775 - vertex 41.262563132924 14.737436867076 0.77775 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 14.75 26.5 0 - vertex 14.883210818105 25.830303993361 0.77775 - vertex 14.883210818105 25.830303993361 0 - endloop -endfacet -facet normal 0 -0.980785280403 0.195090322015 - outer loop - vertex 6.011309837942 24.936988122232 0.77775 - vertex 6.011309837942 24.804173569059 0.110046151702 - vertex 12.002309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 18.116789181895 14.169696006639 0.77775 - vertex 17.737436867076 14.737436867076 0.77775 - vertex 18.116789181895 14.169696006639 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 17.737436867076 14.737436867076 0.77775 - vertex 17.737436867076 14.737436867076 0 - vertex 18.116789181895 14.169696006639 0 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 42.5 15.25 0.77775 - vertex 41.830303993361 15.116789181895 0.77775 - vertex 42.5 15.25 0 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 41.830303993361 15.116789181895 0.77775 - vertex 41.830303993361 15.116789181895 0 - vertex 42.5 15.25 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 15.262563132924 14.737436867076 0.77775 - vertex 14.883210818105 14.169696006639 0.77775 - vertex 15.262563132924 14.737436867076 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 14.883210818105 14.169696006639 0.77775 - vertex 14.883210818105 14.169696006639 0 - vertex 15.262563132924 14.737436867076 0 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 0 - outer loop - vertex 43.169696006639 15.116789181895 0 - vertex 43.737436867076 14.737436867076 0.77775 - vertex 43.169696006639 15.116789181895 0.77775 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 14.75 13.5 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - vertex 14.75 13.5 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 41.262563132924 14.737436867076 0.77775 - vertex 40.883210818105 14.169696006639 0.77775 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 42.5 11.75 0.77775 - vertex 43.169696006639 11.883210818105 0.77775 - vertex 43.169696006639 11.883210818105 0 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 -0 - outer loop - vertex 17.169696006639 15.116789181895 0.77775 - vertex 17.169696006639 15.116789181895 0 - vertex 17.737436867076 14.737436867076 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 12.002309837942 24.730643081307 0 - vertex 12.002309837942 23 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 6.011309837942 23 0.77775 - vertex 0 23 0 - vertex 6.011309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 25.830303993361 0 - vertex 48.011309837942 23 0 - vertex 43.737436867076 25.262563132924 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 15.195826430941 0.110046151702 - vertex 12.002309837942 17 0.77775 - vertex 12.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 0 10 0 - vertex 6.011309837942 15.269356918694 0 - vertex 14.883210818105 12.830303993361 0 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 -0 - outer loop - vertex 17.169696006639 28.116789181895 0.77775 - vertex 16.5 28.25 0 - vertex 17.169696006639 28.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 24.730643081307 0 - vertex 44.116789181895 27.169696006639 0 - vertex 43.737436867076 27.737436867076 0 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 44.25 26.5 0.77775 - vertex 44.25 26.5 0 - vertex 44.116789181895 25.830303993361 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 40.75 26.5 0.77775 - vertex 37.474084379442 23 0.77775 - vertex 40.883210818105 25.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 34.416922535211 17 0.77775 - vertex 40.75 13.5 0.77775 - vertex 40.883210818105 14.169696006639 0.77775 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 17.169696006639 11.883210818105 0.77775 - vertex 17.169696006639 11.883210818105 0 - vertex 16.5 11.75 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 43.737436867076 27.737436867076 0.77775 - vertex 52 30 0.77775 - vertex 41.866228156844 30 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 12.002309837942 15.063011877768 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - vertex 14.75 13.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 48.011309837942 15.063011877768 0.77775 - vertex 52 10 0.77775 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 41.830303993361 24.883210818105 0.77775 - vertex 42.5 24.75 0 - vertex 41.830303993361 24.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 6.011309837942 24.730643081307 0 - vertex 14.883210818105 27.169696006639 0 - vertex 12.002309837942 24.730643081307 0 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 -0 - outer loop - vertex 43.737436867076 14.737436867076 0.77775 - vertex 43.169696006639 15.116789181895 0 - vertex 43.737436867076 14.737436867076 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 43.737436867076 27.737436867076 0.77775 - vertex 41.866228156844 30 0.77775 - vertex 43.169696006639 28.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 34.416922535211 17 0.77775 - vertex 41.830303993361 15.116789181895 0.77775 - vertex 42.5 15.25 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 16.5 11.75 0.77775 - vertex 15.830303993361 11.883210818105 0.77775 - vertex 15.306548743796 10 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 0 23 0.77775 - vertex 0 30 0 - vertex 0 23 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 0 30 0 - vertex 0 23 0.77775 - vertex 0 30 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 52 10 0 - vertex 52 0 0.77775 - vertex 52 10 0.77775 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 17.169696006639 11.883210818105 0 - vertex 17.169696006639 11.883210818105 0.77775 - vertex 17.737436867076 12.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 43.169696006639 28.116789181895 0.77775 - vertex 41.866228156844 30 0.77775 - vertex 42.5 28.25 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 14.042553191489 30 0 - vertex 41.866228156844 30 0.77775 - vertex 52 30 0 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 41.830303993361 11.883210818105 0.77775 - vertex 42.5 11.75 0 - vertex 41.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 15.262563132924 12.262563132924 0.77775 - vertex 15.830303993361 11.883210818105 0 - vertex 15.262563132924 12.262563132924 0 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 40.883210818105 25.830303993361 0 - vertex 40.75 26.5 0.77775 - vertex 40.883210818105 25.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.116789181895 27.169696006639 0 - vertex 40.883210818105 25.830303993361 0 - vertex 41.262563132924 25.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 42.5 28.25 0 - vertex 17.169696006639 28.116789181895 0 - vertex 14.042553191489 30 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 15.262563132924 27.737436867076 0.77775 - vertex 15.830303993361 28.116789181895 0.77775 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 14.883210818105 25.830303993361 0.77775 - vertex 15.262563132924 25.262563132924 0.77775 - vertex 14.883210818105 25.830303993361 0 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 15.262563132924 25.262563132924 0.77775 - vertex 15.262563132924 25.262563132924 0 - vertex 14.883210818105 25.830303993361 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 24.804173569059 0.110046151702 - vertex 48.011309837942 23 0.77775 - vertex 48.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 24.730643081307 0 - vertex 43.737436867076 27.737436867076 0 - vertex 52 30 0 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 18.116789181895 25.830303993361 0 - vertex 18.116789181895 25.830303993361 0.77775 - vertex 18.25 26.5 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 15.195826430941 0.110046151702 - vertex 54.002309837942 15.063011877768 0.77775 - vertex 54.002309837942 17 0.77775 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 41.830303993361 15.116789181895 0 - vertex 41.830303993361 15.116789181895 0.77775 - vertex 41.262563132924 14.737436867076 0.77775 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 -0 - outer loop - vertex 43.737436867076 27.737436867076 0.77775 - vertex 43.169696006639 28.116789181895 0.77775 - vertex 43.737436867076 27.737436867076 0 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 -0 - outer loop - vertex 43.169696006639 28.116789181895 0.77775 - vertex 43.169696006639 28.116789181895 0 - vertex 43.737436867076 27.737436867076 0 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 41.830303993361 11.883210818105 0.77775 - vertex 42.5 11.75 0.77775 - vertex 42.5 11.75 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 15.830303993361 24.883210818105 0.77775 - vertex 15.262563132924 25.262563132924 0.77775 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 41.262563132924 14.737436867076 0.77775 - vertex 41.262563132924 14.737436867076 0 - vertex 41.830303993361 15.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 60 17 0 - vertex 60 0 0 - vertex 52 0 0 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 15.262563132924 25.262563132924 0 - vertex 15.262563132924 25.262563132924 0.77775 - vertex 15.830303993361 24.883210818105 0.77775 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 12.002309837942 23 0 - vertex 17.379510917074 23 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 24.936988122232 0.77775 - vertex 6.011309837942 23 0.77775 - vertex 6.011309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.169696006639 11.883210818105 0 - vertex 41.830303993361 11.883210818105 0 - vertex 42.5 11.75 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 42.5 28.25 0 - vertex 14.042553191489 30 0 - vertex 52 30 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 17 0.77775 - vertex 43.169696006639 15.116789181895 0.77775 - vertex 43.737436867076 14.737436867076 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 15.269356918694 0 - vertex 6.011309837942 17 0.77775 - vertex 6.011309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 -0 - outer loop - vertex 18.116789181895 27.169696006639 0.77775 - vertex 18.116789181895 27.169696006639 0 - vertex 18.25 26.5 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 40.75 26.5 0 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 40.75 26.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 0 30 0.77775 - vertex 14.883210818105 27.169696006639 0.77775 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 42.5 11.75 0.77775 - vertex 43.169696006639 11.883210818105 0 - vertex 42.5 11.75 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 15.830303993361 28.116789181895 0.77775 - vertex 16.5 28.25 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 52 30 0.77775 - vertex 52 30 0 - vertex 41.866228156844 30 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 60 17 0 - vertex 52 0 0 - vertex 52 10 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 0 - outer loop - vertex 44.116789181895 14.169696006639 0.77775 - vertex 43.737436867076 14.737436867076 0.77775 - vertex 43.737436867076 14.737436867076 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 41.866228156844 30 0.77775 - vertex 14.042553191489 30 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.169696006639 11.883210818105 0.77775 - vertex 15.306548743796 10 0.77775 - vertex 17.737436867076 12.262563132924 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 15.269356918694 0 - vertex 12.002309837942 17 0.77775 - vertex 12.002309837942 17 0 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 17.169696006639 24.883210818105 0.77775 - vertex 16.5 24.75 0 - vertex 16.5 24.75 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 23 0.77775 - vertex 43.169696006639 24.883210818105 0.77775 - vertex 42.5 24.75 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 6.011309837942 17 0.77775 - vertex 0 17 0 - vertex 0 17 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 16.5 28.25 0.77775 - vertex 17.169696006639 28.116789181895 0.77775 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 18.116789181895 25.830303993361 0.77775 - vertex 17.737436867076 25.262563132924 0 - vertex 17.737436867076 25.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 16.5 24.75 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 17.169696006639 24.883210818105 0.77775 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 -0 - outer loop - vertex 44.116789181895 27.169696006639 0.77775 - vertex 44.116789181895 27.169696006639 0 - vertex 44.25 26.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 40.75 13.5 0 - vertex 18.25 13.5 0 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 25.830303993361 0 - vertex 48.011309837942 24.730643081307 0 - vertex 48.011309837942 23 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 0 10 0.77775 - vertex 0 10 0 - vertex 14.464705848856 10 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.306548743796 10 0.77775 - vertex 15.830303993361 11.883210818105 0.77775 - vertex 15.262563132924 12.262563132924 0.77775 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 43.169696006639 28.116789181895 0 - vertex 43.169696006639 28.116789181895 0.77775 - vertex 42.5 28.25 0.77775 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 17.169696006639 11.883210818105 0.77775 - vertex 16.5 11.75 0 - vertex 16.5 11.75 0.77775 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 0 - outer loop - vertex 18.25 13.5 0.77775 - vertex 18.116789181895 14.169696006639 0.77775 - vertex 18.116789181895 14.169696006639 0 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 17.169696006639 24.883210818105 0.77775 - vertex 17.737436867076 25.262563132924 0 - vertex 17.169696006639 24.883210818105 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 0 10 0.77775 - vertex 14.464705848856 10 0 - vertex 15.306548743796 10 0.77775 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 0 - outer loop - vertex 17.169696006639 15.116789181895 0.77775 - vertex 17.737436867076 14.737436867076 0 - vertex 17.737436867076 14.737436867076 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 23 0.77775 - vertex 48.011309837942 24.804173569059 0.110046151702 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.830303993361 28.116789181895 0.77775 - vertex 41.866228156844 30 0.77775 - vertex 41.262563132924 27.737436867076 0.77775 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 16.5 11.75 0.77775 - vertex 15.830303993361 11.883210818105 0 - vertex 15.830303993361 11.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.75 26.5 0.77775 - vertex 12.002309837942 24.936988122232 0.77775 - vertex 14.883210818105 25.830303993361 0.77775 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 44.116789181895 14.169696006639 0.77775 - vertex 43.737436867076 14.737436867076 0 - vertex 44.116789181895 14.169696006639 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 12.002309837942 24.804173569059 0.110046151702 - vertex 12.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 60 17 0.77775 - vertex 54.002309837942 17 0.77775 - endloop -endfacet -facet normal 0 0.980785280403 0.195090322015 - outer loop - vertex 6.011309837942 15.063011877768 0.77775 - vertex 12.002309837942 15.195826430941 0.110046151702 - vertex 6.011309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 15.830303993361 24.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.830303993361 24.883210818105 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 16.5 24.75 0.77775 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 18.25 26.5 0.77775 - vertex 18.25 26.5 0 - vertex 18.116789181895 25.830303993361 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.262563132924 25.262563132924 0.77775 - vertex 37.474084379442 23 0.77775 - vertex 41.830303993361 24.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 14.883210818105 27.169696006639 0.77775 - vertex 15.262563132924 27.737436867076 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 14.737436867076 0.77775 - vertex 15.455907969142 17 0.77775 - vertex 17.169696006639 15.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 14.737436867076 0.77775 - vertex 34.416922535211 17 0.77775 - vertex 15.455907969142 17 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.306548743796 10 0.77775 - vertex 15.262563132924 12.262563132924 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 17.169696006639 24.883210818105 0.77775 - vertex 17.737436867076 25.262563132924 0.77775 - vertex 17.737436867076 25.262563132924 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 16.5 15.25 0.77775 - vertex 15.455907969142 17 0.77775 - vertex 15.830303993361 15.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.830303993361 28.116789181895 0.77775 - vertex 42.5 28.25 0.77775 - vertex 41.866228156844 30 0.77775 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 18.116789181895 12.830303993361 0.77775 - vertex 18.25 13.5 0.77775 - vertex 18.25 13.5 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 60 17 0.77775 - vertex 60 17 0 - vertex 54.002309837942 17 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 15.455907969142 17 0.77775 - vertex 12.002309837942 17 0 - vertex 12.002309837942 17 0.77775 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 43.169696006639 11.883210818105 0 - vertex 43.737436867076 12.262563132924 0.77775 - vertex 43.737436867076 12.262563132924 0 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 43.169696006639 11.883210818105 0 - vertex 43.169696006639 11.883210818105 0.77775 - vertex 43.737436867076 12.262563132924 0.77775 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 -0 - outer loop - vertex 18.25 13.5 0.77775 - vertex 18.116789181895 14.169696006639 0 - vertex 18.25 13.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 42.5 28.25 0 - vertex 41.830303993361 28.116789181895 0 - vertex 17.169696006639 28.116789181895 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 23 0.77775 - vertex 48.011309837942 23 0 - vertex 48.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.169696006639 15.116789181895 0.77775 - vertex 15.455907969142 17 0.77775 - vertex 16.5 15.25 0.77775 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 17.737436867076 12.262563132924 0.77775 - vertex 17.737436867076 12.262563132924 0 - vertex 17.169696006639 11.883210818105 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 52 40 0.77775 - vertex 60 23 0.77775 - vertex 60 40 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 40.75 13.5 0 - vertex 18.116789181895 12.830303993361 0 - vertex 18.25 13.5 0 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 43.169696006639 28.116789181895 0 - vertex 42.5 28.25 0.77775 - vertex 42.5 28.25 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 23 0 - vertex 12.002309837942 23 0 - vertex 42.5 24.75 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 23 0.77775 - vertex 60 23 0.77775 - vertex 54.002309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 23 0.77775 - vertex 6.011309837942 24.730643081307 0 - vertex 6.011309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 17.169696006639 15.116789181895 0 - vertex 16.5 15.25 0.77775 - vertex 16.5 15.25 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 17 0.77775 - vertex 6.011309837942 15.063011877768 0.77775 - vertex 6.011309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 60 17 0.77775 - vertex 60 0 0 - vertex 60 17 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 60 0 0.77775 - vertex 60 0 0 - vertex 60 17 0.77775 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 15.262563132924 12.262563132924 0.77775 - vertex 15.830303993361 11.883210818105 0.77775 - vertex 15.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 52 10 0.77775 - vertex 44.116789181895 12.830303993361 0.77775 - vertex 43.737436867076 12.262563132924 0.77775 - endloop -endfacet -facet normal 0 0.980785280403 0.195090322015 - outer loop - vertex 6.011309837942 15.063011877768 0.77775 - vertex 12.002309837942 15.063011877768 0.77775 - vertex 12.002309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.169696006639 24.883210818105 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 17.737436867076 25.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 52 10 0.77775 - vertex 43.737436867076 12.262563132924 0.77775 - vertex 43.169696006639 11.883210818105 0.77775 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 42.5 28.25 0.77775 - vertex 41.830303993361 28.116789181895 0 - vertex 42.5 28.25 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 15.269356918694 0 - vertex 6.011309837942 17 0 - vertex 6.011309837942 17 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 40.883210818105 25.830303993361 0.77775 - vertex 37.474084379442 23 0.77775 - vertex 41.262563132924 25.262563132924 0.77775 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 18.116789181895 12.830303993361 0.77775 - vertex 18.25 13.5 0 - vertex 18.116789181895 12.830303993361 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 25.262563132924 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 18.116789181895 25.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 34.416922535211 17 0.77775 - vertex 41.262563132924 14.737436867076 0.77775 - vertex 41.830303993361 15.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 0 30 0.77775 - vertex 6.011309837942 24.936988122232 0.77775 - vertex 12.002309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 25.830303993361 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 37.474084379442 23 0.77775 - endloop -endfacet -facet normal 0 -0.980785280403 0.195090322015 - outer loop - vertex 6.011309837942 24.936988122232 0.77775 - vertex 12.002309837942 24.804173569059 0.110046151702 - vertex 12.002309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 52 10 0.77775 - vertex 43.169696006639 11.883210818105 0.77775 - vertex 42.5 11.75 0.77775 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 41.262563132924 14.737436867076 0.77775 - vertex 40.883210818105 14.169696006639 0 - vertex 41.262563132924 14.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 23 0 - vertex 43.169696006639 24.883210818105 0 - vertex 43.737436867076 25.262563132924 0 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 44.25 26.5 0.77775 - vertex 44.116789181895 25.830303993361 0 - vertex 44.116789181895 25.830303993361 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 60 17 0.77775 - vertex 54.002309837942 17 0 - vertex 54.002309837942 17 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 23 0 - vertex 42.5 24.75 0 - vertex 43.169696006639 24.883210818105 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 43.737436867076 27.737436867076 0.77775 - vertex 44.116789181895 27.169696006639 0.77775 - vertex 52 30 0.77775 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 18.116789181895 25.830303993361 0.77775 - vertex 18.116789181895 25.830303993361 0 - vertex 17.737436867076 25.262563132924 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 15.195826430941 0.110046151702 - vertex 54.002309837942 17 0.77775 - vertex 54.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 14.883210818105 27.169696006639 0.77775 - vertex 14.75 26.5 0 - vertex 14.883210818105 27.169696006639 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 52 0 0.77775 - vertex 52 0 0 - vertex 60 0 0.77775 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 14.883210818105 27.169696006639 0.77775 - vertex 14.75 26.5 0.77775 - vertex 14.75 26.5 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 15.269356918694 0 - vertex 54.002309837942 17 0.77775 - vertex 54.002309837942 17 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 16.5 11.75 0.77775 - vertex 15.306548743796 10 0.77775 - vertex 17.169696006639 11.883210818105 0.77775 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 17.169696006639 15.116789181895 0 - vertex 17.169696006639 15.116789181895 0.77775 - vertex 16.5 15.25 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 15.195826430941 0.110046151702 - vertex 12.002309837942 15.063011877768 0.77775 - vertex 12.002309837942 17 0.77775 - endloop -endfacet -facet normal 0 0.980785280403 0.195090322015 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 48.011309837942 15.195826430941 0.110046151702 - vertex 48.011309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 16.5 11.75 0.77775 - vertex 16.5 11.75 0 - vertex 15.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 15.063011877768 0.77775 - vertex 48.011309837942 15.269356918694 0 - vertex 48.011309837942 17 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 24.936988122232 0.77775 - vertex 52 30 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 42.5 24.75 0.77775 - vertex 43.169696006639 24.883210818105 0 - vertex 42.5 24.75 0 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 14.75 26.5 0 - vertex 14.75 26.5 0.77775 - vertex 14.883210818105 25.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 14.169696006639 0 - vertex 43.737436867076 14.737436867076 0 - vertex 48.011309837942 17 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 14.169696006639 0 - vertex 48.011309837942 17 0 - vertex 48.011309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.169696006639 24.883210818105 0 - vertex 41.830303993361 24.883210818105 0 - vertex 42.5 24.75 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.169696006639 24.883210818105 0 - vertex 42.5 24.75 0 - vertex 12.002309837942 23 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 52 40 0 - vertex 52 40 0.77775 - vertex 60 40 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 52 40 0 - vertex 60 40 0.77775 - vertex 60 40 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 0 - outer loop - vertex 18.116789181895 27.169696006639 0.77775 - vertex 17.737436867076 27.737436867076 0.77775 - vertex 17.737436867076 27.737436867076 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 18.116789181895 27.169696006639 0.77775 - vertex 17.737436867076 27.737436867076 0 - vertex 18.116789181895 27.169696006639 0 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 15.830303993361 24.883210818105 0 - vertex 15.830303993361 24.883210818105 0.77775 - vertex 16.5 24.75 0.77775 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 15.830303993361 24.883210818105 0 - vertex 16.5 24.75 0.77775 - vertex 16.5 24.75 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 12.002309837942 24.936988122232 0.77775 - vertex 12.002309837942 23 0.77775 - vertex 15.262563132924 25.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 12.002309837942 24.936988122232 0.77775 - vertex 15.262563132924 25.262563132924 0.77775 - vertex 14.883210818105 25.830303993361 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 60 40 0.77775 - vertex 60 23 0.77775 - vertex 60 23 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 60 40 0.77775 - vertex 60 23 0 - vertex 60 40 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 15.262563132924 27.737436867076 0 - vertex 15.262563132924 27.737436867076 0.77775 - vertex 14.883210818105 27.169696006639 0.77775 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 15.262563132924 27.737436867076 0 - vertex 14.883210818105 27.169696006639 0.77775 - vertex 14.883210818105 27.169696006639 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 37.474084379442 23 0.77775 - vertex 48.011309837942 23 0.77775 - vertex 42.5 24.75 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 37.474084379442 23 0.77775 - vertex 42.5 24.75 0.77775 - vertex 41.830303993361 24.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.262563132924 14.737436867076 0 - vertex 12.002309837942 17 0 - vertex 41.422110817733 17 0 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 43.169696006639 15.116789181895 0.77775 - vertex 42.5 15.25 0.77775 - vertex 42.5 15.25 0 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 -0 - outer loop - vertex 43.169696006639 15.116789181895 0.77775 - vertex 42.5 15.25 0 - vertex 43.169696006639 15.116789181895 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 52 10 0.77775 - vertex 60 0 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 60 0 0.77775 - vertex 60 17 0.77775 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 40.75 13.5 0.77775 - vertex 40.883210818105 12.830303993361 0.77775 - vertex 40.883210818105 12.830303993361 0 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 40.75 13.5 0.77775 - vertex 40.883210818105 12.830303993361 0 - vertex 40.75 13.5 0 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 0 - outer loop - vertex 17.737436867076 27.737436867076 0 - vertex 17.737436867076 27.737436867076 0.77775 - vertex 17.169696006639 28.116789181895 0.77775 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 0 - outer loop - vertex 17.737436867076 27.737436867076 0 - vertex 17.169696006639 28.116789181895 0.77775 - vertex 17.169696006639 28.116789181895 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.883210818105 27.169696006639 0.77775 - vertex 0 30 0.77775 - vertex 12.002309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.883210818105 27.169696006639 0.77775 - vertex 12.002309837942 24.936988122232 0.77775 - vertex 14.75 26.5 0.77775 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 43.737436867076 12.262563132924 0.77775 - vertex 44.116789181895 12.830303993361 0.77775 - vertex 44.116789181895 12.830303993361 0 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 43.737436867076 12.262563132924 0.77775 - vertex 44.116789181895 12.830303993361 0 - vertex 43.737436867076 12.262563132924 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 48.011309837942 23 0 - vertex 48.011309837942 23 0.77775 - vertex 37.474084379442 23 0.77775 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 16.5 15.25 0.77775 - vertex 15.830303993361 15.116789181895 0.77775 - vertex 15.830303993361 15.116789181895 0 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 16.5 15.25 0.77775 - vertex 15.830303993361 15.116789181895 0 - vertex 16.5 15.25 0 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 40.883210818105 12.830303993361 0.77775 - vertex 41.262563132924 12.262563132924 0.77775 - vertex 41.262563132924 12.262563132924 0 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 40.883210818105 12.830303993361 0.77775 - vertex 41.262563132924 12.262563132924 0 - vertex 40.883210818105 12.830303993361 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 17 0 - vertex 16.5 15.25 0 - vertex 15.830303993361 15.116789181895 0 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 43.737436867076 25.262563132924 0 - vertex 43.737436867076 25.262563132924 0.77775 - vertex 44.116789181895 25.830303993361 0.77775 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 43.737436867076 25.262563132924 0 - vertex 44.116789181895 25.830303993361 0.77775 - vertex 44.116789181895 25.830303993361 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 40.883210818105 14.169696006639 0.77775 - vertex 40.75 13.5 0.77775 - vertex 40.75 13.5 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 40.883210818105 14.169696006639 0.77775 - vertex 40.75 13.5 0 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 60 23 0 - vertex 60 23 0.77775 - vertex 54.002309837942 23 0.77775 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 60 23 0 - vertex 54.002309837942 23 0.77775 - vertex 54.002309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 0 30 0 - vertex 14.042553191489 30 0 - vertex 14.883210818105 27.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 0 30 0 - vertex 14.883210818105 27.169696006639 0 - vertex 6.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 41.262563132924 25.262563132924 0 - vertex 41.262563132924 25.262563132924 0.77775 - vertex 41.830303993361 24.883210818105 0.77775 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 41.262563132924 25.262563132924 0 - vertex 41.830303993361 24.883210818105 0.77775 - vertex 41.830303993361 24.883210818105 0 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 41.830303993361 28.116789181895 0.77775 - vertex 41.262563132924 27.737436867076 0.77775 - vertex 41.262563132924 27.737436867076 0 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 41.830303993361 28.116789181895 0.77775 - vertex 41.262563132924 27.737436867076 0 - vertex 41.830303993361 28.116789181895 0 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 43.169696006639 24.883210818105 0.77775 - vertex 43.737436867076 25.262563132924 0.77775 - vertex 43.737436867076 25.262563132924 0 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 43.169696006639 24.883210818105 0.77775 - vertex 43.737436867076 25.262563132924 0 - vertex 43.169696006639 24.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 10 0 - vertex 43.169696006639 11.883210818105 0 - vertex 43.737436867076 12.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 10 0 - vertex 43.737436867076 12.262563132924 0 - vertex 54.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 24.936988122232 0.77775 - vertex 60 23 0.77775 - vertex 52 40 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 24.936988122232 0.77775 - vertex 52 40 0.77775 - vertex 52 30 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 15.455907969142 17 0.77775 - vertex 34.416922535211 17 0.77775 - vertex 41.422110817733 17 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 15.455907969142 17 0.77775 - vertex 41.422110817733 17 0 - vertex 12.002309837942 17 0 - endloop -endfacet -facet normal 0 -0.831469612304 0.555570233017 - outer loop - vertex 12.002309837942 24.804173569059 0.110046151702 - vertex 6.011309837942 24.804173569059 0.110046151702 - vertex 6.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 -0.831469612304 0.555570233017 - outer loop - vertex 12.002309837942 24.804173569059 0.110046151702 - vertex 6.011309837942 24.730643081307 0 - vertex 12.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.262563132924 14.737436867076 0.77775 - vertex 15.455907969142 17 0.77775 - vertex 12.002309837942 17 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.262563132924 14.737436867076 0.77775 - vertex 12.002309837942 17 0.77775 - vertex 14.883210818105 14.169696006639 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 44.116789181895 25.830303993361 0.77775 - vertex 43.737436867076 25.262563132924 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 0 17 0.77775 - vertex 0 10 0.77775 - vertex 6.011309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 0 17 0.77775 - vertex 6.011309837942 15.063011877768 0.77775 - vertex 6.011309837942 17 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 17 0.77775 - vertex 34.416922535211 17 0.77775 - vertex 42.5 15.25 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 17 0.77775 - vertex 42.5 15.25 0.77775 - vertex 43.169696006639 15.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.883210818105 14.169696006639 0.77775 - vertex 12.002309837942 17 0.77775 - vertex 12.002309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.883210818105 14.169696006639 0.77775 - vertex 12.002309837942 15.063011877768 0.77775 - vertex 14.75 13.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 6.011309837942 24.936988122232 0.77775 - vertex 0 30 0.77775 - vertex 0 23 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 6.011309837942 24.936988122232 0.77775 - vertex 0 23 0.77775 - vertex 6.011309837942 23 0.77775 - endloop -endfacet -facet normal -0 -0 -1 - outer loop - vertex 40.75 26.5 0 - vertex 40.883210818105 25.830303993361 0 - vertex 18.116789181895 27.169696006639 0 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 0 - outer loop - vertex 44.25 13.5 0.77775 - vertex 44.116789181895 14.169696006639 0.77775 - vertex 44.116789181895 14.169696006639 0 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 -0 - outer loop - vertex 44.25 13.5 0.77775 - vertex 44.116789181895 14.169696006639 0 - vertex 44.25 13.5 0 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 17.737436867076 12.262563132924 0 - vertex 17.737436867076 12.262563132924 0.77775 - vertex 18.116789181895 12.830303993361 0.77775 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 17.737436867076 12.262563132924 0 - vertex 18.116789181895 12.830303993361 0.77775 - vertex 18.116789181895 12.830303993361 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 0 10 0.77775 - vertex 15.306548743796 10 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - endloop -endfacet -facet normal 0 -0.980785280403 0.195090322015 - outer loop - vertex 54.002309837942 24.804173569059 0.110046151702 - vertex 54.002309837942 24.936988122232 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 -0.980785280403 0.195090322015 - outer loop - vertex 54.002309837942 24.804173569059 0.110046151702 - vertex 48.011309837942 24.936988122232 0.77775 - vertex 48.011309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 14.883210818105 12.830303993361 0 - vertex 14.883210818105 12.830303993361 0.77775 - vertex 15.262563132924 12.262563132924 0.77775 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 14.883210818105 12.830303993361 0 - vertex 15.262563132924 12.262563132924 0.77775 - vertex 15.262563132924 12.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 54.002309837942 15.269356918694 0 - vertex 43.737436867076 12.262563132924 0 - vertex 44.116789181895 12.830303993361 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 54.002309837942 15.269356918694 0 - vertex 44.116789181895 12.830303993361 0 - vertex 48.011309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 0 30 0 - vertex 0 30 0.77775 - vertex 14.607403236621 30 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 0 30 0 - vertex 14.607403236621 30 0.77775 - vertex 14.042553191489 30 0 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 41.262563132924 12.262563132924 0 - vertex 41.262563132924 12.262563132924 0.77775 - vertex 41.830303993361 11.883210818105 0.77775 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 41.262563132924 12.262563132924 0 - vertex 41.830303993361 11.883210818105 0.77775 - vertex 41.830303993361 11.883210818105 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 0 10 0 - vertex 0 10 0.77775 - vertex 0 17 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 0 10 0 - vertex 0 17 0.77775 - vertex 0 17 0 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 44.116789181895 12.830303993361 0.77775 - vertex 44.25 13.5 0.77775 - vertex 44.25 13.5 0 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 44.116789181895 12.830303993361 0.77775 - vertex 44.25 13.5 0 - vertex 44.116789181895 12.830303993361 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 41.422110817733 17 0 - vertex 34.416922535211 17 0.77775 - vertex 48.011309837942 17 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 41.422110817733 17 0 - vertex 48.011309837942 17 0.77775 - vertex 48.011309837942 17 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 52 30 0.77775 - vertex 52 40 0.77775 - vertex 52 40 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 52 30 0.77775 - vertex 52 40 0 - vertex 52 30 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 15.830303993361 24.883210818105 0 - vertex 16.5 24.75 0 - vertex 12.002309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.262563132924 27.737436867076 0 - vertex 40.883210818105 27.169696006639 0 - vertex 17.737436867076 27.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.262563132924 27.737436867076 0 - vertex 17.737436867076 27.737436867076 0 - vertex 17.169696006639 28.116789181895 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 6.011309837942 15.063011877768 0.77775 - vertex 0 10 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 6.011309837942 15.063011877768 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - vertex 12.002309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 17 0.77775 - vertex 43.737436867076 14.737436867076 0.77775 - vertex 44.116789181895 14.169696006639 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 17 0.77775 - vertex 44.116789181895 14.169696006639 0.77775 - vertex 48.011309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 15.262563132924 25.262563132924 0 - vertex 15.830303993361 24.883210818105 0 - vertex 12.002309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 15.262563132924 25.262563132924 0 - vertex 12.002309837942 23 0 - vertex 12.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 44.25 26.5 0.77775 - vertex 44.116789181895 25.830303993361 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 40.883210818105 27.169696006639 0 - vertex 40.75 26.5 0 - vertex 18.116789181895 27.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 40.883210818105 27.169696006639 0 - vertex 18.116789181895 27.169696006639 0 - vertex 17.737436867076 27.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 17 0 - vertex 41.262563132924 14.737436867076 0 - vertex 17.169696006639 15.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 17 0 - vertex 17.169696006639 15.116789181895 0 - vertex 16.5 15.25 0 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 15.830303993361 15.116789181895 0 - vertex 15.830303993361 15.116789181895 0.77775 - vertex 15.262563132924 14.737436867076 0.77775 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 15.830303993361 15.116789181895 0 - vertex 15.262563132924 14.737436867076 0.77775 - vertex 15.262563132924 14.737436867076 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 41.262563132924 27.737436867076 0.77775 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 40.883210818105 27.169696006639 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 41.262563132924 27.737436867076 0.77775 - vertex 40.883210818105 27.169696006639 0 - vertex 41.262563132924 27.737436867076 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 48.011309837942 23 0 - vertex 37.474084379442 23 0.77775 - vertex 17.379510917074 23 0.77775 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 48.011309837942 23 0 - vertex 17.379510917074 23 0.77775 - vertex 12.002309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 17 0 - vertex 15.830303993361 15.116789181895 0 - vertex 15.262563132924 14.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 17 0 - vertex 15.262563132924 14.737436867076 0 - vertex 12.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 40.883210818105 25.830303993361 0 - vertex 40.883210818105 25.830303993361 0.77775 - vertex 41.262563132924 25.262563132924 0.77775 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 40.883210818105 25.830303993361 0 - vertex 41.262563132924 25.262563132924 0.77775 - vertex 41.262563132924 25.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.883210818105 12.830303993361 0 - vertex 15.262563132924 12.262563132924 0 - vertex 14.464705848856 10 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.883210818105 12.830303993361 0 - vertex 14.464705848856 10 0 - vertex 0 10 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 27.737436867076 0.77775 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 41.262563132924 27.737436867076 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.262563132924 27.737436867076 0.77775 - vertex 17.169696006639 28.116789181895 0.77775 - vertex 17.737436867076 27.737436867076 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 23 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - vertex 43.737436867076 25.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 23 0.77775 - vertex 43.737436867076 25.262563132924 0.77775 - vertex 43.169696006639 24.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 15.063011877768 0.77775 - vertex 44.116789181895 14.169696006639 0.77775 - vertex 44.25 13.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 44.116789181895 27.169696006639 0.77775 - vertex 44.25 26.5 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 44.116789181895 27.169696006639 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - vertex 52 30 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 27.169696006639 0.77775 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 17.737436867076 27.737436867076 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 23 0.77775 - vertex 54.002309837942 24.936988122232 0.77775 - vertex 54.002309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.262563132924 27.737436867076 0.77775 - vertex 41.866228156844 30 0.77775 - vertex 14.607403236621 30 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.262563132924 27.737436867076 0.77775 - vertex 14.607403236621 30 0.77775 - vertex 17.169696006639 28.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 15.063011877768 0.77775 - vertex 44.25 13.5 0.77775 - vertex 44.116789181895 12.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 15.063011877768 0.77775 - vertex 44.116789181895 12.830303993361 0.77775 - vertex 52 10 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 14.169696006639 0.77775 - vertex 18.25 13.5 0.77775 - vertex 41.262563132924 12.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.25 26.5 0.77775 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 18.116789181895 27.169696006639 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 24.730643081307 0 - vertex 54.002309837942 23 0 - vertex 54.002309837942 23 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 24.730643081307 0 - vertex 54.002309837942 23 0.77775 - vertex 54.002309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.830303993361 11.883210818105 0.77775 - vertex 41.262563132924 12.262563132924 0.77775 - vertex 18.25 13.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.830303993361 11.883210818105 0.77775 - vertex 18.25 13.5 0.77775 - vertex 18.116789181895 12.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 12.830303993361 0.77775 - vertex 17.737436867076 12.262563132924 0.77775 - vertex 42.5 11.75 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 12.830303993361 0.77775 - vertex 42.5 11.75 0.77775 - vertex 41.830303993361 11.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 12.262563132924 0.77775 - vertex 15.306548743796 10 0.77775 - vertex 52 10 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 12.262563132924 0.77775 - vertex 52 10 0.77775 - vertex 42.5 11.75 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 40.883210818105 12.830303993361 0.77775 - vertex 18.116789181895 14.169696006639 0.77775 - vertex 41.262563132924 12.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.25 26.5 0.77775 - vertex 40.75 26.5 0.77775 - vertex 40.883210818105 27.169696006639 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 25.830303993361 0.77775 - vertex 37.474084379442 23 0.77775 - vertex 40.75 26.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 25.830303993361 0.77775 - vertex 40.75 26.5 0.77775 - vertex 18.25 26.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 40.883210818105 12.830303993361 0.77775 - vertex 34.416922535211 17 0.77775 - vertex 17.737436867076 14.737436867076 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 40.883210818105 12.830303993361 0.77775 - vertex 17.737436867076 14.737436867076 0.77775 - vertex 18.116789181895 14.169696006639 0.77775 - endloop -endfacet -endsolid diff --git a/skeinforge/terminal.sh b/skeinforge/terminal.sh deleted file mode 100644 index bc7d246..0000000 --- a/skeinforge/terminal.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -# -# Script to open the bash terminal in this directory. -# -# Usage: set the executable property to true if it isn't already. Then double click the file. -# -echo 'Directory listing:' -echo '' -ls -echo '' -echo 'To run a python script (.py) listed above, try typing something like:' -echo 'python filename' -echo '' -echo 'For example, in the skeinforge directory you could run skeinforge.py by typing:' -echo 'python skeinforge.py' -echo '' -echo 'To skeinforge the test.stl file from the command line, in the skeinforge directory you could type:' -echo 'python skeinforge.py test.stl' -echo '' -bash - diff --git a/skeinforge/test.stl b/skeinforge/test.stl deleted file mode 100644 index f372a18..0000000 --- a/skeinforge/test.stl +++ /dev/null @@ -1,2886 +0,0 @@ -solid "Screw_Holder_Bottom"; Produced by Art of Illusion 2.4, Fri Oct 16 16:42:04 PDT 2009 -facet normal 0 -0.831469612304 0.555570233017 - outer loop - vertex 54.002309837942 24.804173569059 0.110046151702 - vertex 48.011309837942 24.804173569059 0.110046151702 - vertex 54.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 24.730643081307 0 - vertex 14.883210818105 25.830303993361 0 - vertex 15.262563132924 25.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 60 23 0 - vertex 54.002309837942 24.730643081307 0 - vertex 60 40 0 - endloop -endfacet -facet normal 0 0.831469612301 0.555570233022 - outer loop - vertex 54.002309837942 15.269356918694 0 - vertex 48.011309837942 15.269356918694 0 - vertex 54.002309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.464705848856 10 0 - vertex 15.830303993361 11.883210818105 0 - vertex 16.5 11.75 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 30 0 - vertex 43.737436867076 27.737436867076 0 - vertex 43.169696006639 28.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 43.169696006639 15.116789181895 0 - vertex 42.5 15.25 0 - vertex 41.422110817733 17 0 - endloop -endfacet -facet normal 0 -0.831469612304 0.555570233017 - outer loop - vertex 48.011309837942 24.730643081307 0 - vertex 54.002309837942 24.730643081307 0 - vertex 48.011309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 30 0 - vertex 43.169696006639 28.116789181895 0 - vertex 42.5 28.25 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 60 40 0 - vertex 52 30 0 - vertex 52 40 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.883210818105 14.169696006639 0 - vertex 14.75 13.5 0 - vertex 12.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.883210818105 27.169696006639 0 - vertex 14.042553191489 30 0 - vertex 15.262563132924 27.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.464705848856 10 0 - vertex 16.5 11.75 0 - vertex 17.169696006639 11.883210818105 0 - endloop -endfacet -facet normal 0 0.831469612301 0.555570233022 - outer loop - vertex 48.011309837942 15.195826430941 0.110046151702 - vertex 54.002309837942 15.195826430941 0.110046151702 - vertex 48.011309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.042553191489 30 0 - vertex 17.169696006639 28.116789181895 0 - vertex 16.5 28.25 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 15.269356918694 0 - vertex 14.75 13.5 0 - vertex 14.883210818105 12.830303993361 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 54.002309837942 17 0 - vertex 60 17 0 - vertex 54.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 10 0 - vertex 42.5 11.75 0 - vertex 43.169696006639 11.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 15.269356918694 0 - vertex 15.262563132924 14.737436867076 0 - vertex 14.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 10 0 - vertex 14.464705848856 10 0 - vertex 42.5 11.75 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.042553191489 30 0 - vertex 15.830303993361 28.116789181895 0 - vertex 15.262563132924 27.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.464705848856 10 0 - vertex 15.262563132924 12.262563132924 0 - vertex 15.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.042553191489 30 0 - vertex 16.5 28.25 0 - vertex 15.830303993361 28.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 54.002309837942 24.730643081307 0 - vertex 60 23 0 - vertex 54.002309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 23 0 - vertex 16.5 24.75 0 - vertex 17.169696006639 24.883210818105 0 - endloop -endfacet -facet normal 0 0.831469612301 0.555570233022 - outer loop - vertex 6.011309837942 15.269356918694 0 - vertex 6.011309837942 15.195826430941 0.110046151702 - vertex 12.002309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.75 26.5 0 - vertex 12.002309837942 24.730643081307 0 - vertex 14.883210818105 27.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 30 0 - vertex 60 40 0 - vertex 54.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.422110817733 17 0 - vertex 48.011309837942 17 0 - vertex 43.169696006639 15.116789181895 0 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 14.75 13.5 0 - vertex 14.883210818105 12.830303993361 0.77775 - vertex 14.883210818105 12.830303993361 0 - endloop -endfacet -facet normal -0 -0 -1 - outer loop - vertex 6.011309837942 17 0 - vertex 6.011309837942 15.269356918694 0 - vertex 0 17 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.422110817733 17 0 - vertex 41.830303993361 15.116789181895 0 - vertex 41.262563132924 14.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.169696006639 11.883210818105 0 - vertex 17.737436867076 12.262563132924 0 - vertex 41.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 6.011309837942 15.269356918694 0 - vertex 0 10 0 - vertex 0 17 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.883210818105 25.830303993361 0 - vertex 12.002309837942 24.730643081307 0 - vertex 14.75 26.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 24.730643081307 0 - vertex 52 30 0 - vertex 54.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 17 0 - vertex 43.737436867076 14.737436867076 0 - vertex 43.169696006639 15.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 42.5 15.25 0 - vertex 41.830303993361 15.116789181895 0 - vertex 41.422110817733 17 0 - endloop -endfacet -facet normal -0 -0 -1 - outer loop - vertex 12.002309837942 15.269356918694 0 - vertex 14.883210818105 12.830303993361 0 - vertex 6.011309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 0 23 0 - vertex 0 30 0 - vertex 6.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0.831469612301 0.555570233022 - outer loop - vertex 12.002309837942 15.269356918694 0 - vertex 6.011309837942 15.269356918694 0 - vertex 12.002309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 54.002309837942 15.269356918694 0 - vertex 60 17 0 - vertex 52 10 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 6.011309837942 23 0 - vertex 0 23 0 - vertex 6.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 14.169696006639 0 - vertex 48.011309837942 15.269356918694 0 - vertex 44.25 13.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.116789181895 27.169696006639 0 - vertex 41.262563132924 25.262563132924 0 - vertex 18.25 26.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.116789181895 25.830303993361 0 - vertex 18.25 26.5 0 - vertex 41.830303993361 24.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.737436867076 14.737436867076 0 - vertex 41.262563132924 14.737436867076 0 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal -0 -0 -1 - outer loop - vertex 41.262563132924 25.262563132924 0 - vertex 41.830303993361 24.883210818105 0 - vertex 18.25 26.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.737436867076 25.262563132924 0 - vertex 18.116789181895 25.830303993361 0 - vertex 41.830303993361 24.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.737436867076 12.262563132924 0 - vertex 18.116789181895 12.830303993361 0 - vertex 40.883210818105 12.830303993361 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.737436867076 12.262563132924 0 - vertex 41.262563132924 12.262563132924 0 - vertex 41.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.262563132924 27.737436867076 0 - vertex 17.169696006639 28.116789181895 0 - vertex 41.830303993361 28.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 42.5 11.75 0 - vertex 14.464705848856 10 0 - vertex 17.169696006639 11.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.25 26.5 0 - vertex 44.116789181895 27.169696006639 0 - vertex 48.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 40.883210818105 12.830303993361 0 - vertex 41.262563132924 12.262563132924 0 - vertex 17.737436867076 12.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.169696006639 24.883210818105 0 - vertex 17.737436867076 25.262563132924 0 - vertex 41.830303993361 24.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 12.830303993361 0 - vertex 44.25 13.5 0 - vertex 48.011309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.116789181895 12.830303993361 0 - vertex 40.75 13.5 0 - vertex 40.883210818105 12.830303993361 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.25 13.5 0 - vertex 18.116789181895 14.169696006639 0 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.262563132924 14.737436867076 0 - vertex 17.737436867076 14.737436867076 0 - vertex 17.169696006639 15.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.116789181895 14.169696006639 0 - vertex 17.737436867076 14.737436867076 0 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 25.830303993361 0 - vertex 44.25 26.5 0 - vertex 48.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 14.883210818105 14.169696006639 0.77775 - vertex 14.75 13.5 0.77775 - vertex 14.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 14.75 13.5 0.77775 - vertex 14.75 13.5 0 - vertex 14.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 41.830303993361 28.116789181895 0 - vertex 42.5 28.25 0.77775 - vertex 41.830303993361 28.116789181895 0.77775 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 15.830303993361 24.883210818105 0.77775 - vertex 15.830303993361 24.883210818105 0 - vertex 15.262563132924 25.262563132924 0 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 16.5 28.25 0 - vertex 17.169696006639 28.116789181895 0.77775 - vertex 16.5 28.25 0.77775 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 43.169696006639 24.883210818105 0 - vertex 42.5 24.75 0.77775 - vertex 43.169696006639 24.883210818105 0.77775 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 16.5 28.25 0.77775 - vertex 15.830303993361 28.116789181895 0.77775 - vertex 16.5 28.25 0 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 15.830303993361 28.116789181895 0.77775 - vertex 15.830303993361 28.116789181895 0 - vertex 16.5 28.25 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 0 23 0 - vertex 6.011309837942 23 0.77775 - vertex 0 23 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 60 0 0.77775 - vertex 52 10 0.77775 - vertex 52 0 0.77775 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 40.883210818105 27.169696006639 0 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 40.75 26.5 0 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 17.169696006639 24.883210818105 0.77775 - vertex 17.169696006639 24.883210818105 0 - vertex 16.5 24.75 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 52 0 0 - vertex 52 0 0.77775 - vertex 52 10 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 34.416922535211 17 0.77775 - vertex 40.883210818105 12.830303993361 0.77775 - vertex 40.75 13.5 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 12.002309837942 24.936988122232 0.77775 - vertex 12.002309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 42.5 24.75 0 - vertex 41.830303993361 24.883210818105 0.77775 - vertex 42.5 24.75 0.77775 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 60 0 0 - vertex 60 0 0.77775 - vertex 52 0 0 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 15.830303993361 28.116789181895 0.77775 - vertex 15.262563132924 27.737436867076 0.77775 - vertex 15.830303993361 28.116789181895 0 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 15.262563132924 27.737436867076 0.77775 - vertex 15.262563132924 27.737436867076 0 - vertex 15.830303993361 28.116789181895 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 6.011309837942 17 0.77775 - vertex 6.011309837942 17 0 - vertex 0 17 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 17 0 - vertex 48.011309837942 17 0.77775 - vertex 48.011309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 0 - outer loop - vertex 18.25 26.5 0 - vertex 18.25 26.5 0.77775 - vertex 18.116789181895 27.169696006639 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.262563132924 14.737436867076 0.77775 - vertex 15.830303993361 15.116789181895 0.77775 - vertex 15.455907969142 17 0.77775 - endloop -endfacet -facet normal 0 0.980785280403 0.195090322015 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 54.002309837942 15.195826430941 0.110046151702 - vertex 48.011309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 0 - outer loop - vertex 44.25 26.5 0 - vertex 44.25 26.5 0.77775 - vertex 44.116789181895 27.169696006639 0.77775 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 52 10 0 - vertex 15.306548743796 10 0.77775 - vertex 14.464705848856 10 0 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 40.75 26.5 0.77775 - vertex 40.883210818105 25.830303993361 0 - vertex 40.75 26.5 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 15.063011877768 0.77775 - vertex 48.011309837942 15.195826430941 0.110046151702 - vertex 48.011309837942 15.269356918694 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 44.116789181895 27.169696006639 0.77775 - vertex 43.737436867076 27.737436867076 0.77775 - vertex 44.116789181895 27.169696006639 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 43.737436867076 27.737436867076 0.77775 - vertex 43.737436867076 27.737436867076 0 - vertex 44.116789181895 27.169696006639 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 52 10 0 - vertex 52 10 0.77775 - vertex 15.306548743796 10 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 23 0.77775 - vertex 6.011309837942 23 0 - vertex 6.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 34.416922535211 17 0.77775 - vertex 40.883210818105 14.169696006639 0.77775 - vertex 41.262563132924 14.737436867076 0.77775 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 14.75 26.5 0 - vertex 14.883210818105 25.830303993361 0.77775 - vertex 14.883210818105 25.830303993361 0 - endloop -endfacet -facet normal 0 -0.980785280403 0.195090322015 - outer loop - vertex 6.011309837942 24.936988122232 0.77775 - vertex 6.011309837942 24.804173569059 0.110046151702 - vertex 12.002309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 18.116789181895 14.169696006639 0.77775 - vertex 17.737436867076 14.737436867076 0.77775 - vertex 18.116789181895 14.169696006639 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 17.737436867076 14.737436867076 0.77775 - vertex 17.737436867076 14.737436867076 0 - vertex 18.116789181895 14.169696006639 0 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 42.5 15.25 0.77775 - vertex 41.830303993361 15.116789181895 0.77775 - vertex 42.5 15.25 0 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 41.830303993361 15.116789181895 0.77775 - vertex 41.830303993361 15.116789181895 0 - vertex 42.5 15.25 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 15.262563132924 14.737436867076 0.77775 - vertex 14.883210818105 14.169696006639 0.77775 - vertex 15.262563132924 14.737436867076 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 14.883210818105 14.169696006639 0.77775 - vertex 14.883210818105 14.169696006639 0 - vertex 15.262563132924 14.737436867076 0 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 0 - outer loop - vertex 43.169696006639 15.116789181895 0 - vertex 43.737436867076 14.737436867076 0.77775 - vertex 43.169696006639 15.116789181895 0.77775 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 14.75 13.5 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - vertex 14.75 13.5 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 41.262563132924 14.737436867076 0.77775 - vertex 40.883210818105 14.169696006639 0.77775 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 42.5 11.75 0.77775 - vertex 43.169696006639 11.883210818105 0.77775 - vertex 43.169696006639 11.883210818105 0 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 -0 - outer loop - vertex 17.169696006639 15.116789181895 0.77775 - vertex 17.169696006639 15.116789181895 0 - vertex 17.737436867076 14.737436867076 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 12.002309837942 24.730643081307 0 - vertex 12.002309837942 23 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 6.011309837942 23 0.77775 - vertex 0 23 0 - vertex 6.011309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 25.830303993361 0 - vertex 48.011309837942 23 0 - vertex 43.737436867076 25.262563132924 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 15.195826430941 0.110046151702 - vertex 12.002309837942 17 0.77775 - vertex 12.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 0 10 0 - vertex 6.011309837942 15.269356918694 0 - vertex 14.883210818105 12.830303993361 0 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 -0 - outer loop - vertex 17.169696006639 28.116789181895 0.77775 - vertex 16.5 28.25 0 - vertex 17.169696006639 28.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 24.730643081307 0 - vertex 44.116789181895 27.169696006639 0 - vertex 43.737436867076 27.737436867076 0 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 44.25 26.5 0.77775 - vertex 44.25 26.5 0 - vertex 44.116789181895 25.830303993361 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 40.75 26.5 0.77775 - vertex 37.474084379442 23 0.77775 - vertex 40.883210818105 25.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 34.416922535211 17 0.77775 - vertex 40.75 13.5 0.77775 - vertex 40.883210818105 14.169696006639 0.77775 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 17.169696006639 11.883210818105 0.77775 - vertex 17.169696006639 11.883210818105 0 - vertex 16.5 11.75 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 43.737436867076 27.737436867076 0.77775 - vertex 52 30 0.77775 - vertex 41.866228156844 30 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 12.002309837942 15.063011877768 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - vertex 14.75 13.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 48.011309837942 15.063011877768 0.77775 - vertex 52 10 0.77775 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 41.830303993361 24.883210818105 0.77775 - vertex 42.5 24.75 0 - vertex 41.830303993361 24.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 6.011309837942 24.730643081307 0 - vertex 14.883210818105 27.169696006639 0 - vertex 12.002309837942 24.730643081307 0 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 -0 - outer loop - vertex 43.737436867076 14.737436867076 0.77775 - vertex 43.169696006639 15.116789181895 0 - vertex 43.737436867076 14.737436867076 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 43.737436867076 27.737436867076 0.77775 - vertex 41.866228156844 30 0.77775 - vertex 43.169696006639 28.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 34.416922535211 17 0.77775 - vertex 41.830303993361 15.116789181895 0.77775 - vertex 42.5 15.25 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 16.5 11.75 0.77775 - vertex 15.830303993361 11.883210818105 0.77775 - vertex 15.306548743796 10 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 0 23 0.77775 - vertex 0 30 0 - vertex 0 23 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 0 30 0 - vertex 0 23 0.77775 - vertex 0 30 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 52 10 0 - vertex 52 0 0.77775 - vertex 52 10 0.77775 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 17.169696006639 11.883210818105 0 - vertex 17.169696006639 11.883210818105 0.77775 - vertex 17.737436867076 12.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 43.169696006639 28.116789181895 0.77775 - vertex 41.866228156844 30 0.77775 - vertex 42.5 28.25 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 14.042553191489 30 0 - vertex 41.866228156844 30 0.77775 - vertex 52 30 0 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 41.830303993361 11.883210818105 0.77775 - vertex 42.5 11.75 0 - vertex 41.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 15.262563132924 12.262563132924 0.77775 - vertex 15.830303993361 11.883210818105 0 - vertex 15.262563132924 12.262563132924 0 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 40.883210818105 25.830303993361 0 - vertex 40.75 26.5 0.77775 - vertex 40.883210818105 25.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 18.116789181895 27.169696006639 0 - vertex 40.883210818105 25.830303993361 0 - vertex 41.262563132924 25.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 42.5 28.25 0 - vertex 17.169696006639 28.116789181895 0 - vertex 14.042553191489 30 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 15.262563132924 27.737436867076 0.77775 - vertex 15.830303993361 28.116789181895 0.77775 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 14.883210818105 25.830303993361 0.77775 - vertex 15.262563132924 25.262563132924 0.77775 - vertex 14.883210818105 25.830303993361 0 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 15.262563132924 25.262563132924 0.77775 - vertex 15.262563132924 25.262563132924 0 - vertex 14.883210818105 25.830303993361 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 24.804173569059 0.110046151702 - vertex 48.011309837942 23 0.77775 - vertex 48.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 24.730643081307 0 - vertex 43.737436867076 27.737436867076 0 - vertex 52 30 0 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 18.116789181895 25.830303993361 0 - vertex 18.116789181895 25.830303993361 0.77775 - vertex 18.25 26.5 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 15.195826430941 0.110046151702 - vertex 54.002309837942 15.063011877768 0.77775 - vertex 54.002309837942 17 0.77775 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 41.830303993361 15.116789181895 0 - vertex 41.830303993361 15.116789181895 0.77775 - vertex 41.262563132924 14.737436867076 0.77775 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 -0 - outer loop - vertex 43.737436867076 27.737436867076 0.77775 - vertex 43.169696006639 28.116789181895 0.77775 - vertex 43.737436867076 27.737436867076 0 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 -0 - outer loop - vertex 43.169696006639 28.116789181895 0.77775 - vertex 43.169696006639 28.116789181895 0 - vertex 43.737436867076 27.737436867076 0 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 41.830303993361 11.883210818105 0.77775 - vertex 42.5 11.75 0.77775 - vertex 42.5 11.75 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 15.830303993361 24.883210818105 0.77775 - vertex 15.262563132924 25.262563132924 0.77775 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 41.262563132924 14.737436867076 0.77775 - vertex 41.262563132924 14.737436867076 0 - vertex 41.830303993361 15.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 60 17 0 - vertex 60 0 0 - vertex 52 0 0 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 15.262563132924 25.262563132924 0 - vertex 15.262563132924 25.262563132924 0.77775 - vertex 15.830303993361 24.883210818105 0.77775 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 12.002309837942 23 0 - vertex 17.379510917074 23 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 24.936988122232 0.77775 - vertex 6.011309837942 23 0.77775 - vertex 6.011309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.169696006639 11.883210818105 0 - vertex 41.830303993361 11.883210818105 0 - vertex 42.5 11.75 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 42.5 28.25 0 - vertex 14.042553191489 30 0 - vertex 52 30 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 17 0.77775 - vertex 43.169696006639 15.116789181895 0.77775 - vertex 43.737436867076 14.737436867076 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 15.269356918694 0 - vertex 6.011309837942 17 0.77775 - vertex 6.011309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 -0 - outer loop - vertex 18.116789181895 27.169696006639 0.77775 - vertex 18.116789181895 27.169696006639 0 - vertex 18.25 26.5 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 40.75 26.5 0 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 40.75 26.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 0 30 0.77775 - vertex 14.883210818105 27.169696006639 0.77775 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 42.5 11.75 0.77775 - vertex 43.169696006639 11.883210818105 0 - vertex 42.5 11.75 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 15.830303993361 28.116789181895 0.77775 - vertex 16.5 28.25 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 52 30 0.77775 - vertex 52 30 0 - vertex 41.866228156844 30 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 60 17 0 - vertex 52 0 0 - vertex 52 10 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 0 - outer loop - vertex 44.116789181895 14.169696006639 0.77775 - vertex 43.737436867076 14.737436867076 0.77775 - vertex 43.737436867076 14.737436867076 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 41.866228156844 30 0.77775 - vertex 14.042553191489 30 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.169696006639 11.883210818105 0.77775 - vertex 15.306548743796 10 0.77775 - vertex 17.737436867076 12.262563132924 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 15.269356918694 0 - vertex 12.002309837942 17 0.77775 - vertex 12.002309837942 17 0 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 17.169696006639 24.883210818105 0.77775 - vertex 16.5 24.75 0 - vertex 16.5 24.75 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 23 0.77775 - vertex 43.169696006639 24.883210818105 0.77775 - vertex 42.5 24.75 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 6.011309837942 17 0.77775 - vertex 0 17 0 - vertex 0 17 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 16.5 28.25 0.77775 - vertex 17.169696006639 28.116789181895 0.77775 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 18.116789181895 25.830303993361 0.77775 - vertex 17.737436867076 25.262563132924 0 - vertex 17.737436867076 25.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 16.5 24.75 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 17.169696006639 24.883210818105 0.77775 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 -0 - outer loop - vertex 44.116789181895 27.169696006639 0.77775 - vertex 44.116789181895 27.169696006639 0 - vertex 44.25 26.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 40.75 13.5 0 - vertex 18.25 13.5 0 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 25.830303993361 0 - vertex 48.011309837942 24.730643081307 0 - vertex 48.011309837942 23 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 0 10 0.77775 - vertex 0 10 0 - vertex 14.464705848856 10 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.306548743796 10 0.77775 - vertex 15.830303993361 11.883210818105 0.77775 - vertex 15.262563132924 12.262563132924 0.77775 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 43.169696006639 28.116789181895 0 - vertex 43.169696006639 28.116789181895 0.77775 - vertex 42.5 28.25 0.77775 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 17.169696006639 11.883210818105 0.77775 - vertex 16.5 11.75 0 - vertex 16.5 11.75 0.77775 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 0 - outer loop - vertex 18.25 13.5 0.77775 - vertex 18.116789181895 14.169696006639 0.77775 - vertex 18.116789181895 14.169696006639 0 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 17.169696006639 24.883210818105 0.77775 - vertex 17.737436867076 25.262563132924 0 - vertex 17.169696006639 24.883210818105 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 0 10 0.77775 - vertex 14.464705848856 10 0 - vertex 15.306548743796 10 0.77775 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 0 - outer loop - vertex 17.169696006639 15.116789181895 0.77775 - vertex 17.737436867076 14.737436867076 0 - vertex 17.737436867076 14.737436867076 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 23 0.77775 - vertex 48.011309837942 24.804173569059 0.110046151702 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.830303993361 28.116789181895 0.77775 - vertex 41.866228156844 30 0.77775 - vertex 41.262563132924 27.737436867076 0.77775 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 16.5 11.75 0.77775 - vertex 15.830303993361 11.883210818105 0 - vertex 15.830303993361 11.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.75 26.5 0.77775 - vertex 12.002309837942 24.936988122232 0.77775 - vertex 14.883210818105 25.830303993361 0.77775 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 44.116789181895 14.169696006639 0.77775 - vertex 43.737436867076 14.737436867076 0 - vertex 44.116789181895 14.169696006639 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 12.002309837942 24.804173569059 0.110046151702 - vertex 12.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 60 17 0.77775 - vertex 54.002309837942 17 0.77775 - endloop -endfacet -facet normal 0 0.980785280403 0.195090322015 - outer loop - vertex 6.011309837942 15.063011877768 0.77775 - vertex 12.002309837942 15.195826430941 0.110046151702 - vertex 6.011309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 12.002309837942 23 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 15.830303993361 24.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.830303993361 24.883210818105 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 16.5 24.75 0.77775 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 18.25 26.5 0.77775 - vertex 18.25 26.5 0 - vertex 18.116789181895 25.830303993361 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.262563132924 25.262563132924 0.77775 - vertex 37.474084379442 23 0.77775 - vertex 41.830303993361 24.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.607403236621 30 0.77775 - vertex 14.883210818105 27.169696006639 0.77775 - vertex 15.262563132924 27.737436867076 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 14.737436867076 0.77775 - vertex 15.455907969142 17 0.77775 - vertex 17.169696006639 15.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 14.737436867076 0.77775 - vertex 34.416922535211 17 0.77775 - vertex 15.455907969142 17 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.306548743796 10 0.77775 - vertex 15.262563132924 12.262563132924 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 17.169696006639 24.883210818105 0.77775 - vertex 17.737436867076 25.262563132924 0.77775 - vertex 17.737436867076 25.262563132924 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 16.5 15.25 0.77775 - vertex 15.455907969142 17 0.77775 - vertex 15.830303993361 15.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.830303993361 28.116789181895 0.77775 - vertex 42.5 28.25 0.77775 - vertex 41.866228156844 30 0.77775 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 18.116789181895 12.830303993361 0.77775 - vertex 18.25 13.5 0.77775 - vertex 18.25 13.5 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 60 17 0.77775 - vertex 60 17 0 - vertex 54.002309837942 17 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 15.455907969142 17 0.77775 - vertex 12.002309837942 17 0 - vertex 12.002309837942 17 0.77775 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 43.169696006639 11.883210818105 0 - vertex 43.737436867076 12.262563132924 0.77775 - vertex 43.737436867076 12.262563132924 0 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 43.169696006639 11.883210818105 0 - vertex 43.169696006639 11.883210818105 0.77775 - vertex 43.737436867076 12.262563132924 0.77775 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 -0 - outer loop - vertex 18.25 13.5 0.77775 - vertex 18.116789181895 14.169696006639 0 - vertex 18.25 13.5 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 42.5 28.25 0 - vertex 41.830303993361 28.116789181895 0 - vertex 17.169696006639 28.116789181895 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 23 0.77775 - vertex 48.011309837942 23 0 - vertex 48.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.169696006639 15.116789181895 0.77775 - vertex 15.455907969142 17 0.77775 - vertex 16.5 15.25 0.77775 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 17.737436867076 12.262563132924 0.77775 - vertex 17.737436867076 12.262563132924 0 - vertex 17.169696006639 11.883210818105 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 52 40 0.77775 - vertex 60 23 0.77775 - vertex 60 40 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 40.75 13.5 0 - vertex 18.116789181895 12.830303993361 0 - vertex 18.25 13.5 0 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 43.169696006639 28.116789181895 0 - vertex 42.5 28.25 0.77775 - vertex 42.5 28.25 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 23 0 - vertex 12.002309837942 23 0 - vertex 42.5 24.75 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 23 0.77775 - vertex 60 23 0.77775 - vertex 54.002309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 23 0.77775 - vertex 6.011309837942 24.730643081307 0 - vertex 6.011309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 17.169696006639 15.116789181895 0 - vertex 16.5 15.25 0.77775 - vertex 16.5 15.25 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 17 0.77775 - vertex 6.011309837942 15.063011877768 0.77775 - vertex 6.011309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 60 17 0.77775 - vertex 60 0 0 - vertex 60 17 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 60 0 0.77775 - vertex 60 0 0 - vertex 60 17 0.77775 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 15.262563132924 12.262563132924 0.77775 - vertex 15.830303993361 11.883210818105 0.77775 - vertex 15.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 52 10 0.77775 - vertex 44.116789181895 12.830303993361 0.77775 - vertex 43.737436867076 12.262563132924 0.77775 - endloop -endfacet -facet normal 0 0.980785280403 0.195090322015 - outer loop - vertex 6.011309837942 15.063011877768 0.77775 - vertex 12.002309837942 15.063011877768 0.77775 - vertex 12.002309837942 15.195826430941 0.110046151702 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.169696006639 24.883210818105 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 17.737436867076 25.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 52 10 0.77775 - vertex 43.737436867076 12.262563132924 0.77775 - vertex 43.169696006639 11.883210818105 0.77775 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 42.5 28.25 0.77775 - vertex 41.830303993361 28.116789181895 0 - vertex 42.5 28.25 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 6.011309837942 15.269356918694 0 - vertex 6.011309837942 17 0 - vertex 6.011309837942 17 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 40.883210818105 25.830303993361 0.77775 - vertex 37.474084379442 23 0.77775 - vertex 41.262563132924 25.262563132924 0.77775 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 18.116789181895 12.830303993361 0.77775 - vertex 18.25 13.5 0 - vertex 18.116789181895 12.830303993361 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 25.262563132924 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 18.116789181895 25.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 34.416922535211 17 0.77775 - vertex 41.262563132924 14.737436867076 0.77775 - vertex 41.830303993361 15.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 0 30 0.77775 - vertex 6.011309837942 24.936988122232 0.77775 - vertex 12.002309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 25.830303993361 0.77775 - vertex 17.379510917074 23 0.77775 - vertex 37.474084379442 23 0.77775 - endloop -endfacet -facet normal 0 -0.980785280403 0.195090322015 - outer loop - vertex 6.011309837942 24.936988122232 0.77775 - vertex 12.002309837942 24.804173569059 0.110046151702 - vertex 12.002309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 52 10 0.77775 - vertex 43.169696006639 11.883210818105 0.77775 - vertex 42.5 11.75 0.77775 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 41.262563132924 14.737436867076 0.77775 - vertex 40.883210818105 14.169696006639 0 - vertex 41.262563132924 14.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 23 0 - vertex 43.169696006639 24.883210818105 0 - vertex 43.737436867076 25.262563132924 0 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 44.25 26.5 0.77775 - vertex 44.116789181895 25.830303993361 0 - vertex 44.116789181895 25.830303993361 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 60 17 0.77775 - vertex 54.002309837942 17 0 - vertex 54.002309837942 17 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 48.011309837942 23 0 - vertex 42.5 24.75 0 - vertex 43.169696006639 24.883210818105 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 43.737436867076 27.737436867076 0.77775 - vertex 44.116789181895 27.169696006639 0.77775 - vertex 52 30 0.77775 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 18.116789181895 25.830303993361 0.77775 - vertex 18.116789181895 25.830303993361 0 - vertex 17.737436867076 25.262563132924 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 15.195826430941 0.110046151702 - vertex 54.002309837942 17 0.77775 - vertex 54.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 14.883210818105 27.169696006639 0.77775 - vertex 14.75 26.5 0 - vertex 14.883210818105 27.169696006639 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 52 0 0.77775 - vertex 52 0 0 - vertex 60 0 0.77775 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 14.883210818105 27.169696006639 0.77775 - vertex 14.75 26.5 0.77775 - vertex 14.75 26.5 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 15.269356918694 0 - vertex 54.002309837942 17 0.77775 - vertex 54.002309837942 17 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 16.5 11.75 0.77775 - vertex 15.306548743796 10 0.77775 - vertex 17.169696006639 11.883210818105 0.77775 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 17.169696006639 15.116789181895 0 - vertex 17.169696006639 15.116789181895 0.77775 - vertex 16.5 15.25 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 12.002309837942 15.195826430941 0.110046151702 - vertex 12.002309837942 15.063011877768 0.77775 - vertex 12.002309837942 17 0.77775 - endloop -endfacet -facet normal 0 0.980785280403 0.195090322015 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 48.011309837942 15.195826430941 0.110046151702 - vertex 48.011309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 16.5 11.75 0.77775 - vertex 16.5 11.75 0 - vertex 15.830303993361 11.883210818105 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 48.011309837942 15.063011877768 0.77775 - vertex 48.011309837942 15.269356918694 0 - vertex 48.011309837942 17 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 24.936988122232 0.77775 - vertex 52 30 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal -0.195090322016 0.980785280403 0 - outer loop - vertex 42.5 24.75 0.77775 - vertex 43.169696006639 24.883210818105 0 - vertex 42.5 24.75 0 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 14.75 26.5 0 - vertex 14.75 26.5 0.77775 - vertex 14.883210818105 25.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 14.169696006639 0 - vertex 43.737436867076 14.737436867076 0 - vertex 48.011309837942 17 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 44.116789181895 14.169696006639 0 - vertex 48.011309837942 17 0 - vertex 48.011309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.169696006639 24.883210818105 0 - vertex 41.830303993361 24.883210818105 0 - vertex 42.5 24.75 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 17.169696006639 24.883210818105 0 - vertex 42.5 24.75 0 - vertex 12.002309837942 23 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 52 40 0 - vertex 52 40 0.77775 - vertex 60 40 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 52 40 0 - vertex 60 40 0.77775 - vertex 60 40 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 0 - outer loop - vertex 18.116789181895 27.169696006639 0.77775 - vertex 17.737436867076 27.737436867076 0.77775 - vertex 17.737436867076 27.737436867076 0 - endloop -endfacet -facet normal -0.831469612302 -0.555570233021 -0 - outer loop - vertex 18.116789181895 27.169696006639 0.77775 - vertex 17.737436867076 27.737436867076 0 - vertex 18.116789181895 27.169696006639 0 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 15.830303993361 24.883210818105 0 - vertex 15.830303993361 24.883210818105 0.77775 - vertex 16.5 24.75 0.77775 - endloop -endfacet -facet normal 0.195090322016 0.980785280403 0 - outer loop - vertex 15.830303993361 24.883210818105 0 - vertex 16.5 24.75 0.77775 - vertex 16.5 24.75 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 12.002309837942 24.936988122232 0.77775 - vertex 12.002309837942 23 0.77775 - vertex 15.262563132924 25.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 12.002309837942 24.936988122232 0.77775 - vertex 15.262563132924 25.262563132924 0.77775 - vertex 14.883210818105 25.830303993361 0.77775 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 60 40 0.77775 - vertex 60 23 0.77775 - vertex 60 23 0 - endloop -endfacet -facet normal 1 0 0 - outer loop - vertex 60 40 0.77775 - vertex 60 23 0 - vertex 60 40 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 15.262563132924 27.737436867076 0 - vertex 15.262563132924 27.737436867076 0.77775 - vertex 14.883210818105 27.169696006639 0.77775 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 15.262563132924 27.737436867076 0 - vertex 14.883210818105 27.169696006639 0.77775 - vertex 14.883210818105 27.169696006639 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 37.474084379442 23 0.77775 - vertex 48.011309837942 23 0.77775 - vertex 42.5 24.75 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 37.474084379442 23 0.77775 - vertex 42.5 24.75 0.77775 - vertex 41.830303993361 24.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.262563132924 14.737436867076 0 - vertex 12.002309837942 17 0 - vertex 41.422110817733 17 0 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 0 - outer loop - vertex 43.169696006639 15.116789181895 0.77775 - vertex 42.5 15.25 0.77775 - vertex 42.5 15.25 0 - endloop -endfacet -facet normal -0.195090322016 -0.980785280403 -0 - outer loop - vertex 43.169696006639 15.116789181895 0.77775 - vertex 42.5 15.25 0 - vertex 43.169696006639 15.116789181895 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 52 10 0.77775 - vertex 60 0 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 15.063011877768 0.77775 - vertex 60 0 0.77775 - vertex 60 17 0.77775 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 40.75 13.5 0.77775 - vertex 40.883210818105 12.830303993361 0.77775 - vertex 40.883210818105 12.830303993361 0 - endloop -endfacet -facet normal 0.980785280403 0.195090322016 0 - outer loop - vertex 40.75 13.5 0.77775 - vertex 40.883210818105 12.830303993361 0 - vertex 40.75 13.5 0 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 0 - outer loop - vertex 17.737436867076 27.737436867076 0 - vertex 17.737436867076 27.737436867076 0.77775 - vertex 17.169696006639 28.116789181895 0.77775 - endloop -endfacet -facet normal -0.555570233021 -0.831469612302 0 - outer loop - vertex 17.737436867076 27.737436867076 0 - vertex 17.169696006639 28.116789181895 0.77775 - vertex 17.169696006639 28.116789181895 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.883210818105 27.169696006639 0.77775 - vertex 0 30 0.77775 - vertex 12.002309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.883210818105 27.169696006639 0.77775 - vertex 12.002309837942 24.936988122232 0.77775 - vertex 14.75 26.5 0.77775 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 43.737436867076 12.262563132924 0.77775 - vertex 44.116789181895 12.830303993361 0.77775 - vertex 44.116789181895 12.830303993361 0 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 43.737436867076 12.262563132924 0.77775 - vertex 44.116789181895 12.830303993361 0 - vertex 43.737436867076 12.262563132924 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 48.011309837942 23 0 - vertex 48.011309837942 23 0.77775 - vertex 37.474084379442 23 0.77775 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 16.5 15.25 0.77775 - vertex 15.830303993361 15.116789181895 0.77775 - vertex 15.830303993361 15.116789181895 0 - endloop -endfacet -facet normal 0.195090322016 -0.980785280403 0 - outer loop - vertex 16.5 15.25 0.77775 - vertex 15.830303993361 15.116789181895 0 - vertex 16.5 15.25 0 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 40.883210818105 12.830303993361 0.77775 - vertex 41.262563132924 12.262563132924 0.77775 - vertex 41.262563132924 12.262563132924 0 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 40.883210818105 12.830303993361 0.77775 - vertex 41.262563132924 12.262563132924 0 - vertex 40.883210818105 12.830303993361 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 17 0 - vertex 16.5 15.25 0 - vertex 15.830303993361 15.116789181895 0 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 43.737436867076 25.262563132924 0 - vertex 43.737436867076 25.262563132924 0.77775 - vertex 44.116789181895 25.830303993361 0.77775 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 43.737436867076 25.262563132924 0 - vertex 44.116789181895 25.830303993361 0.77775 - vertex 44.116789181895 25.830303993361 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 40.883210818105 14.169696006639 0.77775 - vertex 40.75 13.5 0.77775 - vertex 40.75 13.5 0 - endloop -endfacet -facet normal 0.980785280403 -0.195090322016 0 - outer loop - vertex 40.883210818105 14.169696006639 0.77775 - vertex 40.75 13.5 0 - vertex 40.883210818105 14.169696006639 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 60 23 0 - vertex 60 23 0.77775 - vertex 54.002309837942 23 0.77775 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 60 23 0 - vertex 54.002309837942 23 0.77775 - vertex 54.002309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 0 30 0 - vertex 14.042553191489 30 0 - vertex 14.883210818105 27.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 0 30 0 - vertex 14.883210818105 27.169696006639 0 - vertex 6.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 41.262563132924 25.262563132924 0 - vertex 41.262563132924 25.262563132924 0.77775 - vertex 41.830303993361 24.883210818105 0.77775 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 41.262563132924 25.262563132924 0 - vertex 41.830303993361 24.883210818105 0.77775 - vertex 41.830303993361 24.883210818105 0 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 41.830303993361 28.116789181895 0.77775 - vertex 41.262563132924 27.737436867076 0.77775 - vertex 41.262563132924 27.737436867076 0 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 41.830303993361 28.116789181895 0.77775 - vertex 41.262563132924 27.737436867076 0 - vertex 41.830303993361 28.116789181895 0 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 43.169696006639 24.883210818105 0.77775 - vertex 43.737436867076 25.262563132924 0.77775 - vertex 43.737436867076 25.262563132924 0 - endloop -endfacet -facet normal -0.555570233021 0.831469612302 0 - outer loop - vertex 43.169696006639 24.883210818105 0.77775 - vertex 43.737436867076 25.262563132924 0 - vertex 43.169696006639 24.883210818105 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 10 0 - vertex 43.169696006639 11.883210818105 0 - vertex 43.737436867076 12.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 52 10 0 - vertex 43.737436867076 12.262563132924 0 - vertex 54.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 24.936988122232 0.77775 - vertex 60 23 0.77775 - vertex 52 40 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 54.002309837942 24.936988122232 0.77775 - vertex 52 40 0.77775 - vertex 52 30 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 15.455907969142 17 0.77775 - vertex 34.416922535211 17 0.77775 - vertex 41.422110817733 17 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 15.455907969142 17 0.77775 - vertex 41.422110817733 17 0 - vertex 12.002309837942 17 0 - endloop -endfacet -facet normal 0 -0.831469612304 0.555570233017 - outer loop - vertex 12.002309837942 24.804173569059 0.110046151702 - vertex 6.011309837942 24.804173569059 0.110046151702 - vertex 6.011309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 -0.831469612304 0.555570233017 - outer loop - vertex 12.002309837942 24.804173569059 0.110046151702 - vertex 6.011309837942 24.730643081307 0 - vertex 12.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.262563132924 14.737436867076 0.77775 - vertex 15.455907969142 17 0.77775 - vertex 12.002309837942 17 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 15.262563132924 14.737436867076 0.77775 - vertex 12.002309837942 17 0.77775 - vertex 14.883210818105 14.169696006639 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 44.116789181895 25.830303993361 0.77775 - vertex 43.737436867076 25.262563132924 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 0 17 0.77775 - vertex 0 10 0.77775 - vertex 6.011309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 0 17 0.77775 - vertex 6.011309837942 15.063011877768 0.77775 - vertex 6.011309837942 17 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 17 0.77775 - vertex 34.416922535211 17 0.77775 - vertex 42.5 15.25 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 17 0.77775 - vertex 42.5 15.25 0.77775 - vertex 43.169696006639 15.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.883210818105 14.169696006639 0.77775 - vertex 12.002309837942 17 0.77775 - vertex 12.002309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 14.883210818105 14.169696006639 0.77775 - vertex 12.002309837942 15.063011877768 0.77775 - vertex 14.75 13.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 6.011309837942 24.936988122232 0.77775 - vertex 0 30 0.77775 - vertex 0 23 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 6.011309837942 24.936988122232 0.77775 - vertex 0 23 0.77775 - vertex 6.011309837942 23 0.77775 - endloop -endfacet -facet normal -0 -0 -1 - outer loop - vertex 40.75 26.5 0 - vertex 40.883210818105 25.830303993361 0 - vertex 18.116789181895 27.169696006639 0 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 0 - outer loop - vertex 44.25 13.5 0.77775 - vertex 44.116789181895 14.169696006639 0.77775 - vertex 44.116789181895 14.169696006639 0 - endloop -endfacet -facet normal -0.980785280403 -0.195090322016 -0 - outer loop - vertex 44.25 13.5 0.77775 - vertex 44.116789181895 14.169696006639 0 - vertex 44.25 13.5 0 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 17.737436867076 12.262563132924 0 - vertex 17.737436867076 12.262563132924 0.77775 - vertex 18.116789181895 12.830303993361 0.77775 - endloop -endfacet -facet normal -0.831469612302 0.555570233021 0 - outer loop - vertex 17.737436867076 12.262563132924 0 - vertex 18.116789181895 12.830303993361 0.77775 - vertex 18.116789181895 12.830303993361 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 0 10 0.77775 - vertex 15.306548743796 10 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - endloop -endfacet -facet normal 0 -0.980785280403 0.195090322015 - outer loop - vertex 54.002309837942 24.804173569059 0.110046151702 - vertex 54.002309837942 24.936988122232 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 -0.980785280403 0.195090322015 - outer loop - vertex 54.002309837942 24.804173569059 0.110046151702 - vertex 48.011309837942 24.936988122232 0.77775 - vertex 48.011309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 14.883210818105 12.830303993361 0 - vertex 14.883210818105 12.830303993361 0.77775 - vertex 15.262563132924 12.262563132924 0.77775 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 14.883210818105 12.830303993361 0 - vertex 15.262563132924 12.262563132924 0.77775 - vertex 15.262563132924 12.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 54.002309837942 15.269356918694 0 - vertex 43.737436867076 12.262563132924 0 - vertex 44.116789181895 12.830303993361 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 54.002309837942 15.269356918694 0 - vertex 44.116789181895 12.830303993361 0 - vertex 48.011309837942 15.269356918694 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 0 30 0 - vertex 0 30 0.77775 - vertex 14.607403236621 30 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 0 30 0 - vertex 14.607403236621 30 0.77775 - vertex 14.042553191489 30 0 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 41.262563132924 12.262563132924 0 - vertex 41.262563132924 12.262563132924 0.77775 - vertex 41.830303993361 11.883210818105 0.77775 - endloop -endfacet -facet normal 0.555570233021 0.831469612302 0 - outer loop - vertex 41.262563132924 12.262563132924 0 - vertex 41.830303993361 11.883210818105 0.77775 - vertex 41.830303993361 11.883210818105 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 0 10 0 - vertex 0 10 0.77775 - vertex 0 17 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 0 10 0 - vertex 0 17 0.77775 - vertex 0 17 0 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 44.116789181895 12.830303993361 0.77775 - vertex 44.25 13.5 0.77775 - vertex 44.25 13.5 0 - endloop -endfacet -facet normal -0.980785280403 0.195090322016 0 - outer loop - vertex 44.116789181895 12.830303993361 0.77775 - vertex 44.25 13.5 0 - vertex 44.116789181895 12.830303993361 0 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 41.422110817733 17 0 - vertex 34.416922535211 17 0.77775 - vertex 48.011309837942 17 0.77775 - endloop -endfacet -facet normal 0 1 0 - outer loop - vertex 41.422110817733 17 0 - vertex 48.011309837942 17 0.77775 - vertex 48.011309837942 17 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 52 30 0.77775 - vertex 52 40 0.77775 - vertex 52 40 0 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 52 30 0.77775 - vertex 52 40 0 - vertex 52 30 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 15.830303993361 24.883210818105 0 - vertex 16.5 24.75 0 - vertex 12.002309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.262563132924 27.737436867076 0 - vertex 40.883210818105 27.169696006639 0 - vertex 17.737436867076 27.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 41.262563132924 27.737436867076 0 - vertex 17.737436867076 27.737436867076 0 - vertex 17.169696006639 28.116789181895 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 6.011309837942 15.063011877768 0.77775 - vertex 0 10 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 6.011309837942 15.063011877768 0.77775 - vertex 14.883210818105 12.830303993361 0.77775 - vertex 12.002309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 17 0.77775 - vertex 43.737436867076 14.737436867076 0.77775 - vertex 44.116789181895 14.169696006639 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 17 0.77775 - vertex 44.116789181895 14.169696006639 0.77775 - vertex 48.011309837942 15.063011877768 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 15.262563132924 25.262563132924 0 - vertex 15.830303993361 24.883210818105 0 - vertex 12.002309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 15.262563132924 25.262563132924 0 - vertex 12.002309837942 23 0 - vertex 12.002309837942 24.730643081307 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 44.25 26.5 0.77775 - vertex 44.116789181895 25.830303993361 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 40.883210818105 27.169696006639 0 - vertex 40.75 26.5 0 - vertex 18.116789181895 27.169696006639 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 40.883210818105 27.169696006639 0 - vertex 18.116789181895 27.169696006639 0 - vertex 17.737436867076 27.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 17 0 - vertex 41.262563132924 14.737436867076 0 - vertex 17.169696006639 15.116789181895 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 17 0 - vertex 17.169696006639 15.116789181895 0 - vertex 16.5 15.25 0 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 15.830303993361 15.116789181895 0 - vertex 15.830303993361 15.116789181895 0.77775 - vertex 15.262563132924 14.737436867076 0.77775 - endloop -endfacet -facet normal 0.555570233021 -0.831469612302 0 - outer loop - vertex 15.830303993361 15.116789181895 0 - vertex 15.262563132924 14.737436867076 0.77775 - vertex 15.262563132924 14.737436867076 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 41.262563132924 27.737436867076 0.77775 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 40.883210818105 27.169696006639 0 - endloop -endfacet -facet normal 0.831469612302 -0.555570233021 0 - outer loop - vertex 41.262563132924 27.737436867076 0.77775 - vertex 40.883210818105 27.169696006639 0 - vertex 41.262563132924 27.737436867076 0 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 48.011309837942 23 0 - vertex 37.474084379442 23 0.77775 - vertex 17.379510917074 23 0.77775 - endloop -endfacet -facet normal 0 -1 0 - outer loop - vertex 48.011309837942 23 0 - vertex 17.379510917074 23 0.77775 - vertex 12.002309837942 23 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 17 0 - vertex 15.830303993361 15.116789181895 0 - vertex 15.262563132924 14.737436867076 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 12.002309837942 17 0 - vertex 15.262563132924 14.737436867076 0 - vertex 12.002309837942 15.269356918694 0 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 40.883210818105 25.830303993361 0 - vertex 40.883210818105 25.830303993361 0.77775 - vertex 41.262563132924 25.262563132924 0.77775 - endloop -endfacet -facet normal 0.831469612302 0.555570233021 0 - outer loop - vertex 40.883210818105 25.830303993361 0 - vertex 41.262563132924 25.262563132924 0.77775 - vertex 41.262563132924 25.262563132924 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.883210818105 12.830303993361 0 - vertex 15.262563132924 12.262563132924 0 - vertex 14.464705848856 10 0 - endloop -endfacet -facet normal 0 0 -1 - outer loop - vertex 14.883210818105 12.830303993361 0 - vertex 14.464705848856 10 0 - vertex 0 10 0 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 27.737436867076 0.77775 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 41.262563132924 27.737436867076 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.262563132924 27.737436867076 0.77775 - vertex 17.169696006639 28.116789181895 0.77775 - vertex 17.737436867076 27.737436867076 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 23 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - vertex 43.737436867076 25.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 23 0.77775 - vertex 43.737436867076 25.262563132924 0.77775 - vertex 43.169696006639 24.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 15.063011877768 0.77775 - vertex 44.116789181895 14.169696006639 0.77775 - vertex 44.25 13.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 44.116789181895 27.169696006639 0.77775 - vertex 44.25 26.5 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 44.116789181895 27.169696006639 0.77775 - vertex 48.011309837942 24.936988122232 0.77775 - vertex 52 30 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 27.169696006639 0.77775 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 17.737436867076 27.737436867076 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 23 0.77775 - vertex 54.002309837942 24.936988122232 0.77775 - vertex 54.002309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.262563132924 27.737436867076 0.77775 - vertex 41.866228156844 30 0.77775 - vertex 14.607403236621 30 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.262563132924 27.737436867076 0.77775 - vertex 14.607403236621 30 0.77775 - vertex 17.169696006639 28.116789181895 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 15.063011877768 0.77775 - vertex 44.25 13.5 0.77775 - vertex 44.116789181895 12.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 48.011309837942 15.063011877768 0.77775 - vertex 44.116789181895 12.830303993361 0.77775 - vertex 52 10 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 14.169696006639 0.77775 - vertex 18.25 13.5 0.77775 - vertex 41.262563132924 12.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.25 26.5 0.77775 - vertex 40.883210818105 27.169696006639 0.77775 - vertex 18.116789181895 27.169696006639 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 24.730643081307 0 - vertex 54.002309837942 23 0 - vertex 54.002309837942 23 0.77775 - endloop -endfacet -facet normal -1 0 0 - outer loop - vertex 54.002309837942 24.730643081307 0 - vertex 54.002309837942 23 0.77775 - vertex 54.002309837942 24.804173569059 0.110046151702 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.830303993361 11.883210818105 0.77775 - vertex 41.262563132924 12.262563132924 0.77775 - vertex 18.25 13.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 41.830303993361 11.883210818105 0.77775 - vertex 18.25 13.5 0.77775 - vertex 18.116789181895 12.830303993361 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 12.830303993361 0.77775 - vertex 17.737436867076 12.262563132924 0.77775 - vertex 42.5 11.75 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 12.830303993361 0.77775 - vertex 42.5 11.75 0.77775 - vertex 41.830303993361 11.883210818105 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 12.262563132924 0.77775 - vertex 15.306548743796 10 0.77775 - vertex 52 10 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 17.737436867076 12.262563132924 0.77775 - vertex 52 10 0.77775 - vertex 42.5 11.75 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 40.883210818105 12.830303993361 0.77775 - vertex 18.116789181895 14.169696006639 0.77775 - vertex 41.262563132924 12.262563132924 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.25 26.5 0.77775 - vertex 40.75 26.5 0.77775 - vertex 40.883210818105 27.169696006639 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 25.830303993361 0.77775 - vertex 37.474084379442 23 0.77775 - vertex 40.75 26.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 18.116789181895 25.830303993361 0.77775 - vertex 40.75 26.5 0.77775 - vertex 18.25 26.5 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 40.883210818105 12.830303993361 0.77775 - vertex 34.416922535211 17 0.77775 - vertex 17.737436867076 14.737436867076 0.77775 - endloop -endfacet -facet normal 0 0 1 - outer loop - vertex 40.883210818105 12.830303993361 0.77775 - vertex 17.737436867076 14.737436867076 0.77775 - vertex 18.116789181895 14.169696006639 0.77775 - endloop -endfacet -endsolid