1 from StringIO import StringIO
2 from collections import OrderedDict
3 from config import config
4 from fabmetheus_utilities import euclidean
5 from fabmetheus_utilities.vector3 import Vector3
6 from math import pi
7 from paths import BoundaryPerimeter, Loop, InfillPath
8 from utilities import memory_tracker
9 import math
10 import sys
11 import time
12
13
15 - def __init__(self, z, runtimeParameters):
16
17 if runtimeParameters.profileMemory:
18 memory_tracker.track_object(self)
19
20 self.runtimeParameters = runtimeParameters
21 self.decimalPlaces = self.runtimeParameters.decimalPlaces
22 self.z = z
23
24 self.perimeter = None
25 self.loops = []
26 self.infillPaths = []
27
28 self.innerNestedRings = []
29
30
31 self.infillPathsHolder = []
32 self.extraLoops = []
33 self.penultimateFillLoops = []
34 self.lastFillLoops = None
35
36
37 self.bridgeFeedRateMinute = self.runtimeParameters.bridgeFeedRateMinute
38 self.perimeterFeedRateMinute = self.runtimeParameters.perimeterFeedRateMinute
39 self.extrusionFeedRateMinute = self.runtimeParameters.extrusionFeedRateMinute
40 self.travelFeedRateMinute = self.runtimeParameters.travelFeedRateMinute
41 self.extrusionUnitsRelative = self.runtimeParameters.extrusionUnitsRelative
42
43 self.oozeRate = self.runtimeParameters.oozeRate
44 self.zDistanceRatio = 5.0
45 self.extruderRetractionSpeedMinute = round(60.0 * self.runtimeParameters.extruderRetractionSpeed, self.decimalPlaces)
46
47 self.layerThickness = self.runtimeParameters.layerThickness
48 self.perimeterWidth = self.runtimeParameters.perimeterWidth
49 self.filamentDiameter = self.runtimeParameters.filamentDiameter
50 self.filamentPackingDensity = self.runtimeParameters.filamentPackingDensity
51 self.absolutePositioning = config.getboolean('preface', 'positioning.absolute')
52 self.flowRate = self.runtimeParameters.flowRate
53 self.perimeterFlowRate = self.runtimeParameters.perimeterFlowRate
54 self.bridgeFlowRate = self.runtimeParameters.bridgeFlowRate
55 self.previousPoint = None
56 filamentRadius = 0.5 * self.filamentDiameter
57 filamentPackingArea = pi * filamentRadius * filamentRadius * self.filamentPackingDensity
58 self.flowScaleSixty = 60.0 * ((((self.layerThickness + self.perimeterWidth) / 4) ** 2 * pi) / filamentPackingArea)
59
61 output = StringIO()
62 output.write('\n%4s#########################################' % '')
63 output.write('\n%8snestedRing:' % '')
64
65 output.write('\n%10sboundaryPerimeter:\n' % '')
66 output.write(self.perimeter)
67
68 output.write('\n%10sinnerNestedRings:\n' % '')
69 for innerNestedRing in self.innerNestedRings:
70 output.write('%12s%s\n' % ('', innerNestedRing))
71
72 output.write('\n%10sloops:\n' % '')
73 for loop in self.loops:
74 output.write(loop)
75
76 output.write('\n%10sextraLoops:\n' % '')
77 for extraLoop in self.extraLoops:
78 output.write('%12s%s\n' % ('', extraLoop))
79
80 output.write('\n%10spenultimateFillLoops:\n' % '')
81 for penultimateFillLoop in self.penultimateFillLoops:
82 output.write('%12s%s\n' % ('', penultimateFillLoop))
83
84 output.write('\n%10slastFillLoops:\n' % '')
85 if self.lastFillLoops != None:
86 for lastFillLoop in self.lastFillLoops:
87 output.write('%12s%s\n' % ('', lastFillLoop))
88
89 output.write('\n%10sinfillPaths:\n' % '')
90 for infillPath in self.infillPaths:
91 output.write(infillPath)
92
93 output.write('\n%4s###### end nestedRing ########################' % '')
94
95 return output.getvalue()
96
97
99 '''Returns the amount of time needed to print the ring, and the distance travelled.'''
100 duration = 0.0
101 distance = 0.0
102
103 (perimeterDistance, perimeterDuration) = self.perimeter.getDistanceAndDuration()
104 duration += perimeterDuration
105 distance += perimeterDistance
106
107 for loop in self.loops:
108 (loopDistance, loopDuration) = loop.getDistanceAndDuration()
109 duration += loopDuration
110 distance += loopDistance
111
112 for infillPath in self.infillPaths:
113 (infillPathDistance, infillPathDuration) = infillPath.getDistanceAndDuration()
114 duration += infillPathDuration
115 distance += infillPathDistance
116
117 for nestedRing in self.innerNestedRings:
118 (nestedRingPathDistance, nestedRingPathDuration) = nestedRing.getDistanceAndDuration()
119 duration += nestedRingPathDuration
120 distance += nestedRingPathDistance
121
122 return (distance, duration)
123
124
126 pathList.append(self.perimeter)
127
128 for innerNestedRing in self.innerNestedRings:
129 innerNestedRing.getPerimeterPaths(pathList)
130
132 for loop in self.loops:
133 pathList.append(loop)
134
135 for innerNestedRing in self.innerNestedRings:
136 innerNestedRing.getLoopPaths(pathList)
137
138
140 for infillPath in self.infillPaths:
141 pathList.append(infillPath)
142
143 for innerNestedRing in self.innerNestedRings:
144 innerNestedRing.getInfillPaths(pathList)
145
146
148 if self.perimeter != None:
149 return self.perimeter.getStartPoint()
150
151
153 'Moves the nested ring by the offset amount'
154 for innerNestedRing in self.innerNestedRings:
155 innerNestedRing.offset(offset)
156
157 self.perimeter.offset(offset)
158
159 for loop in self.loops:
160 loop.offset(offset)
161
162 for infillPath in self.infillPaths:
163 infillPath.offset(offset)
164
165
167 self.perimeter = BoundaryPerimeter(self.z, self.runtimeParameters)
168
169 for point in boundaryPointsLoop:
170 self.perimeter.boundaryPoints.append(Vector3(point.real, point.imag, self.z))
171
172 if len(boundaryPointsLoop) < 2:
173 return
174
175 if perimeterLoop == None:
176 perimeterLoop = boundaryPointsLoop
177
178 if euclidean.isWiddershins(perimeterLoop):
179 self.perimeter.type = 'outer'
180 else:
181 self.perimeter.type = 'inner'
182 path = perimeterLoop + [perimeterLoop[0]]
183 self.perimeter.addPath(path)
184
185
187 'Add a thread to the output.'
188
189 infillPath = InfillPath(self.z, self.runtimeParameters)
190 decimalPlaces = self.decimalPlaces
191 if len(thread) > 0:
192 infillPath.startPoint = thread[0]
193 infillPath.points = thread[1 :]
194 else:
195 logger.warning('Zero length vertex positions array which was skipped over, this should never happen.')
196 if len(thread) < 2:
197 logger.warning('Thread of only one point: %s, this should never happen.', thread)
198 return
199
200 self.infillPaths.append(infillPath)
201
202
204 'Get last fill loops from the outside loop and the loops inside the inside loops.'
205 if self.lastFillLoops == None:
206 return self.getSurroundingBoundaries()
207 return self.lastFillLoops
208
209
211 '''Converts XYZ boundary points to XY'''
212 xyBoundaries = []
213 for boundaryPoint in self.perimeter.boundaryPoints:
214 xyBoundaries.append(boundaryPoint.dropAxis())
215 return xyBoundaries
216
217
219 'Get the boundary of the surronding loop plus any boundaries of the innerNestedRings.'
220 surroundingBoundaries = [self.getXYBoundaries()]
221
222 for nestedRing in self.innerNestedRings:
223 surroundingBoundaries.append(nestedRing.getXYBoundaries())
224
225 return surroundingBoundaries
226
227
229 'Get last fill loops from the outside loop and the loops inside the inside loops.'
230 fillLoops = self.getLoopsToBeFilled()[:]
231 surroundingBoundaries = self.getSurroundingBoundaries()
232 withinLoops = []
233 if penultimateFillLoops == None:
234 penultimateFillLoops = self.penultimateFillLoops
235
236 if penultimateFillLoops != None:
237 for penultimateFillLoop in penultimateFillLoops:
238 if len(penultimateFillLoop) > 2:
239 if euclidean.getIsInFilledRegion(surroundingBoundaries, penultimateFillLoop[0]):
240 withinLoops.append(penultimateFillLoop)
241
242 if not euclidean.getIsInFilledRegionByPaths(self.penultimateFillLoops, fillLoops):
243 fillLoops += self.penultimateFillLoops
244
245 for nestedRing in self.innerNestedRings:
246 fillLoops += euclidean.getFillOfSurroundings(nestedRing.innerNestedRings, penultimateFillLoops)
247 return fillLoops
248
259
260 - def addToThreads(self, extrusionHalfWidth, oldOrderedLocation, threadSequence):
261 'Add to paths from the last location. perimeter>inner >fill>paths or fill> perimeter>inner >paths'
262 self.addPerimeterInner(extrusionHalfWidth, oldOrderedLocation, threadSequence)
263 self.transferInfillPaths(extrusionHalfWidth, oldOrderedLocation, threadSequence)
264
268
269 - def addPerimeterInner(self, extrusionHalfWidth, oldOrderedLocation, threadSequence):
270 'Add to the perimeter and the inner island.'
271 for loop in self.extraLoops:
272 innerPerimeterLoop = Loop(self.z, self.runtimeParameters)
273 if euclidean.isWiddershins(loop + [loop[0]]):
274 innerPerimeterLoop.type = 'outer'
275 else:
276 innerPerimeterLoop.type = 'inner'
277 innerPerimeterLoop.addPath(loop + [loop[0]])
278 self.loops.append(innerPerimeterLoop)
279
280 for innerNestedRing in self.innerNestedRings:
281 innerNestedRing.addToThreads(extrusionHalfWidth, oldOrderedLocation, threadSequence)
282