Updated build script to create win32/linux/macos versions. Fixed the defaults to they work with PLA. Fixed the temperature plugin default "ON" problem. Removed all profiles except for PLA.
259 lines
12 KiB
Python
259 lines
12 KiB
Python
"""
|
|
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 <http://www.artofillusion.org/>'
|
|
__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.elementNode.getCopyShallow()
|
|
extrude.setElementNodeToEndStart(copyShallow, Vector3(-derivation.demilength), Vector3(derivation.demilength))
|
|
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.pegRadiusArealized, derivation.pegRadiusArealized)
|
|
pegTip = 0.8 * derivation.pegRadiusArealized
|
|
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.socketRadiusArealized, derivation.socketRadiusArealized)
|
|
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.elementNode.getCopyShallow()
|
|
copyShallow.attributes['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(elementNode):
|
|
'Get vector3 vertexes from attribute dictionary.'
|
|
derivation = MechaslabDerivation(elementNode)
|
|
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(elementNode, negatives, positives)
|
|
|
|
def getGeometryOutputByArguments(arguments, elementNode):
|
|
'Get vector3 vertexes from attribute dictionary by arguments.'
|
|
evaluate.setAttributesByArguments(['length', 'radius'], arguments, elementNode)
|
|
return getGeometryOutput(elementNode)
|
|
|
|
def getNewDerivation(elementNode):
|
|
'Get new derivation.'
|
|
return MechaslabDerivation(elementNode)
|
|
|
|
def processElementNode(elementNode):
|
|
'Process the xml element.'
|
|
solid.processElementNodeByGeometry(elementNode, getGeometryOutput(elementNode))
|
|
|
|
|
|
class CellExistence:
|
|
'Class to determine if a cell exists.'
|
|
def __init__(self, columns, rows, value):
|
|
'Initialize.'
|
|
self.existenceSet = None
|
|
if value == 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 == 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, elementNode):
|
|
'Set defaults.'
|
|
self.bevelOverRadius = evaluate.getEvaluatedFloat(0.2, elementNode, 'bevelOverRadius')
|
|
self.boltRadiusOverRadius = evaluate.getEvaluatedFloat(0.0, elementNode, 'boltRadiusOverRadius')
|
|
self.columns = evaluate.getEvaluatedInt(2, elementNode, 'columns')
|
|
self.elementNode = elementNode
|
|
self.heightOverRadius = evaluate.getEvaluatedFloat(2.0, elementNode, 'heightOverRadius')
|
|
self.interiorOverhangRadians = setting.getInteriorOverhangRadians(elementNode)
|
|
self.overhangSpan = setting.getOverhangSpan(elementNode)
|
|
self.pegClearanceOverRadius = evaluate.getEvaluatedFloat(0.0, elementNode, 'pegClearanceOverRadius')
|
|
self.pegRadians = math.radians(evaluate.getEvaluatedFloat(2.0, elementNode, 'pegAngle'))
|
|
self.pegHeightOverHeight = evaluate.getEvaluatedFloat(0.4, elementNode, 'pegHeightOverHeight')
|
|
self.pegRadiusOverRadius = evaluate.getEvaluatedFloat(0.7, elementNode, 'pegRadiusOverRadius')
|
|
self.radius = lineation.getFloatByPrefixBeginEnd(elementNode, 'radius', 'width', 5.0)
|
|
self.rows = evaluate.getEvaluatedInt(1, elementNode, 'rows')
|
|
self.topBevelOverRadius = evaluate.getEvaluatedFloat(0.2, elementNode, 'topBevelOverRadius')
|
|
# Set derived values.
|
|
self.bevel = evaluate.getEvaluatedFloat(self.bevelOverRadius * self.radius, elementNode, 'bevel')
|
|
self.boltRadius = evaluate.getEvaluatedFloat(self.boltRadiusOverRadius * self.radius, elementNode, 'boltRadius')
|
|
self.boltSides = evaluate.getSidesMinimumThreeBasedOnPrecision(elementNode, self.boltRadius)
|
|
self.bottomLeftCenter = complex(-float(self.columns - 1), -float(self.rows - 1)) * self.radius
|
|
self.height = evaluate.getEvaluatedFloat(self.heightOverRadius * self.radius, elementNode, 'height')
|
|
self.hollowPegSockets = []
|
|
centerY = self.bottomLeftCenter.imag
|
|
diameter = self.radius + self.radius
|
|
self.pegExistence = CellExistence(self.columns, self.rows, evaluate.getEvaluatedValue(None, elementNode, 'pegs'))
|
|
self.socketExistence = CellExistence(self.columns, self.rows, evaluate.getEvaluatedValue(None, elementNode, 'sockets'))
|
|
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, elementNode, 'pegClearance')
|
|
halfPegClearance = 0.5 * self.pegClearance
|
|
self.pegHeight = evaluate.getEvaluatedFloat(self.pegHeightOverHeight * self.height, elementNode, 'pegHeight')
|
|
self.pegRadius = evaluate.getEvaluatedFloat(self.pegRadiusOverRadius * self.radius, elementNode, 'pegRadius')
|
|
sides = 24 * max(1, math.floor(evaluate.getSidesBasedOnPrecision(elementNode, self.pegRadius) / 24))
|
|
self.socketRadius = self.pegRadius + halfPegClearance
|
|
self.pegSides = evaluate.getEvaluatedInt(sides, elementNode, 'pegSides')
|
|
self.pegRadius -= halfPegClearance
|
|
self.pegRadiusArealized = evaluate.getRadiusArealizedBasedOnAreaRadius(elementNode, self.pegRadius, self.pegSides)
|
|
self.socketSides = evaluate.getEvaluatedInt(sides, elementNode, 'socketSides')
|
|
self.socketRadiusArealized = evaluate.getRadiusArealizedBasedOnAreaRadius(elementNode, self.socketRadius, self.socketSides)
|
|
self.topBevel = evaluate.getEvaluatedFloat(self.topBevelOverRadius * self.radius, elementNode, 'topBevel')
|
|
self.topBevelPositions = evaluate.getEvaluatedString('nwse', elementNode, 'topBevelPositions').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__)
|