1. NodeBox 1
    1. Homepage
    2. NodeBox 3Node-based app for generative design and data visualization
    3. NodeBox OpenGLHardware-accelerated cross-platform graphics library
    4. NodeBox 1Generate 2D visuals using Python code (Mac OS X only)
  2. Gallery
  3. Documentation
  4. Forum
  5. Blog

Tesseract

Posted by Zacharias Enochsson on May 31, 2007



Heres a NodeBox script I put together for drawing/rotating/inspecting a 4D-cube. Hope you find it entertaining, or possibly even useful somehow.

"""
tesseract.py
 
Did you ever wonder what the fourth dimension looks like?
---------------------------------------------------------
 
This is an interactive animation of a tesseract, aka hyperccube 
-- the four-dimensional equivalent of a cube -- for NodeBox
 
(see http://en.wikipedia.org/wiki/Tesseract)
 
This script draws a projection of the tesseract
on the 2d surface of your screen. Six 'rotation' 
controls allow you to explore the dimensions of it.
 
XY      If you only move this, it is as if you are rotating
        a paper square on a table. This only rotates in the
        first two dimensions
 
XZ,YZ   Now we have added the third dimension, and rotating
        these will be like rolling a dice in your fingers
        
XQ,YQ,ZQ    These three rotations are between the previous three
            dimensions, and the fourth. Notice that if all controls
            are at zero (and perspective off) and you only rotate ZQ,
            you will see nothing change, because this is a rotation
            between the third and fourth dimension, and you cannot yet
            see either (because you set the *Z rotations to 0)
            
You can turn perspective on or off, if it is on, you will see a more
realistic cube. The perspective projection is essentially an orthogonal 
projection from 4d to 3d, and then a standard perspective projection 
from 3d to 2d. So touching the *Q rotations doesn't really do anything
for the perspective.
 
The SIZE control simply magnifies the image
 
-----------------------------------
zacharias dot enochsson at gmail dot com
 
"""
#imports
from Numeric import *
from Numeric import transpose as tr
from Numeric import matrixmultiply as mxm
 
 
#CONSTANTS:
var("XY",NUMBER,0,0,2*pi) #2d-rotation
var("XZ",NUMBER,0,0,2*pi) #3d-rotation
var("YZ",NUMBER,0,0,2*pi) #3d-rotation
var("XQ",NUMBER,0,0,2*pi) #4d-rotation
var("YQ",NUMBER,0,0,2*pi) #4d-rotation
var("ZQ",NUMBER,0,0,2*pi) #4d-rotation
var("PERSPECTIVE",BOOLEAN,False)
var("LENSE_ANGLE",NUMBER,5,3,10)
var("SIZE",NUMBER,70,20,150)
#Experimentally found to be appropriate for toggle:
DISTANCE = 300*e**(-LENSE_ANGLE*0.49) 
SCREEN_OFFSET = 240 #offsets origin to (240,240) to show entire shape on screen
 
#ROTATION MATRIX DEFINITION
RXY = array([[cos(XY),-sin(XY),0,0],[sin(XY),cos(XY),0,0],[0,0,1,0],[0,0,0,1]])
RXZ = array([[cos(XZ),0,-sin(XZ),0],[0,1,0,0],[sin(XZ),0,cos(XZ),0],[0,0,0,1]])
RYZ = array([[1,0,0,0],[0,cos(YZ),-sin(YZ),0],[0,sin(YZ),cos(YZ),0],[0,0,0,1]])
RXQ = array([[cos(XQ),0,0,-sin(XQ)],[0,1,0,0],[0,0,1,0],[sin(XQ),0,0,cos(XQ)]])
RYQ = array([[1,0,0,0],[0,cos(YQ),0,-sin(YQ)],[0,0,1,0],[0,sin(YQ),0,cos(YQ)]])
RZQ = array([[1,0,0,0],[0,1,0,0],[0,0,cos(ZQ),-sin(ZQ)],[0,0,sin(ZQ),cos(ZQ)]])
R = mxm(mxm(mxm(mxm(mxm(RXY,RXZ),RYZ),RXQ),RYQ),RZQ)
 
#DEFINE POINTS:
points=array([[0,0,0,0],[0,0,0,1],[0,0,1,0],[0,0,1,1],[0,1,0,0],[0,1,0,1],[0,1,1,0],[0,1,1,1],[1,0,0,0],[1,0,0,1],[1,0,1,0],[1,0,1,1],[1,1,0,0],[1,1,0,1],[1,1,1,0],[1,1,1,1]])
 
#ROTATE POINTS:
points = mxm(R,tr(2*points-1))
 
#PROJECTION:
if PERSPECTIVE: points = array((points[0,:]/(DISTANCE+points[2,:]),points[1,:]/(DISTANCE+points[2,:])))*DISTANCE
else: points = array((points[0,:],points[1,:]))
 
#SCALE+TRANSLATE:
points = SIZE*points+SCREEN_OFFSET
 
#DRAW FACES
fill(0,0,0,1)
rect(0,0,1000,1000)
stroke(1,1,1,1)
fill(1,1,1,0.17)
faces=((0,1,3,2),(4,5,7,6),(8,9,11,10),(12,13,15,14),(0,2,6,4),(8,10,14,12),(1,3,7,5),(9,11,15,13),(0,4,12,8),(1,5,13,9),(2,6,14,10),(3,7,15,11),(0,1,5,4),(8,9,13,12),(2,3,7,6),(10,11,15,14),(0,2,10,8),(1,3,11,9),(4,6,14,12),(5,7,15,13),(0,1,9,8),(2,3,11,10),(4,5,13,12),(6,7,15,14))
for i,j,k,l in faces:
    xi,yi = points[:,i]
    xj,yj = points[:,j]
    xk,yk = points[:,k]
    xl,yl = points[:,l]
    beginpath(xi,yi)
    lineto(xj,yj)
    lineto(xk,yk)
    lineto(xl,yl)
    endpath()
PS. I was thrilled to find that NodeBox supports Numeric! I couldn't have made this without it. (actually, why don't you include numby/scipy and some other math-tools and make this a really solid app for mathematical visualization. I'd love that)


 
Posted by Mark M on May 31, 2007

Zacharias,

There are some OS X builds of numpy/scipy available here: http://trichech.us/?page_id=5

I haven't tried using them, but it looks like they would be easier to install than building the packages and dependencies from source. Once installed you should be able to use them in nodebox like any other python module. I agree that they should aid in some interesting visualizations in nodebox.

BTW. The above code is pretty slick. Thanks for posting it.



Posted by Z on May 31, 2007

Thanks for the link! As I understand it, however, those libs are compiled against a 2.5 version of python (which must be installed also, for it to work) and from what I can tell NodeBox runs off the builtin 2.3 version. So although I haven't tried it I get the feeling I will need to coax NodeBox into using python 2.5 -- which I imagine is complicated because the libs shipped with Nodebox are compiled for 2.3

Am I mistaken in this?



Posted by C. Redford on May 31, 2007

I have Numpy installed and it works fine with Python 2.5 but unfortunately, no it doesn't work with Nodebox. I just can't seem to find a platform that can support Numpy and Core Graphics. I was really excited about NodeBox too. Frustrating..



Posted by Mark M on May 31, 2007

C&Z,

I had some similar issues and ended up rebuilding nodebox from source so it was linked with my 2.5 python. There are instructions here: http://dev.nodebox.net/ Building went surprisingly smoothly and now I have a Nodebox working with python 2.5.



Posted by C. Redford on May 31, 2007

Oh wow, that's great! Thanks Mark. Any luck with Numpy? Hopefully I'll be able to find out soon myself but I'm under some unrelated deadlines so it may be a week or so.



Posted by Z on Jun 01, 2007

I realize this might take NodeBox off on a different path than originally intended, but did you ever consider bundling a python interpreter in the NodeBox app? That way you could compile include additional packages which could potentially add more powerful mathematical capabilities, as a foundation for more powerful graphics/animation libraries (think linear algebra and dynamical-systems-solvers). Just wanted to throw that out. You could always consider taking *away* certain modules in the standard distribution, in order to reduce app-size.



Posted by Mark M on Jun 01, 2007

C,

The numpy distribution linked above seems to work just fine for me in the nodebox built against python 2.5. I haven't tested it extensively but this works with no errors:

from numpy import *
print cos(array([0, pi/2, pi]))
So at least it is importing with no errors. To be honest I'm not very familiar with numpy and don't really understand the difference between it and numeric, though.

One problem I had with the above link was that I couldn't get matplotlib to work. It complained about the version of numeric I had installed vs. how it was built. I simply rebuilt and reinstalled it from the source and it too works fine now.



Posted by Tom De Smedt on Jun 01, 2007

Hi everyone,

NodeBox has a good scientific fanbase - people that are interested in doing math and graphing for example. On the other hand, NodeBox also has a good artistic fanbase - people that are interested in fonts and images for example.

If we want to keep everyone happy we basically have two options: create a big app that contains everything, or create a small app that is extensible along with good documentation.

We chose the latter approach: a small set of core functionalities (spartan Python IDE, AppKit, Numeric and PDF export), a growing set of library plug-ins and source code you can build from scratch to suit your own needs. Keeping things small we can get the work done one step at a time.

Consider the alternative with all user requests built in: we would have a cross-platform Windows/Linux/Mac Python interpreter also scriptable in Ruby and Perl, with export functionality for PDF, Quicktime, JPG, Flash, and as a web applet, with rendering of both vectors, pixels and fonts done in OpenGL, audio analysis support, etc. etc.

It sounds great, I know.

And don't get me the wrong way, all of these things ARE on our to-do list one way or another. It will just take some time and a lot of refactoring to avoid ending up with a bug-and-dependency-filled monster.

Right now Frederik is working on the core of Gravital (e.g. NodeBox 2) which will have a node interface and a plugable backend (e.g. it can draw using Cocoa, but also - theoretically at the moment - using OpenGL or ReportLab. It could run cross-platform once someone implements platform-specific GUIs/renderers (I saw some e-mails passing with talk of a Linux port), integration with things like scipy will be easier, etc.

But for now, if you have specific needs, simply build NodeBox from scratch.

C.: did you know Mac has Core Graphics bindings for Python that work right of the box? You can just do:

from CoreGraphics import *
Here's some more information:
http://www.onjava.com/pub/a/mac/2004/03/19/core_graphics.html

Z.: great work on the Tesseract! Thanks for sharing us your code.



Posted by Z on Jun 01, 2007

Thanks for the input tom (and the compliment!) I can totally understand the dev strategy. I was just airing my wishful thinking I guess :)



Posted by C. Redford on Jun 01, 2007

Hi Tom. Thanks for the response. When I was complaining, I didn't realize that Nodebox could simply be rebuilt from scratch to fit my system. I'm new to the open source movement so it is all a little new to me.

Ironically, my main trouble right now is getting *svn* installed on my Mac so I can follow your straightforward instructions for building.

As for the

from CoreGraphics import *
line, it doesn't seem to work in Python 2.5.

It looks like maybe
from Carbon.CG import *
might be the replacement for that in 2.5 but I don't know enough about Core Graphics to find out.



Posted by C.Redford on Jun 01, 2007

Okay I got it compiled and running. It took some wrestling but it's working with Python 2.5 and Numpy! Woohoo! Thanks a lot guys!

Btw: does anyone know an easy way (i.e. a source change) to get my compiled Nodebox to check my Python.Framework folder for dependencies instead of it's own Application Support folder?



Posted by Tom De Smedt on Jun 03, 2007

In NodeBox.py on line 355 you have:

libDir = os.path.join(os.getenv("HOME"), "Library", "Application Support", "NodeBox")
Setting libDir to the path you want will do the trick I think.



Posted by C. Redford on Jun 14, 2007

Okay. FYI, I changed line 355 to

libDir = "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages"
And it worked. Thanks again, Tom.



Posted by Mans on Jul 22, 2009

Just a reminder..
The 4th dimension you mensioned is time. It can't be physical appearance!!

Thank you.



Posted by Zacharias on Sep 16, 2009

In mathematics and geometry you can have as many dimensions as you like (even infintely many). It's only the physical world which seems restricted to three dimensions of space, and one more (the "fourth dimension") of time.



Posted by mahmood on Jul 19, 2010

this concept is wrong if the scientist said that this is four dimension it should be explain firstly clock rotation