Author: paperwing
Date: 2011-07-07 06:56:26 -0700 (Thu, 07 Jul 2011)
New Revision: 26098
Modified:
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/Graphics.java
Log:
added edge selection/deletion, updated method for adding edges in between the
same pair of nodes
Modified:
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/Graphics.java
===================================================================
---
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/Graphics.java
2011-07-07 00:35:03 UTC (rev 26097)
+++
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/Graphics.java
2011-07-07 13:56:26 UTC (rev 26098)
@@ -55,27 +55,6 @@
private static final int EDGE_SLICES_DETAIL = 4;
private static final int EDGE_STACKS_DETAIL = 1;
- private class DrawnNode {
- public float x;
- public float y;
- public float z;
- }
-
- private class DrawnEdge {
- public float x;
- public float y;
- public float z;
- public float rotateAxisX;
- public float rotateAxisY;
- public float rotateAxisZ;
- public float rotateAngle;
- public float length;
- }
-
- private DrawnNode[] nodes;
- private DrawnNode testNode = new DrawnNode();
- private DrawnEdge[] edges;
-
private int nodeListIndex;
private int edgeListIndex;
@@ -91,11 +70,24 @@
private int edgeSeed = 556;
private LinkedHashSet<CyNode> selectedNodes;
+ private LinkedHashSet<CyEdge> selectedEdges;
+
private TreeSet<Integer> selectedNodeIndices;
+ private TreeSet<Integer> selectedEdgeIndices;
- private static final int NO_INDEX = -1; // Value representing that no
node index is being held
- private int hovered = NO_INDEX;
+ // TODO: NO_INDEX relies on cytoscape's guarantee that node and edge
indices are nonnegative
+ private static final int NO_INDEX = -1; // Value representing that no
node or edge index is being held
+ private int hoveredNode = NO_INDEX;
+ private int hoveredEdge = NO_INDEX;
+ private static enum StateModifier {
+ HOVERED, SELECTED, NORMAL, ENLARGED
+ }
+
+ private static final int NO_TYPE = -1;
+ private static final int NODE_TYPE = 0;
+ private static final int EDGE_TYPE = 1;
+
private KeyboardMonitor keys;
private MouseMonitor mouse;
private SimpleCamera camera;
@@ -108,6 +100,8 @@
private CyNetworkView networkView;
private VisualLexicon visualLexicon;
+ private boolean latch_1;
+
public static void initSingleton() {
GLProfile.initSingleton(false);
System.out.println("initSingleton called");
@@ -125,7 +119,10 @@
this.visualLexicon = visualLexicon;
selectedNodes = new LinkedHashSet<CyNode>();
+ selectedEdges = new LinkedHashSet<CyEdge>();
+
selectedNodeIndices = new TreeSet<Integer>();
+ selectedEdgeIndices = new TreeSet<Integer>();
}
public void trackInput(Component component) {
@@ -190,8 +187,8 @@
gl.glPopMatrix();
float[] lightPosition = { -4.0f, 4.0f, 6.0f, 1.0f };
- gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION,
- FloatBuffer.wrap(lightPosition));
+// gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION,
+// FloatBuffer.wrap(lightPosition));
gl.glColor3f(0.6f, 0.6f, 0.6f);
// gl.glTranslatef(0.0f, 0.0f, -6.0f);
@@ -201,7 +198,7 @@
gl.glColor3f(0.51f, 0.51f, 0.53f);
//gl.glColor3f(0.53f, 0.53f, 0.55f);
//gl.glColor3f(0.73f, 0.73f, 0.73f);
- drawEdges(gl);
+ drawEdges(gl, StateModifier.NORMAL);
framesElapsed++;
}
@@ -239,6 +236,10 @@
System.out.println("===");
}
+ if (pressed.contains(KeyEvent.VK_1)) {
+ latch_1 = true;
+ }
+
if (held.contains(KeyEvent.VK_Z)) {
camera.rollClockwise();
}
@@ -359,7 +360,7 @@
}
if (pressed.contains(KeyEvent.VK_J)) {
- CyNode hoverNode =
networkView.getModel().getNode(hovered);
+ CyNode hoverNode =
networkView.getModel().getNode(hoveredNode);
if (hoverNode != null) {
@@ -373,7 +374,7 @@
}
if (pressed.contains(KeyEvent.VK_O)) {
- CyNode hoverNode =
networkView.getModel().getNode(hovered);
+ CyNode hoverNode =
networkView.getModel().getNode(hoveredNode);
if (hoverNode != null && selectedNodes.size()
== 1) {
View<CyNode> hoverView =
networkView.getNodeView(hoverNode);
@@ -426,14 +427,17 @@
}
if
(!networkView.getModel().removeNodes(selectedNodes)) {
- System.out.println("Failed to deleted
nodes: " + selectedNodes);;
+ // do nothing
} else {
// Remove edges attached to the node
networkView.getModel().removeEdges(edgesToBeRemoved);
-
- // TODO: Not sure if this call is needed
- networkView.updateView();
- }
+ }
+
+ // Remove selected edges
+
networkView.getModel().removeEdges(selectedEdges);
+
+ // TODO: Not sure if this call is needed
+ networkView.updateView();
}
keys.update();
@@ -516,11 +520,23 @@
*/
// System.out.println("Mouse is at: (" + mouse.x() + ",
" + mouse.y() + ")");
-
- int result = performPick(gl, mouse.x(), mouse.y());
- hovered = result;
+ int[] pickResult = performPick(gl, mouse.x(),
mouse.y());
+ int pickType = pickResult[0];
+ int pickIndex = pickResult[1];
+ if (pickType == NODE_TYPE) {
+ hoveredNode = pickResult[1];
+ hoveredEdge = NO_INDEX;
+ } else if (pickType == EDGE_TYPE) {
+ hoveredNode = NO_INDEX;
+ hoveredEdge = pickResult[1];
+ } else {
+ // Note that if these 2 lines are removed,
hovering will be "sticky" in that hovering remains unless a new object is
hovered
+ hoveredNode = NO_INDEX;
+ hoveredEdge = NO_INDEX;
+ }
+
if (mouse.getPressed().contains(MouseEvent.BUTTON1)) {
// If control was pressed, prepare to add a node
@@ -537,34 +553,58 @@
viewAdded.setVisualProperty(RichVisualLexicon.NODE_Y_LOCATION, projection.y() *
DISTANCE_SCALE);
viewAdded.setVisualProperty(RichVisualLexicon.NODE_Z_LOCATION, projection.z() *
DISTANCE_SCALE);
- // Update the hovered node
+ // Set the node to be hovered
// TODO: This might not be
needed if the node were added through some way other than the mouse
- hovered = added.getIndex();
+ hoveredNode = added.getIndex();
}
- // Otherwise, prepare to select the node
currently under the mouse cursor
+ // Otherwise, prepare to select the node or
edge currently under the mouse cursor
} else {
- CyNode picked =
networkView.getModel().getNode(result);
+ // If the user did not hold down shift,
unselect other objects
+ if
(!keys.getHeld().contains(KeyEvent.VK_SHIFT)) {
+ selectedNodes.clear();
+ selectedEdges.clear();
+
+ selectedNodeIndices.clear();
+ selectedEdgeIndices.clear();
+
+ //
System.out.println("Selection reset");
+ }
- // TODO: Perhaps throw exception if the
node was found to be null, ie. invalid index
- // Note though the above case could
also be caused by picked == NO_INDEX
- if (picked != null) {
-
- // If the user did not hold
down shift, unselect other nodes
- if
(!keys.getHeld().contains(KeyEvent.VK_SHIFT)) {
+ if (pickType == NODE_TYPE) {
+ CyNode picked =
networkView.getModel().getNode(pickIndex);
+
+ // TODO: Possibly throw
exception if the node was found to be null, ie. invalid index
+ if (picked != null) {
+
+ if
(selectedNodes.contains(picked)) {
+
selectedNodes.remove(picked);
+
selectedNodeIndices.remove(picked.getIndex());
+ } else {
+
selectedNodes.add(picked);
+
selectedNodeIndices.add(picked.getIndex());
+ }
- selectedNodes.clear();
-
selectedNodeIndices.clear();
+ //
ystem.out.println("Selected node index: " + picked.getIndex());
}
+ } else if (pickType == EDGE_TYPE) {
+ CyEdge picked =
networkView.getModel().getEdge(pickIndex);
- if
(selectedNodes.contains(picked)) {
-
selectedNodes.remove(picked);
-
selectedNodeIndices.remove(picked.getIndex());
- } else {
-
selectedNodes.add(picked);
-
selectedNodeIndices.add(picked.getIndex());
+ // TODO: Possibly throw
exception if the edge was found to be null, ie. invalid index
+ if (picked != null) {
+
+ if
(selectedEdges.contains(picked)) {
+
selectedEdges.remove(picked);
+
selectedEdgeIndices.remove(picked.getIndex());
+ } else {
+
selectedEdges.add(picked);
+
selectedEdgeIndices.add(picked.getIndex());
+ }
+
+ //
System.out.println("Selected edge index: " + picked.getIndex());
}
+ } else {
- System.out.println("Selected
node index: " + picked.getIndex());
+ // System.out.println("Nothing
selected");
}
}
}
@@ -573,13 +613,11 @@
}
}
- private int performPick(GL2 gl, double x, double y) {
+ private int[] performPick(GL2 gl, double x, double y) {
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(256);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
- // byteBuffer.
IntBuffer buffer = byteBuffer.asIntBuffer();
- // int buffer[] = new int[256];
IntBuffer viewport = IntBuffer.allocate(4);
gl.glGetIntegerv(GL2.GL_VIEWPORT, viewport);
@@ -593,15 +631,13 @@
GLU glu = new GLU();
gl.glLoadIdentity();
- // System.out.println("viewport: " + viewport.get(0) + ", " +
viewport.get(1) +
- // ", " + viewport.get(2) + ", " + viewport.get(3));
glu.gluPickMatrix(x, screenHeight - y, 2, 2, viewport);
glu.gluPerspective(45.0f, (float) screenWidth / screenHeight, 0.2f,
50.0f);
// don't think this ortho call is needed
// gl.glOrtho(0.0, 8.0, 0.0, 8.0, -0.5, 2.5);
- //draw start
+ // -Begin Drawing-
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
@@ -614,13 +650,26 @@
glu.gluLookAt(position.x(), position.y(), position.z(),
target.x(),
target.y(), target.z(), up.x(), up.y(), up.z());
+ gl.glPushName(NODE_TYPE);
gl.glPushName(NO_INDEX);
+
+ // Render nodes for picking
drawNodes(gl);
- //drawEdges(gl);
- //gl.glPopMatrix();
- //draw end
+ gl.glPopName();
+ gl.glPopName();
+ gl.glPushName(EDGE_TYPE);
+ gl.glPushName(NO_INDEX);
+
+ // Render edges for picking
+ drawEdges(gl, StateModifier.ENLARGED);
+
+ gl.glPopName();
+ gl.glPopName();
+
+ // -End Drawing-
+
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glPopMatrix();
@@ -633,26 +682,41 @@
// System.out.println("Number of hits: " + hits);
int selected;
+ int selectedType;
+ // Current hit record is size 5 because we have (numNames, minZ,
maxZ, name1, name2) for
+ // indices 0-4 respectively
+ int sizeOfHitRecord = 5;
+
if (hits > 0) {
// The variable max helps keep track of the polygon
that is closest
// to the front of the screen
int max = buffer.get(2);
- selected = buffer.get(3);
+ int maxType = buffer.get(3);
+ selectedType = buffer.get(3);
+ selected = buffer.get(4);
+
for (int i = 0; i < hits; i++) {
- if (buffer.get(i * 4 + 2) < max) {
- max = buffer.get(i * 4 + 2);
- selected = buffer.get(i * 4 + 3);
+ if (buffer.get(i * sizeOfHitRecord + 2) <= max &&
buffer.get(i * sizeOfHitRecord + 3) <= maxType) {
+ max = buffer.get(i * sizeOfHitRecord + 2);
+ maxType = buffer.get(i * sizeOfHitRecord + 3);
+
+ selectedType = buffer.get(i * sizeOfHitRecord +
3); // We have that name1 represents the object type
+ selected = buffer.get(i * sizeOfHitRecord + 4);
// name2 represents the object index
}
}
} else {
+ selectedType = NO_TYPE;
selected = NO_INDEX;
}
-
- return selected;
-
+
+ int[] result = new int[2];
+ result[0] = selectedType;
+ result[1] = selected;
+
+ return result;
}
private void drawNodes(GL2 gl) {
@@ -668,35 +732,34 @@
gl.glLoadName(index);
// gl.glLoadName(33);
+ gl.glPushMatrix();
gl.glTranslatef(x, y, z);
if (selectedNodeIndices.contains(index)) {
gl.glColor3f(0.52f, 0.70f, 0.52f);
gl.glScalef(1.1f, 1.1f, 1.1f);
gl.glCallList(nodeListIndex);
- gl.glScalef(1/1.1f, 1/1.1f, 1/1.1f);
- gl.glColor3f(0.73f, 0.73f, 0.73f);
- } else if (index == hovered) {
+ } else if (index == hoveredNode) {
gl.glColor3f(0.52f, 0.52f, 0.70f);
gl.glCallList(nodeListIndex);
+ } else {
gl.glColor3f(0.73f, 0.73f, 0.73f);
- } else {
gl.glCallList(nodeListIndex);
}
- gl.glTranslatef(-x, -y, -z);
+ gl.glPopMatrix();
}
// Draw the testNode
- gl.glTranslatef(testNode.x, testNode.y, testNode.z);
+ // gl.glTranslatef(testNode.x, testNode.y, testNode.z);
// gl.glCallList(nodeListIndex);
// GLUT glut = new GLUT();
// glut.glutSolidCylinder(EDGE_RADIUS, 1,
// EDGE_SLICES_DETAIL, EDGE_STACKS_DETAIL);
- gl.glTranslatef(-testNode.x, -testNode.y, -testNode.z);
+ // gl.glTranslatef(-testNode.x, -testNode.y, -testNode.z);
}
- private void drawEdges(GL2 gl) {
+ private void drawEdges(GL2 gl, StateModifier generalModifier) {
View<CyNode> sourceView;
View<CyNode> targetView;
@@ -719,29 +782,36 @@
Vector3 p1Offset;
Vector3 direction;
+ int edgeIndex;
+
for (View<CyEdge> edgeView : networkView.getEdgeViews()) {
-
+
sourceView =
networkView.getNodeView(edgeView.getModel().getSource());
targetView =
networkView.getNodeView(edgeView.getModel().getTarget());
sourceIndex = sourceView.getModel().getIndex();
targetIndex = targetView.getModel().getIndex();
+ edgeIndex = edgeView.getModel().getIndex();
+
// These indices rely on CyNode's guarantee that
NodeIndex < NumOfNodes
assert sourceIndex < nodeCount;
assert targetIndex < nodeCount;
// Identify this pair of nodes so we'll know if we've
drawn an edge between them before
- if (sourceIndex > targetIndex) {
- pairIdentifier = nodeCount * targetIndex +
targetIndex;
- } else {
- pairIdentifier = nodeCount * sourceIndex +
sourceIndex;
- }
+ pairIdentifier = ((long) Integer.MAX_VALUE + 1) *
sourceIndex + targetIndex; // TODO: Check if this is a safe calculation
+
+ // Unused; this will remove distinguishment between
source and target nodes
+// if (sourceIndex > targetIndex) {
+// pairIdentifier = nodeCount * sourceIndex +
targetIndex;
+// } else {
+// pairIdentifier = nodeCount * targetIndex +
sourceIndex;
+// }
// Have we visited an edge between these nodes before?
if (pairs.containsKey(pairIdentifier)) {
pairs.put(pairIdentifier,
pairs.get(pairIdentifier) + 1);
} else {
- pairs.put(pairIdentifier, 1);
+ pairs.put(pairIdentifier, 0);
}
// Find p0, p1, p2 for the Bezier curve
@@ -762,17 +832,57 @@
p1Offset = direction.cross(0, 1, 0);
p1Offset.normalizeLocal();
+ // Multiplier controlling distance between curve point
p1 and the straight line between the nodes p0 and p2
+ int distanceMultiplier = (int)
Math.sqrt(pairs.get(pairIdentifier));
+
+ int radiusEdgeCount = distanceMultiplier * 2 + 1;
+
+ // Multiplier controlling rotation about the p0p2
vector axis
+ int rotationMultiplier = pairs.get(pairIdentifier);
+
// Shift the square root graph one to the left and one
down to get smoother curves
- p1Offset.multiplyLocal(EDGE_CURVE_FACTOR *
(Math.sqrt(direction.magnitude() + 1) - 1));
+ p1Offset.multiplyLocal(distanceMultiplier *
EDGE_CURVE_FACTOR * (Math.sqrt(direction.magnitude() + 1) - 1)); //TODO: Check
if sqrt is needed
+ if (distanceMultiplier % 2 == 1) {
+ p1Offset = p1Offset.rotate(direction, 2 *
Math.PI * rotationMultiplier / radiusEdgeCount);
+ } else {
+ p1Offset = p1Offset.rotate(direction, 2 *
Math.PI * rotationMultiplier / radiusEdgeCount + Math.PI);
+ }
+
p1.addLocal(p1Offset);
- p1.rotate(direction, 2 * Math.PI *
(pairs.get(pairIdentifier) - 1) / EDGES_PER_RADIUS);
+
+ if (latch_1) {
+ System.out.println("Source index: " +
sourceIndex);
+ System.out.println("Source target: " +
targetIndex);
+ System.out.println("pairs.get(pairIdentifier):
" + pairs.get(pairIdentifier));
+ System.out.println("pairIdentifier: " +
pairIdentifier);
+ }
- drawQuadraticEdge(gl, p0, p1, p2, 4);
+ // Load name for edge picking
+ gl.glLoadName(edgeIndex);
+
+ StateModifier modifier;
+ if (generalModifier == StateModifier.ENLARGED) {
+ modifier = StateModifier.ENLARGED;
+ } else if (selectedEdgeIndices.contains(edgeIndex)) {
+ modifier = StateModifier.SELECTED;
+ } else if (edgeIndex == hoveredEdge) {
+ modifier = StateModifier.HOVERED;
+ } else {
+ modifier = StateModifier.NORMAL;
+ }
+
+ if (distanceMultiplier == 0) {
+ drawQuadraticEdge(gl, p0, p1, p2, 1, modifier);
+ } else {
+ drawQuadraticEdge(gl, p0, p1, p2, 5, modifier);
+ }
}
+
+ latch_1 = false;
}
- private void drawQuadraticEdge(GL2 gl, Vector3 p0, Vector3 p1, Vector3
p2, int numSegments) {
+ private void drawQuadraticEdge(GL2 gl, Vector3 p0, Vector3 p1, Vector3
p2, int numSegments, StateModifier modifier) {
// TODO: Allow the minimum distance to be changed
if (p0.distanceSquared(p2) <
MINIMUM_EDGE_DRAW_DISTANCE_SQUARED) {
return;
@@ -849,7 +959,8 @@
drawSingleEdge(gl,
points[i],
- points[i + 1]);
+ points[i + 1],
+ modifier);
// if (framesElapsed == 3) {
// if
(points[i].subtract(direction.multiply(extend1)).magnitude() > 100) {
@@ -875,28 +986,6 @@
}
- private void drawQuadraticEdgeOld(GL2 gl, Vector3 p0, Vector3 p1,
Vector3 p2, int numSegments) {
- // Equation for Quadratic Bezier curve:
- // B(t) = (1 - t)^2P0 + 2(1 - t)tP1 + t^2P2, t in [0, 1]
-
- double parameter;
-
- Vector3 current = p0;
- Vector3 next;
-
- for (int i = 1; i < numSegments; i++) {
- parameter = (double) i / numSegments;
-
- next = p0.multiply(Math.pow(1 - parameter, 2));
- next.addLocal(p1.multiply(2 * (1 - parameter) *
parameter));
- next.addLocal(p2.multiply(parameter * parameter));
-
- drawSingleEdge(gl, current, next);
-
- current = next;
- }
- }
-
private void drawEdgesOld(GL2 gl) {
View<CyNode> sourceView;
View<CyNode> targetView;
@@ -920,7 +1009,7 @@
}
}
- private void drawSingleEdge(GL2 gl, Vector3 start, Vector3 end) {
+ private void drawSingleEdge(GL2 gl, Vector3 start, Vector3 end,
StateModifier modifier) {
gl.glPushMatrix();
// TODO: Consider using a Vector3f object for just floats, to
use translatef instead of translated
@@ -935,7 +1024,21 @@
rotateAxis.z());
gl.glScalef(1.0f, 1.0f, (float) direction.magnitude());
- gl.glCallList(edgeListIndex);
+
+ if (modifier == StateModifier.ENLARGED) {
+ gl.glScalef(1.6f, 1.6f, 1.0f);
+ gl.glCallList(edgeListIndex);
+ } else if (modifier == StateModifier.SELECTED) {
+ gl.glColor3f(0.45f, 0.65f, 0.45f);
+ gl.glScalef(1.1f, 1.1f, 1.0f);
+ gl.glCallList(edgeListIndex);
+ } else if (modifier == StateModifier.HOVERED) {
+ gl.glColor3f(0.43f, 0.43f, 0.70f);
+ gl.glCallList(edgeListIndex);
+ } else {
+ gl.glColor3f(0.73f, 0.73f, 0.73f);
+ gl.glCallList(edgeListIndex);
+ }
gl.glPopMatrix();
}
--
You received this message because you are subscribed to the Google Groups
"cytoscape-cvs" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/cytoscape-cvs?hl=en.