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 getTeardropPath(inclination, radius, xmlElement): "Get vector3 teardrop path." teardropSides = evaluate.getSidesMinimumThreeBasedOnPrecision(radius, xmlElement) sideAngle = 2.0 * math.pi / float(teardropSides) overhangAngle = evaluate.getOverhangSupportAngle(xmlElement) overhangPlaneAngle = euclidean.getWiddershinsUnitPolar(overhangAngle) overhangAngle = math.atan2(overhangPlaneAngle.imag, overhangPlaneAngle.real * math.cos(inclination)) tanOverhangAngle = math.tan(overhangAngle) beginAngle = overhangAngle beginMinusEndAngle = math.pi + overhangAngle + overhangAngle 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 = evaluate.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 getTeardropPath(inclination, overhangRadians, overhangSpan, radiusArealized, sides): "Get vector3 teardrop path." sideAngle = 2.0 * math.pi / float(sides) 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 * radiusArealized) beginAngle += withinSideAngle firstPoint = teardropPath[0] if overhangSpan <= 0.0: teardropPath.append( complex(0.0, firstPoint.imag + firstPoint.real / tanOverhangAngle)) else: deltaX = (radiusArealized - firstPoint.imag) * tanOverhangAngle overhangPoint = complex(firstPoint.real - deltaX, radiusArealized) 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 getCumulativeVector3Remove(prefix, vector3, xmlElement): "Get cumulative vector3 and delete the prefixed attributes." cumulativeVector3 = evaluate.getVector3RemoveByPrefix( prefix + 'rectangular', vector3, xmlElement) cylindrical = evaluate.getVector3RemoveByPrefix(prefix + 'cylindrical', Vector3(), xmlElement) if not cylindrical.getIsDefault(): cylindricalComplex = euclidean.getWiddershinsUnitPolar( math.radians(cylindrical.y)) * cylindrical.x cumulativeVector3 += Vector3(cylindricalComplex.real, cylindricalComplex.imag, cylindrical.z) polar = evaluate.getVector3RemoveByPrefix(prefix + 'polar', Vector3(), xmlElement) if not polar.getIsDefault(): polarComplex = euclidean.getWiddershinsUnitPolar(math.radians( polar.y)) * polar.x cumulativeVector3 += Vector3(polarComplex.real, polarComplex.imag) spherical = evaluate.getVector3RemoveByPrefix(prefix + 'spherical', Vector3(), xmlElement) if not spherical.getIsDefault(): radius = spherical.x elevationComplex = euclidean.getWiddershinsUnitPolar( math.radians(spherical.z)) * radius azimuthComplex = euclidean.getWiddershinsUnitPolar( math.radians(spherical.y)) * elevationComplex.real cumulativeVector3 += Vector3(azimuthComplex.real, azimuthComplex.imag, elevationComplex.imag) return cumulativeVector3
def getTeardropPath(inclination, overhangRadians, overhangSpan, radiusArealized, sides): "Get vector3 teardrop path." sideAngle = 2.0 * math.pi / float(sides) 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 * radiusArealized) beginAngle += withinSideAngle firstPoint = teardropPath[0] if overhangSpan <= 0.0: teardropPath.append(complex(0.0, firstPoint.imag + firstPoint.real / tanOverhangAngle)) else: deltaX = (radiusArealized - firstPoint.imag) * tanOverhangAngle overhangPoint = complex(firstPoint.real - deltaX, radiusArealized) 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 getTeardropPath(inclination, radius, xmlElement): "Get vector3 teardrop path." teardropSides = evaluate.getSidesMinimumThreeBasedOnPrecision( radius, xmlElement) sideAngle = 2.0 * math.pi / float(teardropSides) overhangAngle = evaluate.getOverhangSupportAngle(xmlElement) overhangPlaneAngle = euclidean.getWiddershinsUnitPolar(overhangAngle) overhangAngle = math.atan2(overhangPlaneAngle.imag, overhangPlaneAngle.real * math.cos(inclination)) tanOverhangAngle = math.tan(overhangAngle) beginAngle = overhangAngle beginMinusEndAngle = math.pi + overhangAngle + overhangAngle 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 = evaluate.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 equateSpherical(point, returnValue): "Get equation for spherical." spherical = evaluate.getVector3ByFloatList(returnValue, point) radius = spherical.x elevationComplex = euclidean.getWiddershinsUnitPolar(math.radians(spherical.z)) * radius azimuthComplex = euclidean.getWiddershinsUnitPolar(math.radians(spherical.y)) * elevationComplex.real point.x = azimuthComplex.real point.y = azimuthComplex.imag point.z = elevationComplex.imag
def equateSpherical( point, returnValue ): "Get equation for spherical." spherical = evaluate.getVector3ByFloatList( returnValue, point ) radius = spherical.x elevationComplex = euclidean.getWiddershinsUnitPolar( math.radians( spherical.z ) ) * radius azimuthComplex = euclidean.getWiddershinsUnitPolar( math.radians( spherical.y ) ) * elevationComplex.real point.x = azimuthComplex.real point.y = azimuthComplex.imag point.z = elevationComplex.imag
def getArcComplexes(begin, end, largeArcFlag, radius, sweepFlag, xAxisRotation): 'Get the arc complexes, procedure at http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes' xAxisRotationComplex = euclidean.getWiddershinsUnitPolar(xAxisRotation) reverseXAxisRotationComplex = complex(xAxisRotationComplex.real, -xAxisRotationComplex.imag) beginRotated = begin * reverseXAxisRotationComplex beginTransformed = complex(beginRotated.real / radius.real, beginRotated.imag / radius.imag) endRotated = end * reverseXAxisRotationComplex endTransformed = complex(endRotated.real / radius.real, endRotated.imag / radius.imag) midpointTransformed = 0.5 * (beginTransformed + endTransformed) midMinusBeginTransformed = midpointTransformed - beginTransformed midMinusBeginTransformedLength = abs(midMinusBeginTransformed) midWiddershinsTransformed = complex(-midMinusBeginTransformed.imag, midMinusBeginTransformed.real) midWiddershinsLengthSquared = 1.0 - midMinusBeginTransformedLength * midMinusBeginTransformedLength if midWiddershinsLengthSquared < 0.0: print('Warning, the radius is too small for getArcComplexes in svgReader') print(begin) print(end) print(radius) return [] midWiddershinsLength = 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 getArcComplexes(begin, end, largeArcFlag, radius, sweepFlag, xAxisRotation): 'Get the arc complexes, procedure at http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes' xAxisRotationComplex = euclidean.getWiddershinsUnitPolar(xAxisRotation) reverseXAxisRotationComplex = complex(xAxisRotationComplex.real, -xAxisRotationComplex.imag) beginRotated = begin * reverseXAxisRotationComplex beginTransformed = complex(beginRotated.real / radius.real, beginRotated.imag / radius.imag) endRotated = end * reverseXAxisRotationComplex endTransformed = complex(endRotated.real / radius.real, endRotated.imag / radius.imag) midpointTransformed = 0.5 * (beginTransformed + endTransformed) midMinusBeginTransformed = midpointTransformed - beginTransformed midMinusBeginTransformedLength = abs(midMinusBeginTransformed) midWiddershinsTransformed = complex(-midMinusBeginTransformed.imag, midMinusBeginTransformed.real) midWiddershinsLengthSquared = 1.0 - midMinusBeginTransformedLength * midMinusBeginTransformedLength if midWiddershinsLengthSquared < 0.0: print('Warning, the radius is too small for getArcComplexes in svgReader') print(begin) print(end) print(radius) return [] midWiddershinsLength = 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 getLighteningHoles(gearDerivation, pitchRadius, shaftRimRadius, teeth): 'Get cutout circles.' innerRadius = pitchRadius - gearDerivation.dedendum lighteningHoleOuterRadius = innerRadius - gearDerivation.rimWidth shaftRimRadius = max(shaftRimRadius, (lighteningHoleOuterRadius) * (0.5 - math.sqrt(0.1875))) lighteningHoleRadius = 0.5 * (lighteningHoleOuterRadius - shaftRimRadius) if lighteningHoleRadius < gearDerivation.lighteningHoleMinimumRadius: return [] lighteningHoles = [] numberOfLighteningHoles = 3 polygonRadius = lighteningHoleOuterRadius - lighteningHoleRadius rimDemiwidth = 0.5 * gearDerivation.lighteningHoleMargin axialMargin = getAxialMargin(lighteningHoleRadius, numberOfLighteningHoles, polygonRadius) if axialMargin < rimDemiwidth: while axialMargin < rimDemiwidth: lighteningHoleRadius *= 0.999 if lighteningHoleRadius < gearDerivation.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 getToothProfileHalfCylinder(gearDerivation, pitchRadius, teeth): '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 = gearDerivation.tanPressure * gearDerivation.tanPressure + 1.0 b = -gearDerivation.tanPressure - gearDerivation.tanPressure cEnd = gearDerivation.cosPressure * (4.0 - gearDerivation.cosPressure) - 3.0 yEnd = (-b - math.sqrt(b*b - 4 * a * cEnd)) * 0.5 / a yBegin = -1.02 * yEnd beginComplex = complex(1.0 - yBegin * gearDerivation.tanPressure, yBegin) endComplex = complex(1.0 - yEnd * gearDerivation.tanPressure, yEnd) endMinusBeginComplex = endComplex - beginComplex wholeAngle = -abs(endMinusBeginComplex) wholeAngleIncrement = wholeAngle / float(gearDerivation.profileDefinitionSurfaces) stringStartAngle = abs(beginComplex - complex(1.0, 0.0)) wholeDepthIncrementComplex = endMinusBeginComplex / float(gearDerivation.profileDefinitionSurfaces) for profileIndex in xrange(gearDerivation.profileDefinitionSurfaces + 1): contactPoint = beginComplex + wholeDepthIncrementComplex * float(profileIndex) stringAngle = stringStartAngle + wholeAngleIncrement * float(profileIndex) angle = math.atan2(contactPoint.imag, contactPoint.real) - stringAngle angle += 0.5 * math.pi - gearDerivation.quarterWavelength / pitchRadius toothPoint = abs(contactPoint) * euclidean.getWiddershinsUnitPolar(angle) * pitchRadius toothPoint = complex(toothPoint.real * gearDerivation.xToothMultiplier, toothPoint.imag) toothProfile.append(toothPoint) return toothProfile
def createShape(self): "Create the shape." halfHeight = 0.5 * self.height polygonBottom = [] polygonTop = [] imaginaryRadius = self.radiusZ if self.radiusZ == None: imaginaryRadius = self.radiusY sides = max(int(evaluate.getSides(max(imaginaryRadius, self.radiusX), self.xmlElement)), 3) sideAngle = 2.0 * math.pi / float(sides) for side in xrange(sides): angle = float(side) * sideAngle unitComplex = euclidean.getWiddershinsUnitPolar(angle) pointBottom = complex(unitComplex.real * self.radiusX, unitComplex.imag * imaginaryRadius) polygonBottom.append(pointBottom) if self.topOverBottom > 0.0: polygonTop.append(pointBottom * self.topOverBottom) if self.topOverBottom <= 0.0: polygonTop.append(complex()) bottomTopPolygon = [ trianglemesh.getAddIndexedLoop(polygonBottom, self.vertices, -halfHeight), trianglemesh.getAddIndexedLoop(polygonTop, self.vertices, halfHeight), ] trianglemesh.addPillarFromConvexLoops(self.faces, bottomTopPolygon) if self.radiusZ != None: for vertex in self.vertices: oldY = vertex.y vertex.y = vertex.z vertex.z = oldY
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 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 getManipulatedPaths(close, elementNode, loop, prefix, sideLength): "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(elementNode) return [loop] derivation = OverhangDerivation(elementNode, prefix) overhangPlaneAngle = euclidean.getWiddershinsUnitPolar( 0.5 * math.pi - derivation.overhangRadians) if derivation.overhangInclinationRadians != 0.0: overhangInclinationCosine = abs( math.cos(derivation.overhangInclinationRadians)) if overhangInclinationCosine == 0.0: return [loop] imaginaryTimesCosine = overhangPlaneAngle.imag * overhangInclinationCosine overhangPlaneAngle = euclidean.getNormalized( complex(overhangPlaneAngle.real, imaginaryTimesCosine)) alongAway = AlongAway(loop, overhangPlaneAngle) if euclidean.getIsWiddershinsByVector3(loop): alterWiddershinsSupportedPath(alongAway, close) else: alterClockwiseSupportedPath(alongAway, elementNode) return [ euclidean.getLoopWithoutCloseSequentialPoints(close, alongAway.loop) ]
def getGeometryOutput(xmlElement): "Get vector3 vertexes from attribute dictionary." radius = lineation.getRadiusComplex(complex(1.0, 1.0), xmlElement) sides = evaluate.getSidesMinimumThreeBasedOnPrecisionSides(max(radius.real, radius.imag), xmlElement) loop = [] start = evaluate.getEvaluatedFloatZero('start', xmlElement) start = getWrappedFloat(start, 360.0) extent = evaluate.getEvaluatedFloatDefault(360.0 - start, 'extent', xmlElement) end = evaluate.getEvaluatedFloatDefault(start + extent, 'end', xmlElement) end = getWrappedFloat(end, 360.0) revolutions = evaluate.getEvaluatedFloatOne('revolutions', xmlElement) if revolutions > 1: end += 360.0 * (revolutions - 1) angleTotal = math.radians(start) extent = end - start sidesCeiling = int(math.ceil(abs(sides) * extent / 360.0)) sideAngle = math.radians(extent) / sidesCeiling spiral = lineation.Spiral(0.5 * sideAngle / math.pi, xmlElement) for side in xrange(sidesCeiling + (extent != 360.0)): unitPolar = euclidean.getWiddershinsUnitPolar(angleTotal) vertex = spiral.getSpiralPoint(unitPolar, Vector3(unitPolar.real * radius.real, unitPolar.imag * radius.imag)) angleTotal += sideAngle loop.append(vertex) sideLength = sideAngle * lineation.getAverageRadius(radius) lineation.setClosedAttribute(revolutions, xmlElement) return lineation.getGeometryOutputByLoop(lineation.SideLoop(loop, sideAngle, sideLength), xmlElement)
def getGeometryOutput(derivation, xmlElement): "Get vector3 vertexes from attribute dictionary." if derivation == None: derivation = SquareDerivation() derivation.setToXMLElement(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 getGeometryOutput(xmlElement): "Get vector3 vertices from attribute dictionary." radius = complex(1.0, 1.0) radius = lineation.getComplexByPrefixes(['demisize', 'radius'], radius, xmlElement) radius = lineation.getComplexByMultiplierPrefixes(2.0, ['diameter', 'size'], radius, xmlElement) sides = evaluate.getSidesMinimumThree(max(radius.real, radius.imag), xmlElement) sides = evaluate.getEvaluatedFloatDefault(sides, 'sides', xmlElement) loop = [] start = evaluate.getEvaluatedFloatZero('start', xmlElement) start = getWrappedFloat(start, 360.0) extent = evaluate.getEvaluatedFloatDefault(360.0 - start, 'extent', xmlElement) end = evaluate.getEvaluatedFloatDefault(start + extent, 'end', xmlElement) end = getWrappedFloat(end, 360.0) revolutions = evaluate.getEvaluatedFloatOne('revolutions', xmlElement) if revolutions > 1: end += 360.0 * (revolutions - 1) sidesCeiling = int(math.ceil(abs(sides) * extent / 360.0)) sideAngle = math.radians(extent) / sidesCeiling startAngle = math.radians(start) for side in xrange(sidesCeiling + (extent != 360.0)): angle = float(side) * sideAngle + startAngle point = euclidean.getWiddershinsUnitPolar(angle) vertex = Vector3(point.real * radius.real, point.imag * radius.imag) loop.append(vertex) sideLength = sideAngle * lineation.getAverageRadius(radius) return lineation.getGeometryOutputByLoop(lineation.SideLoop(loop, sideAngle, sideLength), 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 getGeometryOutput(xmlElement): "Get vector3 vertices from attribute dictionary." if '_arguments' in xmlElement.attributeDictionary: arguments = xmlElement.attributeDictionary['_arguments'] if len(arguments) > 0: xmlElement.attributeDictionary['sides'] = arguments[0] sides = evaluate.getEvaluatedFloatDefault(4.0, 'sides', xmlElement) sideAngle = 2.0 * math.pi / float(sides) radiusXY = evaluate.RadiusXY().getByRadius( getRadiusFromXMLElement(sideAngle, xmlElement), xmlElement) loop = [] sidesCeiling = int(math.ceil(abs(sides))) start = evaluate.getEvaluatedIntZero('start', xmlElement) start = getWrappedInteger(start, sidesCeiling) extent = evaluate.getEvaluatedIntDefault(sidesCeiling - start, 'extent', xmlElement) end = evaluate.getEvaluatedIntDefault(start + extent, 'end', xmlElement) end = getWrappedInteger(end, sidesCeiling) for side in xrange(start, min(end, sidesCeiling)): angle = float(side) * sideAngle point = euclidean.getWiddershinsUnitPolar(angle) vertex = Vector3(point.real * radiusXY.radiusX, point.imag * radiusXY.radiusY) loop.append(vertex) sideLength = sideAngle * radiusXY.radius return lineation.getGeometryOutputByLoop( None, lineation.SideLoop(loop, sideAngle, sideLength), xmlElement)
def createShape( self ): "Create the shape." halfHeight = 0.5 * self.height polygonBottom = [] polygonTop = [] imaginaryRadius = self.radiusZ if self.radiusZ == None: imaginaryRadius = self.radiusY sides = max( int( evaluate.getSides( max( imaginaryRadius, self.radiusX ), self.xmlElement ) ), 3 ) sideAngle = 2.0 * math.pi / float( sides ) for side in xrange( sides ): angle = float( side ) * sideAngle unitComplex = euclidean.getWiddershinsUnitPolar( angle ) pointBottom = complex( unitComplex.real * self.radiusX, unitComplex.imag * imaginaryRadius ) polygonBottom.append( pointBottom ) if self.topOverBottom > 0.0: polygonTop.append( pointBottom * self.topOverBottom ) if self.topOverBottom <= 0.0: polygonTop.append( complex() ) bottomTopPolygon = [ trianglemesh.getAddIndexedLoop( polygonBottom, self.vertices, - halfHeight ), trianglemesh.getAddIndexedLoop( polygonTop, self.vertices, halfHeight ) ] trianglemesh.addPillarFromConvexLoops( self.faces, bottomTopPolygon ) if self.radiusZ != None: for vertex in self.vertices: oldY = vertex.y vertex.y = vertex.z vertex.z = oldY
def equateCylindrical(point, returnValue): "Get equation for cylindrical." point = evaluate.getVector3ByFloatList(returnValue, point) azimuthComplex = euclidean.getWiddershinsUnitPolar(math.radians( point.y)) * point.x point.x = azimuthComplex.real point.y = azimuthComplex.imag
def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): "Get path with overhangs removed or filled in." if len(loop) < 3: return [loop] if not evaluate.getEvaluatedBooleanDefault(True, prefix + 'activate', xmlElement): return [loop] overhangAngle = evaluate.getOverhangSupportAngle(xmlElement) overhangPlaneAngle = euclidean.getWiddershinsUnitPolar(0.5 * math.pi - overhangAngle) overhangVerticalAngle = math.radians( evaluate.getEvaluatedFloatDefault(0.0, prefix + 'inclination', xmlElement)) if overhangVerticalAngle != 0.0: overhangVerticalCosine = abs(math.cos(overhangVerticalAngle)) 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 getToothProfileCylinder(gearDerivation, pitchRadius, teeth): 'Get profile for one tooth of a cylindrical gear.' toothProfile = getToothProfileHalfCylinder(gearDerivation, pitchRadius, teeth) profileFirst = toothProfile[0] profileSecond = toothProfile[1] firstMinusSecond = profileFirst - profileSecond remainingDedendum = abs( profileFirst) - pitchRadius + gearDerivation.dedendum firstMinusSecond *= remainingDedendum / abs(firstMinusSecond) extensionPoint = profileFirst + firstMinusSecond if gearDerivation.bevel <= 0.0: toothProfile.insert(0, extensionPoint) return getMirrorPath(toothProfile) unitPolar = euclidean.getWiddershinsUnitPolar(-2.0 / float(teeth) * math.pi) mirrorExtensionPoint = complex(-extensionPoint.real, extensionPoint.imag) * unitPolar mirrorMinusExtension = euclidean.getNormalized(mirrorExtensionPoint - extensionPoint) if remainingDedendum <= gearDerivation.bevel: toothProfile.insert( 0, complex(extensionPoint.real, extensionPoint.imag) + remainingDedendum * mirrorMinusExtension) return getMirrorPath(toothProfile) firstMinusSecond *= (remainingDedendum - gearDerivation.bevel) / abs(firstMinusSecond) toothProfile.insert(0, profileFirst + firstMinusSecond) toothProfile.insert( 0, complex(extensionPoint.real, extensionPoint.imag) + gearDerivation.bevel * mirrorMinusExtension) return getMirrorPath(toothProfile)
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 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 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) 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 moveCircle(self, derivation, otherCircles, overlapArealRatio): '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(attemptCenter, derivation, searchCircles, overlapArealRatio) if radius > greatestRadius: greatestRadius = radius movedCenter = attemptCenter self.center = movedCenter self.radius = greatestRadius
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 getManipulatedPaths(close, loop, prefix, xmlElement): "Get path with overhangs removed or filled in." if len(loop) < 3: return [loop] overhangAngle = math.radians( xmlElement.getCascadeFloat(45.0, 'overhangangle')) overhangPlaneAngle = euclidean.getWiddershinsUnitPolar(0.5 * math.pi - overhangAngle) overhangVerticalAngle = math.radians( evaluate.getEvaluatedFloatZero(prefix + 'verticalangle', xmlElement)) if overhangVerticalAngle != 0.0: overhangVerticalCosine = abs(math.cos(overhangVerticalAngle)) 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 getGeometryOutput(derivation, elementNode): "Get vector3 vertexes from attribute dictionary." if derivation is None: derivation = SquareDerivation(elementNode) 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(elementNode, derivation.revolutions) 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( elementNode, lineation.SideLoop(loop, 0.5 * math.pi))
def getGeometryOutput(xmlElement): "Get vector3 vertexes from attribute dictionary." inradius = lineation.getComplexByPrefixes(['demisize', 'inradius'], complex(1.0, 1.0), xmlElement) inradius = lineation.getComplexByMultiplierPrefix(2.0, 'size', inradius, xmlElement) demiwidth = lineation.getFloatByPrefixBeginEnd('demiwidth', 'width', inradius.real, xmlElement) demiheight = lineation.getFloatByPrefixBeginEnd('demiheight', 'height', inradius.imag, xmlElement) bottomDemiwidth = lineation.getFloatByPrefixBeginEnd('bottomdemiwidth', 'bottomwidth', demiwidth, xmlElement) topDemiwidth = lineation.getFloatByPrefixBeginEnd('topdemiwidth', 'topwidth', demiwidth, xmlElement) interiorAngle = evaluate.getEvaluatedFloatDefault(90.0, 'interiorangle', xmlElement) topRight = complex(topDemiwidth, demiheight) topLeft = complex(-topDemiwidth, demiheight) bottomLeft = complex(-bottomDemiwidth, -demiheight) bottomRight = complex(bottomDemiwidth, -demiheight) if interiorAngle != 90.0: interiorPlaneAngle = euclidean.getWiddershinsUnitPolar(math.radians(interiorAngle - 90.0)) topRight = (topRight - bottomRight) * interiorPlaneAngle + bottomRight topLeft = (topLeft - bottomLeft) * interiorPlaneAngle + bottomLeft revolutions = evaluate.getEvaluatedIntOne('revolutions', xmlElement) lineation.setClosedAttribute(revolutions, xmlElement) complexLoop = [topRight, topLeft, bottomLeft, bottomRight] originalLoop = complexLoop[:] for revolution in xrange(1, revolutions): complexLoop += originalLoop spiral = lineation.Spiral(0.25, xmlElement) 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 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 getGeometryOutput(derivation, elementNode): "Get vector3 vertexes from attribute dictionary." if derivation == None: derivation = CircleDerivation(elementNode) 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.radiusArealized.real y = unitPolar.imag * derivation.radiusArealized.imag vertex = spiral.getSpiralPoint(unitPolar, Vector3(x, y)) angleTotal += sideAngle loop.append(vertex) radiusMaximum = 0.000001 * max(derivation.radiusArealized.real, derivation.radiusArealized.imag) loop = euclidean.getLoopWithoutCloseEnds(radiusMaximum, loop) lineation.setClosedAttribute(elementNode, derivation.revolutions) return lineation.getGeometryOutputByLoop( elementNode, lineation.SideLoop(loop, sideAngle))
def getRadialPath(begin, center, end, path): "Get radial path." beginComplex = begin.dropAxis() endComplex = end.dropAxis() centerComplex = center.dropAxis() beginMinusCenterComplex = beginComplex - centerComplex endMinusCenterComplex = endComplex - centerComplex 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 = center + Vector3(radialComplex.real, radialComplex.imag, point.z) radialPath.append(polygonPoint) return radialPath
def getDiagonalSwitchedMatrix( angle, diagonals ): "Get the diagonals and switched matrix.math." unitPolar = euclidean.getWiddershinsUnitPolar( math.radians( angle ) ) newMatrixTetragrid = getIdentityMatrixTetragrid() setDiagonalElements( diagonals, newMatrixTetragrid, unitPolar.real ) newMatrixTetragrid[ diagonals[ 0 ] ][ diagonals[ 1 ] ] = - unitPolar.imag newMatrixTetragrid[ diagonals[ 1 ] ][ diagonals[ 0 ] ] = unitPolar.imag return Matrix4X4( newMatrixTetragrid )
def getLayerRotation(self, layerIndex, rotatedLayer): 'Get the layer rotation.' rotation = rotatedLayer.bridgeRotation if rotation != None: return rotation infillOddLayerRotationMultiplier = float(layerIndex % (self.infillBeginRotationRepeat + 1) == self.infillBeginRotationRepeat) layerAngle = self.infillBeginRotation + infillOddLayerRotationMultiplier * self.infillOddLayerExtraRotation return euclidean.getWiddershinsUnitPolar(layerAngle)
def getCumulativeVector3Remove(prefix, vector3, xmlElement): "Get cumulative vector3 and delete the prefixed attributes." cumulativeVector3 = evaluate.getVector3RemoveByPrefix(prefix + 'rectangular', vector3, xmlElement) cylindrical = evaluate.getVector3RemoveByPrefix(prefix + 'cylindrical', Vector3(), xmlElement) if not cylindrical.getIsDefault(): cylindricalComplex = euclidean.getWiddershinsUnitPolar(math.radians(cylindrical.y)) * cylindrical.x cumulativeVector3 += Vector3(cylindricalComplex.real, cylindricalComplex.imag, cylindrical.z) polar = evaluate.getVector3RemoveByPrefix(prefix + 'polar', Vector3(), xmlElement) if not polar.getIsDefault(): polarComplex = euclidean.getWiddershinsUnitPolar(math.radians(polar.y)) * polar.x cumulativeVector3 += Vector3(polarComplex.real, polarComplex.imag) spherical = evaluate.getVector3RemoveByPrefix(prefix + 'spherical', Vector3(), xmlElement) if not spherical.getIsDefault(): radius = spherical.x elevationComplex = euclidean.getWiddershinsUnitPolar(math.radians(spherical.z)) * radius azimuthComplex = euclidean.getWiddershinsUnitPolar(math.radians(spherical.y)) * elevationComplex.real cumulativeVector3 += Vector3(azimuthComplex.real, azimuthComplex.imag, elevationComplex.imag) return cumulativeVector3
def getDiagonalSwitchedTetragrid(angleDegrees, diagonals): "Get the diagonals and switched matrix." unitPolar = euclidean.getWiddershinsUnitPolar(math.radians(angleDegrees)) diagonalSwitchedTetragrid = getIdentityMatrixTetragrid() 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 getDiagonalSwitchedTetragrid(angleDegrees, diagonals): "Get the diagonals and switched matrix." unitPolar = euclidean.getWiddershinsUnitPolar(math.radians(angleDegrees)) diagonalSwitchedTetragrid = getIdentityMatrixTetragrid() 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 getGearProfileCylinder(teeth, toothProfile): 'Get gear profile.' gearProfile = [] toothAngleRadian = 2.0 * math.pi / float(teeth) totalToothAngle = 0.0 for toothIndex in xrange(teeth): for toothPoint in toothProfile: gearProfile.append(toothPoint * euclidean.getWiddershinsUnitPolar(totalToothAngle)) totalToothAngle += toothAngleRadian return gearProfile
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 getLayerRotation(self, layerIndex, rotatedLayer): 'Get the layer rotation.' rotation = rotatedLayer.bridgeRotation if rotation != None: return rotation infillOddLayerRotationMultiplier = float( layerIndex % (self.infillBeginRotationRepeat + 1) == self.infillBeginRotationRepeat) layerAngle = self.infillBeginRotation + infillOddLayerRotationMultiplier * self.infillOddLayerExtraRotation return euclidean.getWiddershinsUnitPolar(layerAngle)
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 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 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 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 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 equateSphericalDotElevation(point, returnValue): "Get equation for spherical elevation." radius = abs(point) if radius <= 0.0: return azimuthComplex = point.dropAxis() azimuthRadius = abs(azimuthComplex) if azimuthRadius <= 0.0: return elevationComplex = euclidean.getWiddershinsUnitPolar(math.radians(returnValue)) azimuthComplex *= radius / azimuthRadius * elevationComplex.real point.x = azimuthComplex.real point.y = azimuthComplex.imag point.z = elevationComplex.imag * radius
def rotate(self, elementNode): 'Rotate.' rotation = math.radians(evaluate.getEvaluatedFloat(0.0, elementNode, 'rotation')) rotation += evaluate.getEvaluatedFloat(0.0, elementNode, 'rotationOverSide') * 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 elementNode.attributes: isClockwise = euclidean.getBooleanFromValue(evaluate.getEvaluatedValueObliviously(elementNode, 'clockwise')) if isClockwise == euclidean.getIsWiddershinsByVector3( self.loop ): self.loop.reverse()
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) lineation.setClosedAttribute(elementNode, derivation.revolutions) return lineation.getGeometryOutputByLoop(elementNode, lineation.SideLoop(loop, derivation.sideAngle))
def rotate(self, xmlElement): "Rotate." rotation = math.radians( evaluate.getEvaluatedFloatDefault(0.0, 'rotation', xmlElement ) ) rotation += evaluate.getEvaluatedFloatDefault(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()
def getGeometryOutput(derivation, xmlElement): "Get vector3 vertexes from attribute dictionary." if derivation == None: derivation = PolygonDerivation() derivation.setToXMLElement(xmlElement) loop = [] spiral = lineation.Spiral(derivation.spiral, 0.5 * derivation.sideAngle / math.pi) for side in xrange(derivation.start, derivation.end): 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) sideLength = derivation.sideAngle * lineation.getRadiusAverage(derivation.radius) lineation.setClosedAttribute(derivation.revolutions, xmlElement) return lineation.getGeometryOutputByLoop(lineation.SideLoop(loop, derivation.sideAngle, sideLength), xmlElement)
def helicalMove(self, isCounterclockwise, splitLine): "Get statistics for a helical move." if self.oldLocation == None: return location = self.getLocationSetFeedRateToSplitLine(splitLine) location += self.oldLocation center = self.oldLocation.copy() indexOfR = gcodec.indexOfStartingWithSecond("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 processSVGElementcircle( elementNode, svgReader ): "Process elementNode by svgReader." attributes = elementNode.attributes center = euclidean.getComplexDefaultByDictionaryKeys( complex(), attributes, 'cx', 'cy') radius = euclidean.getFloatDefaultByDictionary( 0.0, attributes, 'r') if radius == 0.0: print('Warning, in processSVGElementcircle in svgReader radius is zero in:') print(attributes) return global globalNumberOfCirclePoints global globalSideAngle loop = [] loopLayer = svgReader.getLoopLayer() for side in xrange( globalNumberOfCirclePoints ): unitPolar = euclidean.getWiddershinsUnitPolar( float(side) * globalSideAngle ) loop.append( center + radius * unitPolar ) loopLayer.loops += getTransformedFillOutline(elementNode, loop, svgReader.yAxisPointingUpward)
def centerRotate( self, xmlElement ): "Add a wedge center and rotate." wedgeCenter = evaluate.getVector3ByKey( 'wedgecenter', None, xmlElement ) if wedgeCenter != None: self.loop.append( wedgeCenter ) rotation = math.radians( evaluate.getEvaluatedFloatZero( 'rotation', xmlElement ) ) rotation += evaluate.getEvaluatedFloatZero( '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()
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 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)