MrDraw/SkeinPyPy_NewUI/fabmetheus_utilities/geometry/manipulation_paths/round.py
Daid a414a80837 Adding SkeinPyPy_NewUI as development for a brand new user interface.
Experimental, doesn't slice yet, loads of work ahead.
2012-02-20 00:30:49 +01:00

94 lines
4.3 KiB
Python

"""
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 <http://www.artofillusion.org/>'
__date__ = '$Date: 2008/02/05 $'
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
globalExecutionOrder = 40
def getManipulatedPaths(close, elementNode, loop, prefix, sideLength):
"Get round loop."
if len(loop) < 3:
return [loop]
derivation = RoundDerivation(elementNode, prefix, sideLength)
if derivation.radius == 0.0:
return loop
roundLoop = []
sidesPerRadian = 0.5 / math.pi * evaluate.getSidesMinimumThreeBasedOnPrecision(elementNode, sideLength)
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, derivation.radius, sidesPerRadian)
return [euclidean.getLoopWithoutCloseSequentialPoints(close, roundLoop)]
def getNewDerivation(elementNode, prefix, sideLength):
'Get new derivation.'
return RoundDerivation(elementNode, prefix, sideLength)
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 processElementNode(elementNode):
"Process the xml element."
lineation.processElementNodeByFunction(elementNode, getManipulatedPaths)
class RoundDerivation:
"Class to hold round variables."
def __init__(self, elementNode, prefix, sideLength):
'Set defaults.'
self.radius = lineation.getFloatByPrefixSide(0.0, elementNode, prefix + 'radius', sideLength)