VBA – Generating unique keys for TreeView module

Today I came across a problem while creating a hierarchy tree for 3D models in Microsoft Access.

My hierarchy tree system looks like this:

*A (parent node)

-A1

–A11

—A111

–A12

–A13

-A2

–A21

-A3

.

.

.

My problem was that the node keys for the Dot.Net TreeView module tend to repeat, for example when reaching A11 in the first level of hierarchy (A11)

There are probably more elegant solutions out there, but mine was to generate an unique key for the first generation of the tree (first branch). From A to Z, and when we run out of letters, start with AA-ZZ and then from AAA-ZZZ. This should, in theory (still to be tested) do for extensive hierarchy trees.

Hereunder the code. If somebody stumbles across this code and has any suggestion, it will be appreciated

Option Compare Database
Option Explicit

Private basicLetterCount As Integer
Private timesLooped As Integer
Private keyDict As New Scripting.Dictionary
Private alphabet As New Collection
Private existingKeys As New Scripting.Dictionary

' ------------------------------------
' PUBLIC FUNCTIONS
' ------------------------------------

Public Sub initializeKeyGeneratorSystem()

keyDict.RemoveAll
existingKeys.RemoveAll
Call populateAlphabet

basicLetterCount = 1
timesLooped = 0

End Sub

Public Function generateKey(i As Integer)

Dim currentLetter As String

currentLetter = alphabet.Item(basicLetterCount)
existingKeys.Add generateNewKey(currentLetter, timesLooped), i

If (basicLetterCount >= 26) Then
basicLetterCount = 1
timesLooped = timesLooped + 1
Else
basicLetterCount = basicLetterCount + 1

End If

generateKey = GetKey(existingKeys, i)

End Function

' ------------------------------------
' PRIVATE FUNCTIONS
' ------------------------------------
Private Sub populateAlphabet()

Dim str As String
Dim i As Integer

str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

For i = 1 To Len(str)
alphabet.Add (mID(str, i, 1))
Next i

End Sub

Private Function generateNewKey(letter As String, nrRepeat As Integer) As String
Dim result As String
Dim i As Integer

result = letter
For i = 1 To nrRepeat
result = result + letter
Next i

generateNewKey = result

End Function

Private Function GetKey(Dic As Dictionary, strItem As Integer) As String
Dim key As Variant
For Each key In Dic.Keys
If Dic.Item(key) = strItem Then
GetKey = CStr(key)
Exit Function
End If
Next
End Function

Usage in the main function:

 

Private Function myFunctionName()

Dim externalCount As Integer
Dim i As Integer

externalCount = 100
'Initialize the key generator system
Call initializeKeyGeneratorSystem
'You need to pass an external count to the keygenerator
For i = 1 To externalCount
Debug.Print (generateKey(i))
Next i
End Sub

3ds Max and FlightStudio: getting around with the Flight Studio Hierarchy menu

I have been developing some maxscript scripts in order to automatize the process of exporting models to .flt format. The purpose was to programmatically create object/xref dummy nodes from maxscript. However, the Open Flight functions are barely accessible and documented in the 3ds Max help. Which is a pity. According to the documentation, you can create a flt object in the hierarchy window with maxscript, using this function of the Flight Studio interface:

FlightStudio.CreateObject()

But, how do you access the properties of this newly created node? Change its name? Define which file it refers to, in the case of xref flight nodes? I got this workaround: create the flt object/xref node, and immediately after, look for any dummies in the scene which begins with x* (in the case of xref flt nodes) or o* (in the case of object nodes). After you have found it, you can access its properties just as with any max object.

local allobjs = $*

fltStudio.CreateExternalRef()

for o in allobjs do 
(
if (classOf o == Dummy) then 
(
if (matchPattern o.name pattern:"x*" ignoreCase:false) then (

--put the xref path
fltStudio.PutExternalRefFilename o (fileextToFLT fPath)

--rename
o.name = fName

-- align it to the parent object PIVOT (not center)
o.rotation = rot o.position = pos o.boxsize = [0.5, 0.5, 0.5]

-- put in object's layer 
If (objLayer == undefined) then objLayer = "0"
local target = LayerManager.getLayerFromName 
objLayer target.addNode o 
append createdDummies o 
) 
) 
)

On light and space – [d]espacio series (2011)

Video 13′ 46”

Music by Ángel Arranz

De la luz y del espacio is the fourth and last piece of the series entitled [d]espacio, composed by Ángel Arranz and visualized by Beatriz del Saz, inspired on four different avant-garde buildings in Spain. De la luz y del espacio is based on Bodegas Qumrán, a work by the architecture studio Konkrit Blu from Barcelona.

The piece takes as a model the resonances of the real spaces, recorded by the composer self.
To this end, a glass of wine was used as a resonator by introducing inside a small microphone. This noise-silence captured by using naturally amplified resonators was taken as a metaphor of light translated to sound. So do video animations. These are based on the real 3D model of the winery. Few colors were used in order to enhance the quality of shapes, while the duality between light and space is represented with the colors black and white.

The video was created in close collaboration with the composer, and this made possible a special synergy with the musical discourse.

Quaternions and OpenFrameworks

There are multiple ways of representing rotation in a 3D environment. You have “normal” rotation (degrees about the XYZ axis), axis-to-angle rotation (rarely used in 3D animation), Euler angles, and quaternions. Each of them has its advantages and disadvantages, it just depends on the kind of project you are working on.

I found that in my particular case, for the video I am working on, quaternions were the best option. But… What is a quaternion? It took me a while to get to understand what this obscure mathematical word means, and I think I still don’t quite understand it, but well, here is my attempt to make this concept a little bit more clear – from the animator’s point of view.

OpenFrameworks code

This code is based on an example published by an user called julapy, from Sydney, on this post of the OpenFrameworks forum.

1) ofQuaternion class
In OpenFrameworks, creating a quaternion is as simple as declaring an instance of the class ofQuaternion.
OF007 includes this class in its core, however, if you are using OF006, you’ll have to use the “ofxQuaternion” add-on, and include its header accordingly in testApp.h.

ofQuaternion qr (angle, axis);

Note that the class ofQuaternion has several constructors. This means that you can initialize an instance in several ways (in Xcode, you can see this by right-clicking in the name ofQuaternion and selecting the option Jump to Definition).
I am going to use the constructor accepting a float scalar and a ofVec3f. The scalar represents the angle or amount of rotation, while the ofVec3f is a 3-dimensional vector representing a (normalized) axis of rotation. That is to say, the axis around which the rotation is produced.

2) Create 4 quaternions
Now we are going to create 4 quaternions:

  • A quaternion for “roll” rotation (rotation around Z-axis)
  • A quaternion for “pill” rotation (rotation around Y-axis)
  • A quaternion for “yaw” rotation (rotation around X-axis)
  • A quaternion to include all the 3 rotations combined
//Declare the normalized XYZ axis as vector variables
ofVec3f Znormal(0, 0, 1);
ofVec3f Xnormal(1, 0, 0);
ofVec3f Ynormal(1, 0, 1);

//Create the quaternions
ofQuaternion qr (roll, Znormal); // quat roll.
ofQuaternion qp (pitch, Xnormal); // quat pitch.
ofQuaternion qh (heading, Ynormal); // quat heading or yaw.
ofQuaternion qt; // quat total.

Basically we are telling our quaternion: please rotate “roll/pitch/heading” degrees around the “Znormal/Xnormal/Ynormal” axis.
As it seems, this way of thinking is not correct mathematically, but it serves our purposes.

Note: If you observe the complete code (see below), the variables roll, pitch and yaw are changed by user interaction, if you press a key the angle of each of them is incremented by one.

3) Combine the 3 quaternions into one

Now we want to obtain a single “definitive” quaternion which contains the rotations of qr, qp, and qh. We do this by multiplying all the quaternions. Note that THE ORDER DOES MATTER: Apply roll first, then pitch, then heading.

 qt = qr * qp * qh;

4) Apply transformation
This is the most important step. We extract the quaternion information and transform it into a “normal” 4×4 matrix, like the ones OpenGL uses to make transformation operations. This way we can go on working with our old friend glRotatef.

How do we do this? Don’t worry, the difficult stuff was already implemented by the clever OF developers. We are just using one member function of the ofQuaternion class.

First we create two new variables which stores the angle of rotation after quaternion transformation, and the axis around which the rotation occurs, also after quaternion transformation.
I like to imagine it this way: when you create a quaternion, you are specifying a rotation around an axis in a world which has no euclidean xyz coordinates. You cannot define this rotation as up, down, left or right as it has no references.
Once this rotation is performed, you have to come back to the “real world”, and translate this rotation into the coordinate space you are working on. This transformation is made with the function member getRotate(qangle, qaxis).
We are telling the quaternion to give back some elements which the application will use to build a normal 4×4 transformation matrix, so that it can go on with the transformation process. Recall that for example in OpenGL transformations and rotations are made by multiplying multiple matrices in a given order. More on this in the OpenGL Red Book.

ofPushMatrix();
ofVec3f qaxis; float qangle;
qt.getRotate(qangle, qaxis);

ofRotate(qangle, qaxis.x, qaxis.y, qaxis.z);
//here goes the object we want to draw
ofPopMatrix();

You can download and see the complete code in this GitHub repository page.

Further reading…

– Great FAQ pagina to get you started (as found in Roxlu’s blog) http://www.j3d.org/matrix_faq/matrfaq_latest.html

– Wikipedia pagina on quaternions http://en.wikipedia.org/wiki/Quaternion

– Book “3D Math Primer for Graphics and Game Development” – a must-read, really useful if you don’t have much of a maths background

SAH – [d]espacio series (2012)

Video 11′ 51″

Music by Ángel Arranz

AH is the third video of the acoustic series [d]espacio, with music by Ángel Arranz and inspired in Bodegas Ysios winery by the architect Santiago Calatrava. The video replicates the visual structure of the winery’s facade, and has 3 straightforward, clearly differentiated parts. In this case, music and video evolve in a separate way, and the structure of one does not influence the structure of the other. In the style of ancient Egyptian architecture, the video uses straight lines exclusively, which combine in whimsical patterns. The colors remind of the desert landscapes of Egypt, of the white garments of the gods represented in the tombs’ mural paintings, of their extraordinary treasures, and naturally, of the red and rosy hues of wine: a beverage whose elaboration, as the legend goes, Osiris taught to mankind.

JavaScript interpolation and Max/Jitter

For my last video, Qumran B, I wanted to create have 9 objects (jit.gl.gridshapes) each with a different texture, so I decided to implement a piece of JavaScript code.
I have been messing around with C++ and OpenFrameworks the last months, and somehow coming back to the pre-made graphical environment in Max/Jitter felt quite annoying.

After some posting in the fantastic Max support forum (the community there is incredibly helpful and always give you great tips) I came out with this code.

The idea is that whenever the function “randomize” is called, these pieces jump to different location in space interpolating (tweeing) from the original position to the final position. These intermediate positions are calculated inside the js object and then sent to 9 different [receive] objects inside my patch.

I also found this fantastic article by Paul Bourke. In this article he describes the commonest interpolation methods and he even shares the C++ functions to make them possible.

The script’s basis are tasks. JS tasks are basically functions which are programmed to happen at a given interval, or to repeat until they are stopped. You do not need to call these functions everytime (for example, by sending a bang into the js object), instead you program when you want the function to start repeating, and when you want it to end.

When creating interpolation, it is important to take into account that the original and final positions need to be the same from the beginning to the end of the moment, otherwise the interpolation won’t work properly.

Here the code:

//Complete corrected js code  
inlets=1;
outlets=0;
var nPieces =9;
var pieces = new Array(nPieces);
var finalPos = new Array(nPieces); //store actual positions, then generate new positions
var sendObj = ["send0", "send1", "send2", "send3", "send4", "send5", "send6", "send7", "send8"];
var rScale = 5;
var counter = 0.0;
var refreshCounter = 0.01;
var interpYesNo = false;
var PI = 3.141594;
//TASKS
var tsk = new Task(updateCounter, this);
tsk.interval = 50; //repeats each 50 ms
function piece(x, y, z, w, h) { //pieces constructor
this.pos = [x,y, z];
this.scale = [w,h, 1.0];
this.vel = [0.0, 0.0, 0.0];
}
function setUpPieces () {
for(i=0; i<nPieces; i++)
{
pieces[i] = new piece(0.0, 0.0, 0.0, 1.0, 1.0);
messnamed(sendObj[i], "position", pieces[i].pos[0], pieces[i].pos[1], pieces[i].pos[2]);
}
}
function randomPos () {
return(((Math.random()-0.5)*rScale), ((Math.random()-0.5)*rScale), ((Math.random()-0.5)*rScale));
}
function calculateNewPositions() {
//store origin and final pos
for(i=0; i<nPieces; i++){
//originPos[i] = pieces[i].pos;//DELETE THIS LINE
finalPos[i] = [randomPos(), randomPos(), randomPos()];
}
}
//LINEAR INTERPOLATION
function interpolation (initialPos, finalPos, time) {
return(initialPos+time*(finalPos-initialPos));
}
for(i=0; i<nPieces; i++)
{
messnamed(sendObj[i], "position",
interpolation(pieces[i].pos[0], finalPos[i][0], c),
interpolation(pieces[i].pos[1], finalPos[i][1], c),
interpolation(pieces[i].pos[2], finalPos[i][2], c));
}
}
function randomize() {
if (interpYesNo == false) {
interpYesNo= true;
calculateNewPositions();
tsk.repeat(); //start task
}
}
function updateCounter() {
if(counter < 1.0)
{
counter += refreshCounter;
post(counter, "\n");
interpolate(counter);
}
else
{
counter = 0.0;
interpYesNo = false;
for(i = 0; i<nPieces, i++)
{
pieces[i].pos = finalPos[i]; //STORE FINAL POSITION AS INITIAL POSITION }
arguments.callee.task.cancel(); //cancel the task
}
}
updateCounter.local = 1; //prevent triggering the task directly from outside the js
function stop() {
tsk.cancel();
interpYesNo = false;
}

Tallereando

Video installation (45′)

Tallereando is a multidisciplinary exhibition which integrates a series of photographies by José Luis Rodríguez Posadas, a sound composition by the composer Ángel Arranz and a video installation with abstract 3D images by myself.

The video tries to recreate the dynamism and aural ambiances produced by the old tools portrayed in the photographies.

DK Between the East and the West (2011)

Live video improvisation

Music by Ángel Arranz

DK <qumran> is a series of multidisciplinar pieces consisting of three electronic pieces with acoustic instruments composed by Ángel Arranz, with visual improvisations inspired in the architecture of the winery Bodegas Qumrán, by the architecture studio konkritblu

Extrusion – [d]espacio series (2011)

Video 9′ 24”
Music by Ángel Arranz

Extrusion is a video created in close collaboration with the composer of the music, Angel Arranz. The term ‘Extrusion’ means:

1. The act or process of pushing or thrusting out.
2. The act or process of shaping by forcing through a die.
3. An object or material produced by extruding.

Usually this term is associated to plastics, and in this sense the video depicts a fluid, flexible process of transformation in several stages. It describes the transit from a dramatic, colliding and artificial sort of transformation, such as that occuring in industrial environments, to a more natural, “accepted” change, similar to the ones happening in nature, most of the time with unpredictable results.

The video is created by using OpenGL environments and JavaScript scripting.

extr_2extr_3extr_4extr

void init ()

{ printf(“Welcome to my blog!\n”); }