def getGeometryOutput(derivation, elementNode): "Get vector3 vertexes from attribute dictionary." if derivation == None: derivation = PolygonDerivation(elementNode) 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(elementNode, derivation.revolutions) return lineation.getGeometryOutputByLoop( elementNode, lineation.SideLoop(loop, derivation.sideAngle, sideLength))
def getGeometryOutput(derivation, xmlElement): "Get vector3 vertexes from attribute dictionary." if derivation == 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 getQuadraticPath(elementNode): "Get the quadratic path." end = evaluate.getVector3FromElementNode(elementNode) previousElementNode = elementNode.getPreviousElementNode() if previousElementNode is None: print( 'Warning, can not get previousElementNode in getQuadraticPath in quadratic for:' ) print(elementNode) return [end] begin = elementNode.getPreviousVertex(Vector3()) controlPoint = evaluate.getVector3ByPrefix(None, elementNode, 'controlPoint') if controlPoint is None: oldControlPoint = evaluate.getVector3ByPrefixes( previousElementNode, ['controlPoint', 'controlPoint1'], None) if oldControlPoint is None: oldControlPoint = end controlPoint = begin + begin - oldControlPoint evaluate.addVector3ToElementNode(elementNode, 'controlPoint', controlPoint) return svg_reader.getQuadraticPoints( begin, controlPoint, end, lineation.getNumberOfBezierPoints(begin, elementNode, end))
def getQuadraticPath(xmlElement): "Get the quadratic path." end = evaluate.getVector3FromXMLElement(xmlElement) previousXMLElement = xmlElement.getPreviousXMLElement() if previousXMLElement == 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 == None: oldControlPoint = evaluate.getVector3ByPrefixes( ['controlPoint', 'controlPoint1'], None, previousXMLElement) if oldControlPoint == 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 getGeometryOutput(derivation, xmlElement): "Get triangle mesh from attribute dictionary." if derivation == None: derivation = ExtrudeDerivation() derivation.setToXMLElement(xmlElement) if derivation.radius != complex(): maximumRadius = max(derivation.radius.real, derivation.radius.imag) sides = int(math.ceil(evaluate.getSidesMinimumThreeBasedOnPrecisionSides(maximumRadius, xmlElement))) loop = [] sideAngle = 2.0 * math.pi / sides angleTotal = 0.0 for side in xrange(sides): point = euclidean.getWiddershinsUnitPolar(angleTotal) loop.append(Vector3(point.real * derivation.radius.real, point.imag * derivation.radius.imag)) angleTotal += sideAngle derivation.target = [loop] + derivation.target if len(euclidean.getConcatenatedList(derivation.target)) == 0: print('Warning, in extrude there are no paths.') print(xmlElement.attributeDictionary) return None negatives = [] positives = [] addNegativesPositives(derivation, negatives, derivation.target, positives) return getGeometryOutputByNegativesPositives(derivation, negatives, positives, xmlElement)
def moveCircle(self, arealOverlapRatio, derivation, otherCircles): 'Move circle into an open spot.' angle = (abs(self.center) + self.radius) % euclidean.globalTau movedCenter = self.center searchRadius = derivation.searchRadiusOverRadius * self.radius distanceIncrement = searchRadius / float(derivation.searchAttempts) distance = 0.0 greatestRadius = self.radius searchCircles = [] searchCircleDistance = searchRadius + searchRadius + self.radius + derivation.wallThickness for otherCircle in otherCircles: if abs(self.center - otherCircle.center) <= searchCircleDistance + otherCircle.radius: searchCircles.append(otherCircle) for attemptIndex in xrange(derivation.searchAttempts): angle += euclidean.globalGoldenAngle distance += distanceIncrement offset = distance * euclidean.getWiddershinsUnitPolar(angle) attemptCenter = self.center + Vector3(offset.real, offset.imag) radius = self.getRadius(arealOverlapRatio, attemptCenter, derivation, searchCircles) if radius > greatestRadius: greatestRadius = radius movedCenter = attemptCenter self.center = movedCenter self.radius = greatestRadius
def getGeometryOutput(derivation, xmlElement): "Get vector3 vertexes from attribute dictionary." if derivation == None: derivation = CircleDerivation(xmlElement) loop = [] angleTotal = math.radians(derivation.start) sidesCeiling = int( math.ceil(abs(derivation.sides) * derivation.extent / 360.0)) sideAngle = math.radians(derivation.extent) / sidesCeiling spiral = lineation.Spiral(derivation.spiral, 0.5 * sideAngle / math.pi) for side in xrange(sidesCeiling + 1): unitPolar = euclidean.getWiddershinsUnitPolar(angleTotal) vertex = spiral.getSpiralPoint( unitPolar, Vector3(unitPolar.real * derivation.radius.real, unitPolar.imag * derivation.radius.imag)) angleTotal += sideAngle loop.append(vertex) loop = euclidean.getLoopWithoutCloseEnds( 0.000001 * max(derivation.radius.real, derivation.radius.imag), loop) sideLength = sideAngle * lineation.getRadiusAverage(derivation.radius) lineation.setClosedAttribute(derivation.revolutions, xmlElement) return lineation.getGeometryOutputByLoop( lineation.SideLoop(loop, sideAngle, sideLength), xmlElement)
def setToArtOfIllusionDictionary(self): "Set the shape of this carvable object info." vertexElement = self.elementNode.getFirstChildByLocalName('vertex') vertexPointElements = vertexElement.getChildElementsByLocalName( 'bf:Elem') for vertexPointElement in vertexPointElements: coordinateElement = vertexPointElement.getFirstChildByLocalName( 'r') vertex = Vector3(float(coordinateElement.attributes['x']), float(coordinateElement.attributes['y']), float(coordinateElement.attributes['z'])) self.vertexes.append(vertex) edgeElement = self.elementNode.getFirstChildByLocalName('edge') edgeSubelements = edgeElement.getChildElementsByLocalName('bf:Elem') for edgeSubelementIndex in xrange(len(edgeSubelements)): edgeSubelement = edgeSubelements[edgeSubelementIndex] vertexIndexes = [ int(edgeSubelement.attributes['v1']), int(edgeSubelement.attributes['v2']) ] edge = face.Edge().getFromVertexIndexes(edgeSubelementIndex, vertexIndexes) self.edges.append(edge) faceElement = self.elementNode.getFirstChildByLocalName('face') faceSubelements = faceElement.getChildElementsByLocalName('bf:Elem') for faceSubelementIndex in xrange(len(faceSubelements)): faceSubelement = faceSubelements[faceSubelementIndex] edgeIndexes = [ int(faceSubelement.attributes['e1']), int(faceSubelement.attributes['e2']), int(faceSubelement.attributes['e3']) ] self.faces.append(face.Face().getFromEdgeIndexes( edgeIndexes, self.edges, faceSubelementIndex)) removeListArtOfIllusionFromDictionary(self.elementNode.attributes, ['closed', 'smoothingMethod'])
def getCubicPath(xmlElement): "Get the cubic path." end = evaluate.getVector3FromXMLElement(xmlElement) previousXMLElement = xmlElement.getPreviousXMLElement() if previousXMLElement == 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 == None: oldControlPoint = evaluate.getVector3ByPrefixes( ['controlPoint', 'controlPoint1'], None, previousXMLElement) if oldControlPoint == None: oldControlPoints = evaluate.getTransformedPathByKey( [], 'controlPoints', previousXMLElement) if len(oldControlPoints) > 0: oldControlPoint = oldControlPoints[-1] if oldControlPoint == None: oldControlPoint = end controlPoint0 = begin + begin - oldControlPoint return getCubicPathByBeginEnd(begin, [controlPoint0, controlPoint1], end, xmlElement)
def getCraftedGcode( self, gcodeText, repository ): "Parse gcode text and store the statistics." self.absolutePerimeterWidth = 0.4 self.characters = 0 self.cornerHigh = Vector3( - 999999999.0, - 999999999.0, - 999999999.0 ) self.cornerLow = Vector3( 999999999.0, 999999999.0, 999999999.0 ) self.extruderActive = False self.extruderSpeed = 0.0 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 = gcodec.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.cornerHigh += halfExtrusionCorner self.cornerLow -= halfExtrusionCorner extent = self.cornerHigh - self.cornerLow roundedHigh = euclidean.getRoundedPoint( self.cornerHigh ) roundedLow = euclidean.getRoundedPoint( self.cornerLow ) roundedExtent = euclidean.getRoundedPoint( extent ) axisString = " axis, the extrusion starts at " crossSectionArea = 0.9 * self.absolutePerimeterWidth * self.layerThickness # 0.9 if from the typical fill density if self.extrusionDiameter != None: crossSectionArea = math.pi / 4.0 * self.extrusionDiameter * self.extrusionDiameter volumeExtruded = 0.001 * crossSectionArea * self.totalDistanceExtruded self.addLine( "On the 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( "On the 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( "On the 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( "The average feedRate is %s mm/s, (%s mm/min)." % ( euclidean.getThreeSignificantFigures( averageFeedRate ), euclidean.getThreeSignificantFigures( 60.0 * averageFeedRate ) ) ) self.addLine( "The cross section area is %s mm2." % euclidean.getThreeSignificantFigures( crossSectionArea ) ) if self.extrusionDiameter != None: self.addLine( "The extrusion diameter is %s mm." % euclidean.getThreeSignificantFigures( self.extrusionDiameter ) ) self.addLine( 'The extrusion fill density ratio is %s' % euclidean.getThreeSignificantFigures( crossSectionArea / self.absolutePerimeterWidth / self.layerThickness ) ) # self.addLine( 'The perimeter extrusion fill density ratio is %s' % euclidean.getThreeSignificantFigures( crossSectionArea / self.absolutePerimeterWidth / self.layerThickness ) ) self.addLine( "The extruder speed is %s" % euclidean.getThreeSignificantFigures( self.extruderSpeed ) ) self.addLine( "The extruder was extruding %s percent of the time." % euclidean.getThreeSignificantFigures( 100.0 * self.totalDistanceExtruded / self.totalDistanceTraveled ) ) self.addLine( "The extruder was toggled %s times." % self.extruderToggled ) self.addLine( "The layer thickness is %s mm." % euclidean.getThreeSignificantFigures( self.layerThickness ) ) if self.operatingFeedRatePerSecond != None: flowRate = crossSectionArea * self.operatingFeedRatePerSecond self.addLine( "The operating flow rate is %s mm3/s." % euclidean.getThreeSignificantFigures( flowRate ) ) self.addLine( "The perimeter width is %s mm." % euclidean.getThreeSignificantFigures( self.absolutePerimeterWidth ) ) self.addLine( " " ) self.addLine( "The following procedures have been performed on the skein:" ) for procedure in self.procedures: self.addLine( procedure ) self.addLine( " " ) self.addLine( "The text has %s lines and a size of %s KB." % ( self.numberOfLines, kilobytes ) ) self.addLine( "The total build time is %s s." % int( round( self.totalBuildTime ) ) ) Filehandle = open ('report.txt', 'a') Filehandle.write ("The total build time is %s s." % int( round( self.totalBuildTime ) )+'\n') self.addLine( "The total distance extruded is %s mm." % euclidean.getThreeSignificantFigures( self.totalDistanceExtruded ) ) self.addLine( "The total distance traveled is %s mm." % euclidean.getThreeSignificantFigures( self.totalDistanceTraveled ) ) if self.version != None: self.addLine( "The version is " + self.version ) self.addLine( "The volume extruded is %s cc." % euclidean.getThreeSignificantFigures( volumeExtruded ) ) Filehandle.write ("The volume extruded is %s cc." % euclidean.getThreeSignificantFigures( volumeExtruded )+'\n') Filehandle.close () return self.output.getvalue()
def getVertexGivenLine(line): "Get vertex given obj vertex line." splitLine = line.split() return Vector3(float(splitLine[1]), float(splitLine[2]), float(splitLine[3]))
def getTranslateTetragrid(elementNode, prefix): 'Get translate matrix and delete the translate attributes.' translation = getCumulativeVector3Remove(Vector3(), elementNode, prefix) if translation.getIsDefault(): return None return getTranslateTetragridByTranslation(translation)
def getGeometryOutput(xmlElement): "Get vector3 vertexes from attribute dictionary." start = evaluate.getVector3ByPrefix('start', Vector3(), xmlElement) end = evaluate.getVector3ByPrefix('end', Vector3(), xmlElement) endMinusStart = end - start endMinusStartLength = abs(endMinusStart) if endMinusStartLength <= 0.0: print( 'Warning, end is the same as start in getGeometryOutput in line for:' ) print(start) print(end) print(xmlElement) return None steps = evaluate.getEvaluatedFloatDefault(None, 'steps', xmlElement) step = evaluate.getEvaluatedFloatDefault(None, 'step', xmlElement) xmlElement.attributeDictionary['closed'] = str( evaluate.getEvaluatedBooleanDefault(False, 'closed', xmlElement)) if step == None and steps == None: return lineation.getGeometryOutputByLoop( lineation.SideLoop([start, end]), xmlElement) loop = [start] if step != None and steps != None: stepVector = step / endMinusStartLength * endMinusStart end = start + stepVector * steps return getGeometryOutputByStep(end, loop, steps, stepVector, xmlElement) if step == None: stepVector = endMinusStart / steps return getGeometryOutputByStep(end, loop, steps, stepVector, xmlElement) typeString = evaluate.getEvaluatedStringDefault('minimum', 'type', xmlElement) endMinusStartLengthOverStep = endMinusStartLength / step if typeString == 'average': steps = max(1.0, round(endMinusStartLengthOverStep)) stepVector = step / endMinusStartLength * endMinusStart end = start + stepVector * steps return getGeometryOutputByStep(end, loop, steps, stepVector, xmlElement) if typeString == 'maximum': steps = math.ceil(endMinusStartLengthOverStep) if steps < 1.0: return lineation.getGeometryOutputByLoop( lineation.SideLoop([start, end]), xmlElement) stepVector = endMinusStart / steps return getGeometryOutputByStep(end, loop, steps, stepVector, xmlElement) if typeString == 'minimum': steps = math.floor(endMinusStartLengthOverStep) if steps < 1.0: return lineation.getGeometryOutputByLoop(lineation.SideLoop(loop), xmlElement) stepVector = endMinusStart / steps return getGeometryOutputByStep(end, loop, steps, stepVector, xmlElement) print( 'Warning, the step type was not one of (average, maximum or minimum) in getGeometryOutput in line for:' ) print(typeString) print(xmlElement) loop.append(end) return lineation.getGeometryOutputByLoop(lineation.SideLoop(loop), xmlElement)
def __init__(self, elementNode): 'Set defaults.' self.inradius = evaluate.getVector3ByPrefixes(elementNode, ['demisize', 'inradius'], Vector3(1.0, 1.0, 1.0)) self.inradius = evaluate.getVector3ByMultiplierPrefix(elementNode, 2.0, 'size', self.inradius)
def getSegmentPathDefault(): "Get segment path default." return [Vector3(), Vector3(0.0, 1.0)]
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 self.numberOfLines = 1 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 FilamentRadius = repository.FilamentDiameter.value / 2 filamentCrossSectionArea = (FilamentRadius * FilamentRadius) * math.pi extrusionXSection = (( (self.layerThickness + self.perimeterWidth) / 4)**2) * math.pi volumeExtruded = extrusionXSection * self.totalDistanceExtruded / 1000 mass = (volumeExtruded / 1000) * repository.density.value self.delay = (repository.realPrintTime.value - repository.calculatedPrintTime.value ) / repository.totalCommandsEntered.value buildQuadraticVolume = int(extent.x) * int(extent.y) * int(extent.z) self.estimatedBuildTime = ( self.totalDistanceTraveled / self.totalCommandcount / averageFeedRate + ((averageFeedRate * 0.75 / repository.accelerationRate.value) / 2) ) * self.totalCommandcount / 60 # self.delay * self.totalCommandcount + self.totalBuildTime machineTimeCost = repository.machineTime.value * self.estimatedBuildTime / 3600.0 self.filamentInOutRatio = filamentCrossSectionArea / ( (((self.layerThickness + self.perimeterWidth) / 4) * ((self.layerThickness + self.perimeterWidth) / 4) * math.pi)) self.totalDistanceFilament = self.totalDistanceExtruded averageFeedRate = self.totalDistanceTraveled / self.totalBuildTime averageFeedRateEst = self.totalDistanceTraveled / self.estimatedBuildTime materialCost = repository.material.value * mass / 1000 self.addLine(' ') self.addLine("Procedures used (in sequence..") for procedure in self.procedures: self.addLine(procedure) 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('Statistics') self.addLine("Distance traveled is %s m." % euclidean.getThreeSignificantFigures( self.totalDistanceTraveled / 1000)) self.addLine("Distance extruded is %s m." % euclidean.getThreeSignificantFigures( self.totalDistanceExtruded / 1000)) if self.extruderSpeed != 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) self.addLine( "Feed rate average is %s mm/s, (%s mm/min)." % (euclidean.getThreeSignificantFigures(averageFeedRateEst), euclidean.getThreeSignificantFigures(60.0 * averageFeedRateEst))) self.addLine("A Total of %s commands will be executed." % self.totalCommandcount) self.addLine(' ') self.addLine('Time') self.addLine("Calculated Build time is %s." % euclidean.getDurationString(self.totalBuildTime)) self.addLine("Corrected Build time is %s." % euclidean.getDurationString(self.estimatedBuildTime)) self.addLine("Delay is %s seconds per command ." % self.delay) self.addLine(' ') self.addLine('Consumption') self.addLine("Extrusion Cross section area is %s mm2." % euclidean.getThreeSignificantFigures(extrusionXSection)) self.addLine("Mass extruded is %s grams." % euclidean.getThreeSignificantFigures(mass)) self.addLine("Volume extruded is %s cc." % euclidean.getThreeSignificantFigures(volumeExtruded)) self.addLine("Filament used is %s m." % euclidean.getThreeSignificantFigures( self.totalDistanceFilament / 100000)) 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(' ') if self.profileName != None: self.addLine(' ') self.addLine('Profile') self.addLine(self.profileName) self.addLine(' ') self.addLine('Info') self.addLine("Layer thickness is %s mm." % euclidean.getThreeSignificantFigures(self.layerThickness)) self.addLine( "Perimeter width is %s mm." % euclidean.getThreeSignificantFigures(self.absolutePerimeterWidth)) self.addLine( "Filament Cross section area is %s mm2." % euclidean.getThreeSignificantFigures(filamentCrossSectionArea)) self.addLine( 'Filament In / Out ratio is %s' % euclidean.getThreeSignificantFigures(self.filamentInOutRatio)) self.addLine("Text has %s lines and a size of %s KB." % (self.numberOfLines, kilobytes)) self.addLine('') if self.profileName is not None: self.addLine(' ') self.addLine("Profile used to Skein: ") self.addLine(self.profileName) self.addLine(' ') if self.version is not None: self.addLine("You are using SFACT Version " + self.version) self.addLine(' ') return self.output.getvalue()
def getCraftedGcode(self, gcodeText, repository): "Parse gcode text and store the statistics." self.absoluteEdgeWidth = 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.layerHeight = 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) halfEdgeWidth = 0.5 * self.absoluteEdgeWidth halfExtrusionCorner = Vector3(halfEdgeWidth, halfEdgeWidth, halfEdgeWidth) 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 = self.absoluteEdgeWidth * self.layerHeight if self.volumeFraction != None: crossSectionArea *= self.volumeFraction self.extrusionDiameter = math.sqrt(4.0 * crossSectionArea / math.pi) 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 != 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 != 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)) self.addLine( 'Extrusion diameter is %s mm.' % euclidean.getThreeSignificantFigures(self.extrusionDiameter)) if self.volumeFraction != None: self.addLine( 'Volume fraction is %s.' % euclidean.getThreeSignificantFigures(self.volumeFraction)) 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 != None: self.addLine("Version is " + self.version) self.addLine(' ') self.addLine("Procedures") for procedure in self.procedures: self.addLine(procedure) if self.profileName != None: self.addLine(' ') self.addLine('Profile') self.addLine(self.profileName) self.addLine(' ') self.addLine('Slice') self.addLine( "Edge width is %s mm." % euclidean.getThreeSignificantFigures(self.absoluteEdgeWidth)) self.addLine("Layer height is %s mm." % euclidean.getThreeSignificantFigures(self.layerHeight)) self.addLine(' ') return self.output.getvalue()
def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): "Get wedge loop." wedgeCenter = evaluate.getVector3ByPrefix(Vector3(), prefix + 'center', xmlElement) loop.append(wedgeCenter) return [loop]
def getCarvedSVG(self, carving, fileName, repository): "Parse gnu triangulated surface text and store the carved gcode." scale = repository.scale.value rotate = repository.rotate.value / 180 * math.pi scaleX = scale scaleY = scale scaleZ = scale if repository.flipX.value == True: scaleX = -scaleX if repository.flipY.value == True: scaleY = -scaleY if repository.flipZ.value == True: scaleZ = -scaleZ swapXZ = repository.swapXZ.value swapYZ = repository.swapYZ.value mat00 = math.cos(rotate) * scaleX mat01 = -math.sin(rotate) * scaleY mat10 = math.sin(rotate) * scaleX mat11 = math.cos(rotate) * scaleY for i in xrange(0, len(carving.vertexes)): x = carving.vertexes[i].x y = carving.vertexes[i].y z = carving.vertexes[i].z if swapXZ: x, z = z, x if swapYZ: y, z = z, y carving.vertexes[i] = Vector3(x * mat00 + y * mat01, x * mat10 + y * mat11, z * scaleZ) if repository.alternativeCenter.value != '': carving2 = svg_writer.getCarving( repository.alternativeCenter.value) for i in xrange(0, len(carving2.vertexes)): x = carving2.vertexes[i].x y = carving2.vertexes[i].y z = carving2.vertexes[i].z if swapXZ: x, z = z, x if swapYZ: y, z = z, y carving2.vertexes[i] = Vector3(x * mat00 + y * mat01, x * mat10 + y * mat11, z * scaleZ) minZ = carving2.getMinimumZ() minSize = carving2.getCarveCornerMinimum() maxSize = carving2.getCarveCornerMaximum() else: minZ = carving.getMinimumZ() minSize = carving.getCarveCornerMinimum() maxSize = carving.getCarveCornerMaximum() for v in carving.vertexes: v.z -= minZ v.x -= minSize.x + (maxSize.x - minSize.x) / 2 v.y -= minSize.y + (maxSize.y - minSize.y) / 2 v.x += repository.centerX.value v.y += repository.centerY.value layerHeight = repository.layerHeight.value edgeWidth = repository.edgeWidth.value carving.setCarveLayerHeight(layerHeight) importRadius = 0.5 * repository.importCoarseness.value * abs(edgeWidth) carving.setCarveImportRadius(max(importRadius, 0.001 * layerHeight)) carving.setCarveIsCorrectMesh(repository.correctMesh.value) loopLayers = carving.getCarveBoundaryLayers() if len(loopLayers) < 1: print( 'Warning, there are no slices for the model, this could be because the model is too small for the Layer Height.' ) return '' layerHeight = carving.getCarveLayerHeight() decimalPlacesCarried = euclidean.getDecimalPlacesCarried( repository.extraDecimalPlaces.value, layerHeight) edgeWidth = repository.edgeWidth.value svgWriter = svg_writer.SVGWriter( repository.addLayerTemplateToSVG.value, carving.getCarveCornerMaximum(), carving.getCarveCornerMinimum(), decimalPlacesCarried, carving.getCarveLayerHeight(), edgeWidth) truncatedRotatedBoundaryLayers = svg_writer.getTruncatedRotatedBoundaryLayers( loopLayers, repository) return svgWriter.getReplacedSVGTemplate( fileName, truncatedRotatedBoundaryLayers, 'carve', carving.getFabmetheusXML())
def getNestedVectorTestExample(x=0.0, y=0.0, z=0.0): 'Get the NestedVectorTestExample.' return NestedVectorTestExample(Vector3(x, y, z))
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 getVector3(x=0.0, y=0.0, z=0.0): 'Get the vector3.' return Vector3(x, y, z)
def getTransformedVector3Blindly(tetragrid, vector3): 'Get the vector3 multiplied by a tetragrid without checking if the tetragrid exists.' return Vector3(getTransformedByList(tetragrid[0], vector3), getTransformedByList(tetragrid[1], vector3), getTransformedByList(tetragrid[2], vector3))
def getVertexGivenBinary(byteIndex, stlData): "Get vertex given stl vertex line." return Vector3(getFloatGivenBinary(byteIndex, stlData), getFloatGivenBinary(byteIndex + 4, stlData), getFloatGivenBinary(byteIndex + 8, stlData))
def getVector3TransformedByMatrix( matrixTetragrid, vector3 ): "Get the vector3 multiplied by a matrix." return Vector3( getTransformedByList( matrixTetragrid[ 0 ], vector3 ), getTransformedByList( matrixTetragrid[ 1 ], vector3 ), getTransformedByList( matrixTetragrid[ 2 ], vector3 ) )
def getVertexGivenLine(line): "Get vertex given stl vertex line." splitLine = line.split() return Vector3(getFloat(splitLine[1]), getFloat(splitLine[2]), getFloat(splitLine[3]))
def addHopUp(self, location): "Add hop to highest point." locationUp = Vector3( location.x, location.y, self.highestZ ) self.distanceFeedRate.addLine( self.distanceFeedRate.getLinearGcodeMovementWithFeedRate( self.travelFeedRatePerMinute, locationUp.dropAxis(), locationUp.z ) )
def translatePoints(points, prefix, xmlElement): "Translate the points." translateVector3 = matrix.getCumulativeVector3Remove( Vector3(), prefix, xmlElement) if abs(translateVector3) > 0.0: euclidean.translateVector3Path(points, translateVector3)
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 __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 == None: if self.axisEnd == 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 == 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)