Avatar of romarin12
romarin12Flag for France

asked on 

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 {
               radius 0.1
               height 4
            }
         }
      }

  ]
}


Game ProgrammingMath / Science

Avatar of undefined
Last Comment
jgordos
ASKER CERTIFIED SOLUTION
Avatar of jgordos
jgordos
Flag of United States of America image

Blurred text
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.
See Pricing Options
Start Free Trial
Avatar of romarin12
romarin12
Flag of France image

ASKER

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.



Avatar of jgordos
jgordos
Flag of United States of America image

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....

Avatar of romarin12
romarin12
Flag of France image

ASKER

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");
        
        // add spheres
        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                  radius 0.1";
        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;
    }
}

Open in new window

Avatar of romarin12
romarin12
Flag of France image

ASKER

All,

I have found the Java code I was looking for. this topic was alerady adressed in:
http://forums.sun.com/thread.jspa?threadID=433772&messageID=1943374

See also code and demo below.

Olivier

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
 
package Java3Dthing;
 
/*
 * CylinderTransformer.java
 * 
 * http://forums.sun.com/thread.jspa?threadID=433772&messageID=1943374
 *
 * 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");                
        
        // add spheres
        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                  radius 0.1";
        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();
    }
    
}

Open in new window

Avatar of jgordos
jgordos
Flag of United States of America image

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
Avatar of jgordos
jgordos
Flag of United States of America image

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

Avatar of jgordos
jgordos
Flag of United States of America image

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
Avatar of jgordos
jgordos
Flag of United States of America image

Like I said.

there was no response to my comment.

SO I OBJECTED
Math / Science
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
Ask the experts
Read over 600 more reviews

TRUSTED BY

IBM logoIntel logoMicrosoft logoUbisoft logoSAP logo
Qualcomm logoCitrix Systems logoWorkday logoErnst & Young logo
High performer badgeUsers love us badge
LinkedIn logoFacebook logoX logoInstagram logoTikTok logoYouTube logo