use of de.lmu.ifi.dbs.elki.visualization.parallel3d.layout.Layout.Node in project elki by elki-project.
the class Parallel3DRenderer method renderLabels.
private void renderLabels(GL2 gl, IntIntPair[] edgesort) {
shared.textrenderer.begin3DRendering();
// UNDO the camera rotation. This will mess up text orientation!
gl.glRotatef((float) MathUtil.rad2deg(shared.camera.getRotationZ()), 0.f, 0.f, 1.f);
// Rotate to have the text face the camera direction, which looks +Y
// While the text will be visible from +Z and +Y is baseline.
gl.glRotatef(90.f, 1.f, 0.f, 0.f);
// HalfPI: 180 degree extra rotation, for text orientation.
double cos = FastMath.cos(shared.camera.getRotationZ()), sin = FastMath.sin(shared.camera.getRotationZ());
shared.textrenderer.setColor(0.0f, 0.0f, 0.0f, 1.0f);
float defaultscale = .01f / (float) FastMath.sqrt(shared.dim);
// TODO: div depth?
final float targetwidth = .2f;
// Assume all text is at least this width
final float minratio = 8.f;
for (int i = 0; i < shared.dim; i++) {
if (shared.labels[i] != null) {
Rectangle2D b = shared.textrenderer.getBounds(shared.labels[i]);
float scale = defaultscale;
if (Math.max(b.getWidth(), b.getHeight() * minratio) * scale > targetwidth) {
scale = targetwidth / (float) Math.max(b.getWidth(), b.getHeight() * minratio);
}
float w = (float) b.getWidth() * scale;
// Rotate manually, in x-z plane
float x = (float) (cos * shared.layout.getNode(i).getX() + sin * shared.layout.getNode(i).getY());
float y = (float) (-sin * shared.layout.getNode(i).getX() + cos * shared.layout.getNode(i).getY());
shared.textrenderer.draw3D(shared.labels[i], (x - w * .5f), 1.01f, -y, scale);
}
}
// Show depth indexes on debug:
if (OpenGL3DParallelCoordinates.Instance.DEBUG) {
shared.textrenderer.setColor(1f, 0f, 0f, 1f);
for (IntIntPair pair : edgesort) {
Layout.Edge edge = shared.layout.edges.get(pair.second);
final Node node1 = shared.layout.getNode(edge.dim1);
final Node node2 = shared.layout.getNode(edge.dim2);
final double mx = 0.5 * (node1.getX() + node2.getX());
final double my = 0.5 * (node1.getY() + node2.getY());
// Rotate manually, in x-z plane
float x = (float) (cos * mx + sin * my);
float y = (float) (-sin * mx + cos * my);
shared.textrenderer.draw3D(Integer.toString(pair.first), (x - defaultscale * .5f), 1.01f, -y, .5f * defaultscale);
}
}
shared.textrenderer.end3DRendering();
}
use of de.lmu.ifi.dbs.elki.visualization.parallel3d.layout.Layout.Node in project elki by elki-project.
the class Parallel3DRenderer method drawParallelPlot.
protected void drawParallelPlot(GLAutoDrawable drawable, GL2 gl) {
// Sort axes by sq. distance from camera, front-to-back:
sortAxes();
// Sort edges by the maximum (foreground) index.
IntIntPair[] edgesort = sortEdges(dindex);
if (textures != null) {
gl.glShadeModel(GL2.GL_FLAT);
// Render spider web:
// outside glBegin!
gl.glLineWidth(shared.settings.linewidth);
gl.glBegin(GL.GL_LINES);
gl.glColor4f(0f, 0f, 0f, 1f);
for (Layout.Edge edge : shared.layout.edges) {
Node n1 = shared.layout.getNode(edge.dim1), n2 = shared.layout.getNode(edge.dim2);
gl.glVertex3d(n1.getX(), n1.getY(), 0f);
gl.glVertex3d(n2.getX(), n2.getY(), 0f);
}
gl.glEnd();
// Draw axes and 3DPC:
for (int i = 0; i < shared.dim; i++) {
final int d = axes[i].second;
final Node node1 = shared.layout.getNode(d);
// Draw edge textures
for (IntIntPair pair : edgesort) {
// Not yet available?
if (pair.second >= completedTextures) {
continue;
}
// Other axis must have a smaller index.
if (pair.first >= i) {
continue;
}
Layout.Edge edge = shared.layout.edges.get(pair.second);
// Must involve the current axis.
if (edge.dim1 != d && edge.dim2 != d) {
continue;
}
int od = axes[pair.first].second;
gl.glEnable(GL.GL_TEXTURE_2D);
gl.glColor4f(1f, 1f, 1f, 1f);
final Node node2 = shared.layout.getNode(od);
gl.glBindTexture(GL.GL_TEXTURE_2D, textures[pair.second]);
gl.glBegin(GL2.GL_QUADS);
gl.glTexCoord2d((edge.dim1 == d) ? 0f : 1f, 0f);
gl.glVertex3d(node1.getX(), node1.getY(), 0f);
gl.glTexCoord2d((edge.dim1 == d) ? 0f : 1f, 1f);
gl.glVertex3d(node1.getX(), node1.getY(), 1f);
gl.glTexCoord2d((edge.dim1 != d) ? 0f : 1f, 1f);
gl.glVertex3d(node2.getX(), node2.getY(), 1f);
gl.glTexCoord2d((edge.dim1 != d) ? 0f : 1f, 0f);
gl.glVertex3d(node2.getX(), node2.getY(), 0f);
gl.glEnd();
gl.glDisable(GL.GL_TEXTURE_2D);
}
// Draw axis
// outside glBegin!
gl.glLineWidth(shared.settings.linewidth);
gl.glBegin(GL.GL_LINES);
gl.glColor4f(0f, 0f, 0f, 1f);
gl.glVertex3d(node1.getX(), node1.getY(), 0f);
gl.glVertex3d(node1.getX(), node1.getY(), 1f);
gl.glEnd();
// Draw ticks.
LinearScale scale = shared.proj.getAxisScale(d);
gl.glPointSize(shared.settings.linewidth * 2f);
gl.glBegin(GL.GL_POINTS);
for (double tick = scale.getMin(); tick <= scale.getMax() + scale.getRes() / 10; tick += scale.getRes()) {
gl.glVertex3d(node1.getX(), node1.getY(), scale.getScaled(tick));
}
gl.glEnd();
}
}
// Render labels
renderLabels(gl, edgesort);
}
Aggregations