Skip to main content

Setting Centroid of Points and Proper Scale?

13 replies [Last post]
ogoto1
Offline
Joined: 2010-03-02

I recently started using Java3d with integration of geotools.org. I'm able to get results from geotools data structures mapped correctly to Java3d data structures and display but....

For the life of me I'm unable to set a Centroid and properly scale large points.
My screen is always a Centroid of 0,0.

What I have is points that are like
(9999.0,100100, 93),
(10000.0,100200, 96),
(10100.0,100300, 98)
So the points are never displayed in my Frame of 400,300
I would really appreciate a code snipped to do the following:
1) set centroid not at 0,0 but at lets say: (10000.0,100200, 96)?
2) scale properly large points like the 3 above to a frame of lets say 400,300?

I played around with the following:
transform3D.setTranslation(new Vector3f(0f,0f,-2f));
transform3D.setScale(.5);

But I honestly think I'm seriously missing something.
Any input would be greatly appreciated.

Thanks

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
aces
Offline
Joined: 2003-07-17

I use the scale factor to better fit on 3D viewer.
The numerator 0.95 means the model is at 95% of normal size to fit on canvas 3D.

by the way, type I prefer type float number as
-5914.92f
instead the verbose
(float) -5914.92

ogoto1
Offline
Joined: 2010-03-02

Just now getting back to responding. The work never ends.
I really appreciate your help on this.

I ended up putting together a transform method for my data to get it centered around 0
I'm getting great results now.

I make the following call after defining my plaPts:
plaPts = transform(plaPts,pointMax);

The new transform method is the following:

public Point3f[] transform(Point3f[] plaPts, int pointMax){
double maxX=0.0d;
double minX=0.0d;
double midX=0.0d;
double maxY=0.0d;
double minY=0.0d;
double midY=0.0d;
double maxZ=0.0d;
javax.vecmath.Point3f point3f = new javax.vecmath.Point3f();
for(int i=0; i
point3f = (javax.vecmath.Point3f)plaPts[i];
if(i==0){
maxX=point3f.x;
minX=point3f.x;
maxY=point3f.y;
minY=point3f.y;
maxZ=point3f.z;
}

if(point3f.x>=maxX) maxX=point3f.x;
if(point3f.x<=minX) minX=point3f.x;
if(point3f.y>=maxY) maxY=point3f.y;
if(point3f.y<=minY) minY=point3f.y;
if(Math.abs(point3f.z)>maxZ) maxZ=point3f.z;

}

midX=((maxX-minX)*.5)+minX;
midY=((maxY-minY)*.5)+minY;

for(int i=0; i
point3f = plaPts[i];
float x = point3f.x;
float y = point3f.y;
if(x>=0 && y>=0){
point3f.x=((x-(float)Math.abs(midX)));
point3f.y=((y-(float)Math.abs(midY)));
}
if(x>=0 && y<=0){
point3f.x=(x-(float)Math.abs(midX));
point3f.y=(y+(float)Math.abs(midY));
}
if(x<=0 && y<=0){
point3f.x=(x+(float)Math.abs(midX));
point3f.y=(y+(float)Math.abs(midY));
}
if(x<=0 && y>=0){
point3f.x=(x+(float)Math.abs(midX));
point3f.y=(y-(float)Math.abs(midY));
}

point3f.z=point3f.z*4;
plaPts[i]=point3f;
}
}

ogoto1
Offline
Joined: 2010-03-02

On the point3f.x, point3f.y, and point3f.z may have to define as point3f.getX(), point3f.getY(), and point3f.getZ().

Also I do a magnification of point3f.z*4 to give a little more significant z display.

aces
Offline
Joined: 2003-07-17

Why you just translate your object forward OR move your viewing platform (camera) backward ?

This is much easier than messing geometry Z coordinates.

aces
Offline
Joined: 2003-07-17

Tip :

Get Shape3D's bounds as BoundingSphere and get center

[code]
BoundingSphere bounds = new BoundingSphere(shape.getBounds());

Point3d center = new Point3d();

bounds.getCenter(center);
[/code]

========
tip fixed

Message was edited by: aces

ogoto1
Offline
Joined: 2010-03-02

The first part of my question has been answered for the Centroid. Thank you so much!
I'm still having an issue with scale.

In order to get points like below to display in the Frame I have to do something like this:
transform3D.setTranslation(new Vector3f(0f,0f,-50f));
transform3D.setScale(.02);

x: 243.82 y: -91.69 z: 202.82
x: 280.68 y: 23.66 z: 223.56
x: 318.31 y: -94.01 z: 211.72
x: 333.99 y: 170.48 z: 237.24
x: 350.37 y: 43.54 z: 236.54
x: 408.82 y: -93.34 z: 217.41
x: 421.91 y: 45.18 z: 244.07
x: 430.78 y: -20.32 z: 232.19

What is the proper way to get scale?
Thank you again for the Center code!

aces
Offline
Joined: 2003-07-17

For scaling, use boundingSphere.getRadious().

something like :
[code]
// 0.95d gives some border space
double scale = 0.95d / boundingSphere.getRadious();

[/code]

ogoto1
Offline
Joined: 2010-03-02

Aces:
I really appreciate your help. I did the following based on your correct suggestion to get the scale corrected:

double scale = 0.95d / boundingSphere.getRadius();
transform3D.setScale(scale);

When I first ran the program I got a blank Frame.
Then I did the Left Mouse Button and zoomed out (mouse towards monitor) and the points came into focus.

So I added the following code reran the app and all my points came into focus in the Frame:
transform3D.setTranslation(new Vector3f(0f,0f,-3f));

Is there a way to set the Z of the Vector3f(-3f) to display all the points at optimal focus at initial run time?

aces
Offline
Joined: 2003-07-17

Sorry,

the 0.95d factor is good for "nominal viewing transform", i.e, the
Z distance given by

[code]
// The ViewPlatform is moved back along Z so that objects at the origin spanning the
// normalized X range of -1.0 to +1.0 can be fully viewed across the width of the window.
//This is done by setting a translation of 1/(tan(fieldOfView/2)) in the ViewPlatform transform.
simpleUniverse.getViewingPlatform().setNominalViewingTransform()
[/code]

ogoto1
Offline
Joined: 2010-03-02

Aces:

I figure at this point that putting some of my code would be best. What I did is take my larger example and break it down into a smaller example so that I don't clutter the forum. I left off the Imports from the example to make it smaller. I would appreciate it if you would take a minute to look at my code.

The following is my radius, center, and scale at run time.

Radius: 210.34576154023407
center: (5705.945068359375, 3606.2099609375, 77.66500091552734)
scale: 0.004516373389431419

The following is my code excluding imports:
public class PlotData extends Frame {

public static void main(String args[]) {
PlotData plotData = new PlotData();

}

public PlotData() {
super("Java Plot");
setSize(400, 300);
GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();

Canvas3D canvas3D = new Canvas3D(config);
add("Center", canvas3D);
setVisible(true);

addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
});

SimpleUniverse universe = new SimpleUniverse(canvas3D);
BranchGroup contentBranchGroup = constructContentBranch();
universe.getViewingPlatform().setNominalViewingTransform();
universe.addBranchGraph(contentBranchGroup);
}

private BranchGroup constructContentBranch() {
BranchGroup objRoot = new BranchGroup();

Transform3D transform3D = new Transform3D();
transform3D.setIdentity();
TransformGroup cubeTransformGroup = new TransformGroup();
cubeTransformGroup.setTransform(transform3D);
cubeTransformGroup.setBoundsAutoCompute(true);
cubeTransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
cubeTransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);

int pointMax = 11;
Point3f[] plaPts = new Point3f[pointMax];
plaPts[0]= new Point3f((float) 5914.92, (float) 3582.93,(float) 71.93);
plaPts[1]= new Point3f((float) 5867.26, (float) 3588.81,(float) 73.48);
plaPts[2]= new Point3f((float) 5820.15, (float) 3589.81,(float) 73.63);
plaPts[3]= new Point3f((float) 5774.16, (float) 3593.38,(float) 74.23);
plaPts[4]= new Point3f((float) 5724.52, (float) 3598.34,(float) 75.28);
plaPts[5]= new Point3f((float) 5676.14, (float) 3600.67,(float) 76.52);
plaPts[6]= new Point3f((float) 5625.73, (float) 3604.85,(float) 78.12);
plaPts[7]= new Point3f((float) 5577.06, (float) 3608.36,(float) 80.1);
plaPts[8]= new Point3f((float) 5528.57, (float) 3611.69,(float) 82.32);
plaPts[9]= new Point3f((float) 5496.97, (float) 3614.09,(float) 83.4);
plaPts[10]= new Point3f((float) 5884.07, (float) 3629.49,(float) 73.23);

Color3f white = new Color3f(1.0f, 1.0f, 10.0f);
Appearance app = new Appearance();
ColoringAttributes ca = new ColoringAttributes(white, ColoringAttributes.SHADE_FLAT);
app.setColoringAttributes(ca);

PointArray pp = new PointArray(pointMax, GeometryArray.COORDINATES);
pp.setCoordinates(0, plaPts);
Shape3D ppShape = new Shape3D(pp, app);
cubeTransformGroup.addChild(ppShape);

objRoot.addChild(cubeTransformGroup);

BoundingSphere boundingSphere = new BoundingSphere(objRoot.getBounds());

Point3d center = new Point3d();
boundingSphere.getCenter(center);
double scale = 0.95d / boundingSphere.getRadius();
transform3D.setScale(scale);
cubeTransformGroup.setTransform(transform3D);

MouseRotate myMouseRotate = new MouseRotate();
myMouseRotate.setTransformGroup(cubeTransformGroup);
myMouseRotate.setSchedulingBounds(boundingSphere);
objRoot.addChild(myMouseRotate);

MouseTranslate myMouseTranslate = new MouseTranslate();
myMouseTranslate.setTransformGroup(cubeTransformGroup);
myMouseTranslate.setSchedulingBounds(boundingSphere);
objRoot.addChild(myMouseTranslate);

MouseZoom myMouseZoom = new MouseZoom();
myMouseZoom.setTransformGroup(cubeTransformGroup);
myMouseZoom.setSchedulingBounds(boundingSphere);
objRoot.addChild(myMouseZoom);

return objRoot;
}
}

ogoto1
Offline
Joined: 2010-03-02

It appears that the Radius is not being calculated correctly.

I forced the radius to 6000 and the points appeared in the + + Quadrant in the upper right corner:
boundingSphere.setRadius(6000);

Then I did the following:
1) changed:
int pointMax = 11;
to:
int pointMax = 22;
2) added the following to the array:
plaPts[11]= new Point3f((float) -5914.92, (float) -3582.93,(float) 71.93);
plaPts[12]= new Point3f((float) -5867.26, (float) -3588.81,(float) 73.48);
plaPts[13]= new Point3f((float) -5820.15, (float) -3589.81,(float) 73.63);
plaPts[14]= new Point3f((float) -5774.16, (float) -3593.38,(float) 74.23);
plaPts[15]= new Point3f((float) -5724.52, (float) -3598.34,(float) 75.28);
plaPts[16]= new Point3f((float) -5676.14, (float) -3600.67,(float) 76.52);
plaPts[17]= new Point3f((float) -5625.73, (float) -3604.85,(float) 78.12);
plaPts[18]= new Point3f((float) -5577.06, (float) -3608.36,(float) 80.1);
plaPts[19]= new Point3f((float) -5528.57, (float) -3611.69,(float) 82.32);
plaPts[20]= new Point3f((float) -5496.97, (float) -3614.09,(float) 83.4);
plaPts[21]= new Point3f((float) -5705.94, (float) -3606.20,(float) 77.66);
3) commented:
//boundingSphere.setRadius(6000);

When running the radius, scale, and center are calculated correctly. It appears that +,- numbers are required for proper radius calculation:
radius: 6931.663417666428
scale: 1.370522402427643E-4
center: (0.0, 0.0, 77.66500091552734)

I will be curious as to what magic you have to solve this problem.

darwinjob
Offline
Joined: 2004-11-16

Sorry, but isn't it better to move the camera instead of modifying the data?

ogoto1
Offline
Joined: 2010-03-02

Do you have an example code snipped for setting up the camera? It seems like my code collapses when I add it in.