# VRML rotations : how to draw a cylinder between 2 spheres

Dear All,

I am looking for math formulae (or Java code) that could help me draw a cylinder between 2 spheres.

I am using Java to create a WRL file. The world is composed of several spheres (known x,y,z locations). I would like to draw cylinders between spheres, but I am struggling with the VRML rotation function.

So I would need a function that returns:
translation Ax Ay Az
rotation Bx By Bz Th
given 2 locations (x1,y1,z1) (x2,y2,z2)

Thanks,

Olivier

===========================

#VRML V2.0 utf8

Group {
children [
Transform {
translation 1 2 3
children Shape {
appearance DEF xapp Appearance {
material Material { }
}
geometry Sphere { radius 0.2 }
}
}
Transform {
translation 3 2 1
children Shape {
appearance USE xapp
geometry Sphere { radius 0.2 }
}
}
Transform {
translation 1 2 3
rotation 1 0 0 1.57
children Shape {
appearance USE xapp
geometry Cylinder {
height 4
}
}
}

]
}

Game ProgrammingMath / Science

Last Comment
jgordos
jgordos

THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
romarin12

thanks John.

So, for now, your solution is:
translate x1 y1 z1
rotation 1 0 0 R1 {
rotation 0 0 1 R2 {
cylinder blah

Is there a way to combine the 2 rotations into a single rotation? This would be more efficient on the 'client' side.

jgordos

the problem with "combining" is that the "output" of the first rotation is used as an "input" in the second rotation.

Can you do matrix math in VRML?  I've never tried....

romarin12

I can definetely do matrix math in Java...

Here is below your solution coded in Java. My code works when the 2 points are in the XY plan, it does not when points are outside. There is something wrong with the second angle. I am afraid I need a crash course in geometry... Can you help?

``````package testvrmlrotations;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;

public class Main {

public static void main(String[] args) throws IOException {

FileWriter fos = new FileWriter("B:/x.wrl");
BufferedWriter out = new BufferedWriter(fos);

out.write( "#VRML V2.0 utf8");
out.write( "\r  Background { skyColor [ 0.0 0.0 0.0 ] }");

// works when in XY plane
out.write(doit( -2.0, 1.0 , 0.0,   2.0, -3.0, 0.0  ));

// doesn't work when out of XY plane : something wrong with R2
out.write(doit( -2.0, 1.0 , 0.0,   5.0, -1.0, -5.0  ));

out.close();

}

/**
* returns VMRL declarations for
* - 2 spheres at (x1,y1,z1) and (x2,y2,z2)
* - a cylinder connecting the spheres
*/
public static String doit(double x1, double y1, double z1 ,
double x2, double y2, double z2) {

String s=""; // the output
DecimalFormat df = new DecimalFormat(" 0.000");

s += getSpheres(x1,y1,z1);
s += getSpheres(x2,y2,z2);

// **** draw cylinder ****

// get barycenter: this is (0,0,0) for the cylinder
double x=(x1+x2)/2;
double y=(y1+y2)/2;
double z=(z1+z2)/2;

// get height
double h=Math.sqrt( Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2) + Math.pow((z1-z2), 2) ) ;

// vector: barycenter->point2
double vx = (x2-x)/2;
double vy = (y2-y)/2;
double vz = (z2-z)/2;

// Z angle for XY plane : this angle seems OK
double r1 = - Math.atan2(vx, vy);

// vector from XY plane to point2 : something wrong here!!!!
double wx = vy * Math.sin(r1) + vx * Math.cos(r1);
double wy = vx * Math.sin(r1) + vy * Math.cos(r1);
double wz = vz;

// Y angle for new XZ plane
double r2 = - Math.atan2(wx, wz);

// output VRML declarations - nested rotations
s += "\r      Transform {";
s += "\r         translation " + df.format(x) + df.format(y) + df.format(z);
s += "\r         rotation 0 0 1" + df.format(r1);
s += "\r         children Transform {";
s += "\r            translation 0 0 0 " ;
s += "\r            rotation 0 1 0" + df.format(r2);
s += "\r            children Shape {";
s += "\r               appearance Appearance {";
s += "\r                  material Material { diffuseColor 1.0 0.0 1.0 }";
s += "\r               }";
s += "\r               geometry Cylinder {";
s += "\r                  height " + df.format(h);
s += "\r               }";
s += "\r            }";
s += "\r         }";
s += "\r      }";

return s;
}

public static String getSpheres(double x , double y, double z) {

String s=""; // the output
DecimalFormat df = new DecimalFormat(" 0.000");

s += "\r      Transform {";
s += "\r         translation " + df.format(x) + df.format(y) + df.format(z);
s += "\r         children Shape {";
s += "\r            appearance Appearance {";
s += "\r               material Material { diffuseColor 1.0 1.0 1.0 }";
s += "\r            }";
s += "\r            geometry Sphere { radius 0.2 }";
s += "\r         }";
s += "\r      }";

return s;
}
}
``````
romarin12

All,

I have found the Java code I was looking for. this topic was alerady adressed in:

Olivier

``````/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package Java3Dthing;

/*
* CylinderTransformer.java
*
*
* Created on 25 July 2003, 11:04
*/

import javax.vecmath.*;

/** A class to calculate the length and transformations necessary to produce a
* cylinder to connect two points.  Useful for Java3D and VRML where a cylinder
* object is created aligned along the y-axis.
* @author Alastair Hill
*/
public class CylinderTransformer {

/** point A */
private final Point3f pointA;
/** point B */
private final Point3f pointB;
/** the angle through which to rotate the cylinder */
private float angle;
/** the axis around which to rotate the cylinder */
private Vector3f axis;
/** The translation required to translate the cylinder to the midpoint of the two
* points
*/
private Vector3f translation;
/** The length of the cylinder required to join the two points */
private float length;

/** Creates a new instance of CylinderTransformer
* @param a point a
* @param b point b
*/
public CylinderTransformer(Point3f a, Point3f b) {
pointA = a;
pointB = b;

//carry out the calculations
doCalculations();
}

/** Carries out the necessary calculations so that values may be returned */
private void doCalculations() {
length = pointA.distance(pointB);

float[] arrayA = new float[3];
pointA.get(arrayA);
float[] arrayB = new float[3];
pointB.get(arrayB);
float[] arrayMid = new float[3];

for (int i=0;i<arrayA.length;i++){
arrayMid[i] = (arrayA[i] + arrayB[i]) / 2f;
}

//the translation needed is
translation = new Vector3f(arrayMid);

//the initial orientation of the bond is in the y axis
Vector3f init = new Vector3f(0.0f,1.0f,0.0f);

//the vector needed is the same as that from a to b
Vector3f needed = new Vector3f(pointB.x-pointA.x, pointB.y-pointA.y, pointB.z-pointA.z);

//so the angle to rotate the bond by is:
angle = needed.angle(init);

//and the axis to rotate by is the cross product of the initial and
//needed vectors - ie the vector orthogonal to them both
axis = new Vector3f();
axis.cross(init, needed);
}

/** Returns the angle (in radians) through which to rotate the cylinder
* @return the angle.
*/
public float getAngle() {
return angle;
}

/** The axis around which the cylinder must be rotated
* @return the axis
*/
public javax.vecmath.Vector3f getAxis() {
return axis;
}

/** The length required for the cylinder to join the two points
* @return the length
*/
public float getLength() {
return length;
}

/** The translation required to move the cylinder to the midpoint of the two points
* @return the translation
*/
public javax.vecmath.Vector3f getTranslation() {
return translation;
}

/** Generates a (pretty) string representation of the the CylinderTransformer
* @return the string representation
*/
public String toString(){
return "tr: " + translation + ", ax: " + axis + ", an: " + angle + ", le: " + length;
}

/** Generates the required axis and angle combined into an AxisAngle4f object
* @return the axis and angle
*/
public javax.vecmath.AxisAngle4f getAxisAngle() {
return new AxisAngle4f(axis.x,axis.y,axis.z,angle);
}
}

-------------------------

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package Java3Dthing;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;

/**
*
* @author olivier
*/
public class runme {

public void go() throws IOException {

FileWriter fos = new FileWriter("B:/xxx.wrl");
BufferedWriter out = new BufferedWriter(fos);

out.write( "#VRML V2.0 utf8");
out.write( "\r  Background { skyColor [ 0.0 0.0 0.0 ] }");

out.write(doit( -2.0, 1.0 , 0.0,   2.0, -3.0, 0.0  ));

out.write(doit( -2.0, 1.0 , 0.0,   5.0, -1.0, -5.0  ));

out.close();

}

/**
* returns VMRL declarations for
* - 2 spheres at (x1,y1,z1) and (x2,y2,z2)
* - a cylinder connecting the spheres
*/
public static String doit(double x1, double y1, double z1 ,
double x2, double y2, double z2) {

String s=""; // the output
DecimalFormat df = new DecimalFormat("0.000");

s += getSpheres(x1,y1,z1);
s += getSpheres(x2,y2,z2);

// **** draw cylinder ****
Point3f a = new Point3f();
a.x = (float) x1;
a.y = (float) y1;
a.z = (float) z1;

Point3f b = new Point3f();
b.x = (float) x2;
b.y = (float) y2;
b.z = (float) z2;

CylinderTransformer ct = new CylinderTransformer(a,b);

Vector3f vt = ct.getTranslation();
Vector3f va = ct.getAxis();

s += "\r      Transform {";
s += "\r         translation " + df.format(vt.x) + " " + df.format(vt.y) + " " + df.format(vt.z);
s += "\r         rotation " + df.format(va.x) + " " + df.format(va.y) + " " + df.format(va.z) + " " + df.format(ct.getAngle());
s += "\r         children  Shape {";
s += "\r               appearance Appearance {";
s += "\r                  material Material { diffuseColor 1.0 0.0 1.0 }";
s += "\r               }";
s += "\r               geometry Cylinder {";
s += "\r                  height " + df.format(ct.getLength());
s += "\r               }";
s += "\r         }";
s += "\r      }";

return s;
}

public static String getSpheres(double x , double y, double z) {

String s=""; // the output
DecimalFormat df = new DecimalFormat("0.000");

s += "\r      Transform {";
s += "\r         translation " + df.format(x) + " " + df.format(y) + " " + df.format(z);
s += "\r         children Shape {";
s += "\r            appearance Appearance {";
s += "\r               material Material { diffuseColor 1.0 1.0 1.0 }";
s += "\r            }";
s += "\r            geometry Sphere { radius 0.2 }";
s += "\r         }";
s += "\r      }";

return s;
}

public static void main(String[] args) throws IOException {
runme demo = new runme();

demo.go();
}

}
``````
jgordos

I understand that you've found the source code that you were looking for, but the answer i gave is still valid.

I wasn't going to write your code for you, or debug your existing solution.. that's up to you to do.

This feels like a homework exercise...  I offered guidance without just giving you the solution, which is what we're supposed to do on here.

-john
jgordos

I still don't understand why this question is being closed with no points...

jgordos

I objected because I want to understand why it's autoclosing without any comments back from the question answerer to my 7/24/2008 comment.

-john
jgordos

Like I said.

there was no response to my comment.

SO I OBJECTED
Math / Science

The Math / Science topic primarily includes discussions of mathematics, physics, statistics and economic analysis, but also biology, chemistry and other sciences.

10K
Questions
--
Followers
--
Top Experts
Get a personalized solution from industry experts

TRUSTED BY