Torus Knot#
Torus Knot Coord
from pynodes import *
from pynodes.math import *
@tree
def torus_knot_coord(Φ: Float, p: Integer, q: Integer):
# The name of the function decorated by the decorator is treated as the name of the node tree
r = cos(q * Φ) + 2
x = r * cos(p * Φ)
y = r * sin(p * Φ)
z = -sin(q * Φ)
return CombineXYZ(x, y, z)
Torus Knot Curve
@tree
def torus_knot_curve(
p: Integer = 2,
q: Integer = 3,
# End factor for trim curve (name, default, min, max)
e: Float = ("End", 1, 0, 1),
# The larger the value, the smoother the curve (name, default))
n: Integer = ("Sample", 128)
):
# Create a primitive curve circle node and assign the geometry of the output socket to `curve`
curve = CurveCircle(resolution=n)
# Call the node tree defined above as a function
pos = torus_knot_coord(curve.parameter.factor * 2 * pi, p, q)
# Use the obtained coordinates to set the position of the curve,
# and then create a trim curve node to trim the curve by the end factor.
curve = curve.set_position(position=pos).trim_factor(end=e)
# Create a frame, pass in the label of the frame.
with frame("Deal with the connection of endpoints problem"):
# All nodes created in the scope of the with statement will embeded in this frame
curve = curve.to_mesh().merge_by_distance().to_curve()
# The above operation is actually to align the normal lines
# at the beginning and end of the curve, so that when the mesh
# surface is generated later, it will not break
return curve
Version with material
@tree
def torus_knot_mesh(
p: Integer = 3,
q: Integer = 7,
e: Float = ("End", 1, 0, 1),
n: Integer = ("Sample", 256),
# The radius of the profile curve circle
r: Float = ("Profile Radius", 0.3)
):
# Call the node tree defined above
curve = torus_knot_curve(p, q, e, n)
# Store the parameter factor of the curve for shading
curve.store_named_attribute("factor", curve.parameter.factor)
# Sweep the curve to mesh with a profile curve
mesh = curve.to_mesh(CurveCircle(radius=r))
# return mesh
# Optional: set the shade smooth and set the material
return mesh.set_shade_smooth().set_material("Torus Knot")
@tree
def torus_knot():
"""@Material"""
shader = BsdfPrincipled()
factor = Shader.attribute(name="factor").fac
color = GradientTexture(vector=factor).color
color = color.mix("#117f0f")
shader['Base Color'] = color
return shader