Index
Base.convertBase.convertLuxor.betweenLuxor.betweenLuxor.distanceLuxor.distanceLuxor.drawpathLuxor.midpointLuxor.midpointThebes.anglebetweenvectorsThebes.anglebetweenvectorsThebes.axes3DThebes.axes3DThebes.carpetThebes.carpetThebes.cartesiantosphericalThebes.cartesiantosphericalThebes.cartesiantosphericalThebes.centerpointThebes.crossproduct3DThebes.crossproduct3DThebes.dotproduct3DThebes.dotproduct3DThebes.drawcubeThebes.drawcubeThebes.eyepointThebes.faceThebes.helloworldThebes.hiddensurfaceThebes.import_off_fileThebes.magnitudeThebes.magnitudeThebes.makeThebes.movebyThebes.movebyThebes.movebyThebes.moveby!Thebes.moveby!Thebes.moveby!Thebes.newprojectionThebes.objecttopolyThebes.perspectiveThebes.pinThebes.pinThebes.pinThebes.pinThebes.pointsperpendicularThebes.pointsperpendicularThebes.projectThebes.rotateXThebes.rotateXThebes.rotateYThebes.rotateYThebes.rotateZThebes.rotateZThebes.rotatebyThebes.rotatebyThebes.rotatebyThebes.rotatebyThebes.rotatebyThebes.rotateby!Thebes.rotateby!Thebes.rotateby!Thebes.rotateby!Thebes.rotateby!Thebes.scaleby!Thebes.scaleby!Thebes.scaleby!Thebes.scaleby!Thebes.sortfaces!Thebes.sphericaltocartesianThebes.sphericaltocartesianThebes.sphericaltocartesianThebes.surfacenormalThebes.surfacenormalThebes.text3DThebes.text3DThebes.uppointThebes.uppointThebes.wireframe
Base.convert — Methodconvert(Point3D, pt::Point, z)Convert pt to a Point3D(pt.x, pt.y, z).
Base.convert — Methodconvert(Point3D, pt::Point)Convert pt to a Point3D(pt.x, pt.y, 0).
Luxor.between — Functionbetween(p1::Point3D, p2::Point3D, x=0.5)
between((p1::Point3D, p2::Point3D), x=0.5)Find a point on a line between two 3D points. If x is 0.5, the returned point should be halfway between them.
Luxor.distance — Methoddistance(p1::Point3D, p2::Point3D)Return the distance between two points.
Luxor.drawpath — Methoddrawpath(path::Path, k::Real, anchor::Point3D;
about=Point3D(0., 0., 0.),
rotation::Rotation=RotXYZ(0, 0, 0),
steps=20, # used when approximating Bezier curve segments
action=:none,
startnewpath=true,
pathlength = 0.0)Draw a Luxor Path object on a 2D plane, starting at anchor with rotation about about.
Luxor.midpoint — Methodmidpoint(pt1::Point3D, pt2::Point3D)Find the midpoint between two points. See also between().
Thebes.anglebetweenvectors — Methodanglebetweenvectors(v1::Point3D, v2::Point3D)Calclate the angle between two vectors.
Thebes.axes3D — Functionaxes3D(n=100)Draw labelled 3D axes at (0, 0, 0) with length n.
Thebes.carpet — Functioncarpet(n; kind=:circular)Draw a circular carpet centered at the origin, using current Luxor parameters.
If kind is not :circular, the carpet will be a square.
Points that can't be rendered are not included in the final shape.
Thebes.cartesiantospherical — Methodcartesiantospherical(x, y, z)Return (ρ, θ, ϕ) (radius, longitude, colatitude) of the Point3D(x, y, z).
Thebes.cartesiantospherical — Methodcartesiantospherical(pt::Point3D)Return (ρ, θ, ϕ) (radius, longitude, colatitude) of pt.
Thebes.centerpoint — Methodcenterpoint()
centerpoint(pt::Point3D)Get or set the current center position.
Thebes.crossproduct3D — Methodcrossproduct3D(A::Point3D, B::Point3D)Find one of these.
Thebes.dotproduct3D — Methoddotproduct3D(a::Point3D, b::Point3D)Finds the dot product of a and b
Thebes.drawcube — Functiondrawcube(n=10, action=:stroke)Draw a cube. drawcube(1) draws a wireframe unit cube.
Thebes.eyepoint — Methodeyepoint()
eyepoint(pt::Point3D)Get or set the current eye position.
Thebes.face — Methodface(o::Object, n)Thebes.helloworld — Methodhelloworld()Reset all the things. The equivalent of typing:
eyepoint(100, 100, 100)
centerpoint(0, 0, 0)
uppoint(0, 0, 10)
perspective(0)hiddensurface(o::Object)Given an object o, sort the faces in o.faces, then draw filled grey polygons for each face.
Thebes.import_off_file — Methodimport_off_file(fname)Import a file in OFF (Object File Format).
Returns a Tuple - vertices, and faces. Vertices is a vector of [x, y, z], and faces a vector of vectors of vertex numbers.
off_file = raw"
OFF
8 6 0
-0.500000 -0.500000 0.500000
0.500000 -0.500000 0.500000
-0.500000 0.500000 0.500000
0.500000 0.500000 0.500000
-0.500000 0.500000 -0.500000
0.500000 0.500000 -0.500000
-0.500000 -0.500000 -0.500000
0.500000 -0.500000 -0.500000
4 0 1 3 2
4 2 3 5 4
4 4 5 7 6
4 6 7 1 0
4 1 7 5 3
4 6 0 2 4
"
f = open("/tmp/cube.off", "w") do f
write(f, off_file)
end
@draw begin
o = make(import_off_file("/tmp/cube.off"))
scaleby!(o, 100)
pin(o)
endThebes.magnitude — Methodmagnitude(a::Point3D)Calculates magnitude of a.
Thebes.make — Functionmake(primitive, name="unnamed")primitive contains two arrays, an array of 3D points, and an array of faces, where each face is a list of vertex numbers.
Returns a Object.
Example
make(Cube, "cube")returns an Object object containing an array of vertices, an array of faces, and an array of labels.
@draw begin
helloworld()
tol = 0.01
a = []
sethue("black")
for t in -2pi:tol:2pi
push!(a, Point3D((50 + cos(5t)) * cos(3t), (50 + cos(5t)) * sin(2t), sin(5t)))
end
Knot = make((a, []), "knot")
pin(Knot, gfunction=(args...) -> begin
for verts in args[1].vertices
pin(verts)
end
end)
endThe default gfunction expects faces - if there aren't any, use a gfunction that draws vertices.
Thebes.moveby! — Methodmoveby!(o::Object, x, y, z)
moveby!(o::Object, pt::Point3D)Set the position of object to Point3D(x, y, z).
Thebes.moveby! — Methodmoveby!(ptlist::Point3D, x, y, z)
moveby!(ptlist::Point3D, pt::Point3D)Move all points in the list by a vector.
Thebes.moveby — Methodmoveby(o::Object, x, y, z)
moveby(o::Object, pt::Point3D)Set the position of a copy of the object to Point3D(x, y, z).
Thebes.moveby — Methodmoveby(pt::Point3D, d::Point3D)Return a new point that's the result of moving a point pt by a vector d.
Thebes.newprojection — Functionnewprojection(ipos::Point3D, center::Point3D, up::Point3D, perspective=0.0)
Define a new Projection:
- ipos is the eye position
- center is the 3D point to appear in the center of the 2D image
- up is a point that is to appear vertically above the center
If perspective is 0.0 (the default) the projection is parallel. Otherwise it's a vague magnification factor for perspective projections.
The three vectors U, V, W, and the three scalar products, ue, ve, and we:
- U is at right angles to line of sight w, and to t-e, so it corresponds to
the x axis of the 2D image
- V is at right angles to u and to the line of sight, so it's the y axis of the
2D image
W is the line of sight
we is the projection of the eye position onto w
ue is the projection of the eye position onto that x-axis
ve is the projection of the eye position onto that y axis
Thebes.objecttopoly — Methodobjecttopoly(o::Object)Return a tuple:
an array of 2D points representing the vertices of
oan array of 2D polygons representing the faces of
o
Example
This example draws the faces of a cube in colors, and marks the vertices in black.
using Luxor, Thebes
@draw begin
helloworld()
o = make(Cube)
scaleby!(o, 100, 100, 100)
vs, fs = objecttopoly(o)
setopacity(0.4)
sethue("black")
for face in fs
randomhue()
poly(face, :fill)
end
sethue("black")
circle.(vs, 3, :fill)
endThebes.perspective — Methodperspective()
perspective(n)Get or set the current perspective.
Thebes.pin — Methodpin(o::Object;
gfunction=(o) -> hiddensurface(o))Draw a rendering of an object.
The default rendering function is hiddensurface().
You can also use the built-in wireframe() rendering function.
Examples
@draw begin
o = make(Cube)
axes3D(200)
scaleby!(o, 200, 200, 200)
eyepoint(250, 270, 300)
pin(o) # use an attempted hiddensurface rendering
o = make(Tetrahedron)
axes3D(200)
scaleby!(o, 200, 200, 200)
eyepoint(250, 270, 300)
pin(o, gfunction=wireframe) # use a wireframe rendering
endMore help
You could write your own rendering function to draw objects.
function a_rendering_function(o::Object)
if !isempty(o.faces)
sortfaces!(o)
@layer begin
for (n, face) in enumerate(o.faces)
@layer begin
vertices = o.vertices[face]
sn = surfacenormal(vertices)
ang = anglebetweenvectors(sn, eyepoint())
setgrey(rescale(ang, 0, π, 1, 0))
pin(vertices, gfunction = (p3, p2) ->
begin
poly(p2, :fill)
sethue("white")
poly(p2, :stroke, close=true)
end)
end
end
end
end
endThebes.pin — Methodpin(p3_1::Point3D, p3_2::Point3D;
gfunction = ((p3_1, p3_2), (p2_1, p2_2)) ->
line(p2_1, p2_2, :stroke))Draw two 3D points.
The default action is to draw a line between two points.
The gfunction can access the 3D points as the first argument, the two 2D points in the second argument.
pin(p, Point3D(50cos(θ), 50sin(θ), p.z),
gfunction = (p3s, p2s) -> begin
line(p2s..., :stroke)
end)
Returns the two 2D points.
Thebes.pin — Methodpin(pt::Point3D;
gfunction = (p3, p2) -> circle(p2, 1, :stroke))Draw a single 3D point on the current Luxor drawing.
The default graphic is a circle. You can define others using a custom gfunction, which takes two arguments: the 3D point and its 2D counterpoint.
For example, this draws a circle whose radius is larger if the point is nearer to the eye.
pin(p, gfunction = (p3, p2) -> begin
d = distance(p3, eyepoint())
circle(p2, rescale(d, 0, 300, 20, 5), :fill)
end
)Returns the 2D point.
Thebes.pin — Methodpin(p3list::Array{Point3D, 1};
gfunction = (p3list, p2list) ->
poly(p2list, :stroke, close=true))Draw an array of 3D points.
The default action is to draw a polygon through all the points.
The gfunction can access the 3D points as the first argument, the two 2D points in the second argument.
helix = [Point3D(100cos(θ), 100sin(θ), 20θ) for θ in 0:π/12:4π]
a_box = pin(helix, gfunction =
(p3list, p2list) -> prettypoly(p2list, :stroke)
)Returns the list of 2D points.
Thebes.pointsperpendicular — Functionpointsperpendicular(p1::Point3D, p2::Point3D, radius, angles = [0, π])Find points perpendicular to a line joining p1 and p2. Points are radius units away from the line.
Thebes.project — Methodproject(P::Point3D)
Project a 3D point onto a 2D surface, as defined by the current projection.
TODO Currently this returns 'nothing' if the point is behind the eyepoint. This makes handling the conversion a bit harder, though, since the function now returns either a 2D Luxor point or nothing.
using Thebes, Luxor
@svg begin
eyepoint(Point3D(250, 250, 100))
centerpoint(Point3D(0, 0, 0))
uppoint(Point3D(0, 0, 10))
sethue("grey50")
carpet(300)
axes3D(100)
sethue("red")
for i in 1:30
randpoint3D = Point3D(rand(0.0:150, 3)...)
sethue("red")
pt1 = pin(randpoint3D)
if pt1 != nothing
circle(pt1, 5, :fill)
end
end
endThebes.rotateX — MethodrotateX(pt3D::Point3D, rad)Return a new point resulting from rotating the point around the x axis by an angle in radians.
Rotations are anticlockwise when looking along axis from 0 to +axis.
Thebes.rotateY — MethodrotateY(pt3D::Point3D, rad)Return a new point resulting from rotating the point around the y axis by an angle in radians.
Rotations are anticlockwise when looking along axis from 0 to +axis.
Thebes.rotateZ — MethodrotateZ(pt3D::Point3D, rad)Return a new point resulting from rotating the point around the z axis by an angle in radians.
Thebes.rotateby! — Methodrotateby!(o::Object, r::Rotation)
rotateby!(o::Object, angleX, angleY, angleZ)Rotate an object through rotation r, or around the x, y, and/or z axis by angleX, angleY, angleZ.
Thebes.rotateby! — Methodrotateby!(o::Object, pt::Point3D, angleX, angleY, angleZ)
rotateby!(o::Object, pt::Point3D, r::Rotation=RotXYZ(0, 0, 0))Rotate an object around a point by rotation r, or angleX, angleY, angleZ.
Thebes.rotateby! — Methodrotateby!(ptlist::Array{Point3D, 1}, angleX, angleY, angleZ)Modify a list of points by rotating each one around the x, y, and z axes by angleX, angleY, angleZ.
Thebes.rotateby! — Methodrotateby!(ptlist::Array{Point3D, 1}, existingpt::Point3D, angleX, angleY, angleZ)
rotateby!(ptlist::Array{Point3D, 1}, existingpt::Point3D, r::Rotation)
rotateby!(ptlist::Array{Point3D, 1}, r::Rotation=RotXYZ{Float64})Rotate each point in the list by rotation (or angleX, angleY, angleZ) around another point (or origin).
Thebes.rotateby — Methodrotateby(o::Object, angleX, angleY, angleZ)Rotate a copy of the object by angleX, angleY, angleZ.
Thebes.rotateby — Methodrotateby(o::Object, pt::Point3D, angleX, angleY, angleZ)
rotateby(o::Object, pt::Point3D, r::Rotation=RotXYZ(0, 0, 0))Rotate a copy of the object around a point by rotation r, or angleX, angleY, angleZ.
Thebes.rotateby — Methodrotateby(pt::Point3D, angleX, angleY, angleZ)
rotateby(ptlist::Array{Point3D, 1}, angleX, angleY, angleZ)
rotateby(point::Point3D, r::Rotation)
rotateby(ptlist::Array{Point3D, 1}, r::Rotation)Return a new point/list of points resulting from rotating around the x, y, and z axes by angleX, angleY, angleZ.
The Z rotation is first, then the Y, then the X.
A 3×3 rotation matrix parameterized by the "Tait-Bryant" XYZ Euler angle convention, consisting of first a rotation about the Z axis by theta3, followed by a rotation about the Y axis by theta2, and finally a rotation about the X axis by theta1.
Thebes.rotateby — Methodrotateby(point::Point3D, about::Point3D, angleX, angleY, angleZ)
rotateby(point::Point3D, about::Point3D, r::Rotation)
rotateby(ptlist::Array{Point3D, 1}, about::Point3D, r::Rotation)Thebes.scaleby! — Methodscaleby!(o::Object, x, y, z)Scale object by x in x, y in y, and z in z.
Thebes.scaleby! — Methodscaleby!(o::Object, d)Scale object by d in x, d in y, and d in z.
Thebes.scaleby! — Methodscaleby!(ptlist::Array{Point3D, 1}, x, y, z)Scales a list of points by multiplying by x in X, y in Y, z in Z.
Thebes.sortfaces! — Methodsortfaces!(o::Object;
eyepoint::Point3D=eyepoint())Find the averages of the z values of the faces in Object, and sort the faces of o so that the faces are in order of nearest (highest) z relative to eyepoint...
or something like that ? not sure how this works
Thebes.sphericaltocartesian — Methodsphericaltocartesian(ρ, θ, ϕ)Return Point3D(x, y, z) corresponding to (ρ, θ, ϕ):
ρ is the distance from the origin (ie radius)
θ is the azimuthal angle (the longitude) 0 is +x, π is -x, 2π is +x
ϕ is the polar angle (the colatitude) 0 is North Pole, π is South Pole
There are two major conventions for spherical coordinate notation.
In physics books:
(ρ, θ, φ) gives the radial distance, polar angle (colatitude), and azimuthal angle (longitude)
In mathematics books:
(ρ, θ , φ ) gives the radial distance, azimuthal angle (longitude), and polar angle (colatitude)
So we're using the mathematics one here.
Thebes.sphericaltocartesian — Methodsphericaltocartesian((ρ, θ, ϕ))Return Point3D(x, y, z) corresponding to (ρ, θ, ϕ).
Thebes.surfacenormal — Methodsurfacenormal(ptlist::Array{Point3D, 1})Finds one of these.
Thebes.text3D — Method text3D(str, anchor::Point3D;
halign=:left,
valign=:baseline,
about=Point3D(0., 0., 0.),
rotation::Rotation=RotXYZ(0, 0, 0))Draw text at point pt, lying in the plane of the x axis. Angles in rotation rotate the text about the about point, defaulting to Point3D(0, 0, 0).
Uses Luxor's fontface() and fontsize() settings.
Specify rotations using functions from Rotations.jl, such as:
RotX(a)RotZ(a)RotXZ(a1, a2)RotXYZ(a1, a2, a3)
Thebes.uppoint — Methoduppoint(pt::Point3D)Specify the "up" direction for the world: a line from the centerpoint to the uppoint defines the up direction.
Thebes.uppoint — Methoduppoint()
uppoint(pt::Point3D)The "up" direction for the world: a line from the centerpoint to the uppoint defines the up direction.
Thebes.wireframe — Methodwireframe(o::Object)Given an object o, sort the faces in o.faces, then draw grey stroked polygons for each face.