/* Copyright 2008-2010 Gephi Authors : Mathieu Bastian <mathieu.bastian@gephi.org> Website : http://www.gephi.org This file is part of Gephi. Gephi is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Gephi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with Gephi. If not, see <http://www.gnu.org/licenses/>. */ package org.gephi.visualization.opengl.compatibility.objects; import com.sun.opengl.util.BufferUtil; import java.nio.FloatBuffer; import javax.media.opengl.GL; import javax.media.opengl.glu.GLU; import org.gephi.graph.api.EdgeData; import org.gephi.graph.api.NodeData; import org.gephi.visualization.VizModel; import org.gephi.visualization.apiimpl.ModelImpl; import org.gephi.lib.gleem.linalg.Vec3f; import org.gephi.lib.gleem.linalg.Vecf; import org.gephi.visualization.GraphLimits; import org.gephi.visualization.opengl.octree.Octant; /** * * @author Mathieu Bastian */ public class SelfLoop2dModel extends Edge2dModel { private static Vec3f upVector = new Vec3f(0f, 1f, 0f); private static Vec3f sideVector = new Vec3f(1f, 0f, 0f); protected static FloatBuffer buffer = BufferUtil.newFloatBuffer(24); public int segments = 20; public SelfLoop2dModel() { octants = new Octant[1]; } @Override public void display(GL gl, GLU glu, VizModel vizModel) { gl.glEnd(); //Edge weight GraphLimits limits = vizModel.getLimits(); float weightRatio; if (limits.getMinWeight() == limits.getMaxWeight()) { weightRatio = Edge2dModel.WEIGHT_MINIMUM / limits.getMinWeight(); } else { weightRatio = Math.abs((Edge2dModel.WEIGHT_MAXIMUM - Edge2dModel.WEIGHT_MINIMUM) / (limits.getMaxWeight() - limits.getMinWeight())); } float w = weight; float edgeScale = vizModel.getEdgeScale(); w = ((w - limits.getMinWeight()) * weightRatio + Edge2dModel.WEIGHT_MINIMUM) * edgeScale; // //Params NodeData node = obj.getSource(); float x = node.x(); float y = node.y(); float z = node.z(); //Get thickness points float baseRightX = x + sideVector.x() * w / 2; float baseRightY = y + sideVector.y() * w / 2; float baseRightZ = z + sideVector.z() * w / 2; float baseLeftX = x - sideVector.x() * w / 2; float baseLeftY = y - sideVector.y() * w / 2; float baseLeftZ = z - sideVector.z() * w / 2; float baseTopX = x + upVector.x() * w / 2; float baseTopY = y + upVector.y() * w / 2; float baseTopZ = z + upVector.z() * w / 2; float baseBottomX = x - upVector.x() * w / 2; float baseBottomY = y - upVector.y() * w / 2; float baseBottomZ = z - upVector.z() * w / 2; //Calculate control points float height = node.getRadius() * 3; float controlExterior1X = baseLeftX + upVector.x() * height; float controlExterior1Y = baseLeftY + upVector.y() * height; float controlExterior1Z = baseLeftZ + upVector.z() * height; float controlExterior2X = baseBottomX + sideVector.x() * height; float controlExterior2Y = baseBottomY + sideVector.y() * height; float controlExterior2Z = baseBottomZ + sideVector.z() * height; height /= 1.15f; float controlInterior1X = baseRightX + upVector.x() * height; float controlInterior1Y = baseRightY + upVector.y() * height; float controlInterior1Z = baseRightZ + upVector.z() * height; float controlInterior2X = baseTopX + sideVector.x() * height; float controlInterior2Y = baseTopY + sideVector.y() * height; float controlInterior2Z = baseTopZ + sideVector.z() * height; //Fill buffer with interior curve buffer.rewind(); buffer.put(baseRightX); buffer.put(baseRightY); buffer.put(baseRightZ); buffer.put(controlInterior1X); buffer.put(controlInterior1Y); buffer.put(controlInterior1Z); buffer.put(controlInterior2X); buffer.put(controlInterior2Y); buffer.put(controlInterior2Z); buffer.put(baseTopX); buffer.put(baseTopY); buffer.put(baseTopZ); //Fill buffer with exterior curve buffer.put(baseLeftX); buffer.put(baseLeftY); buffer.put(baseLeftZ); buffer.put(controlExterior1X); buffer.put(controlExterior1Y); buffer.put(controlExterior1Z); buffer.put(controlExterior2X); buffer.put(controlExterior2Y); buffer.put(controlExterior2Z); buffer.put(baseBottomX); buffer.put(baseBottomY); buffer.put(baseBottomZ); buffer.rewind(); //Rewind //Color if (!selected) { float r; float g; float b; float a; if (vizModel.isEdgeHasUniColor()) { float[] uni = vizModel.getEdgeUniColor(); r = uni[0]; g = uni[1]; b = uni[2]; a = uni[3]; } else { r = obj.r(); if (r == -1f) { NodeData source = obj.getSource(); r = 0.498f * source.r(); g = 0.498f * source.g(); b = 0.498f * source.b(); a = obj.alpha(); } else { g = 0.498f * obj.g(); b = 0.498f * obj.b(); r *= 0.498f; a = obj.alpha(); } } if (vizModel.getConfig().isLightenNonSelected()) { float lightColorFactor = vizModel.getConfig().getLightenNonSelectedFactor(); a = a - (a - 0.01f) * lightColorFactor; gl.glColor4f(r, g, b, a); } else { gl.glColor4f(r, g, b, a); } } else { float r = 0f; float g = 0f; float b = 0f; if (vizModel.isEdgeSelectionColor()) { ModelImpl m1 = (ModelImpl) obj.getSource().getModel(); ModelImpl m2 = (ModelImpl) obj.getTarget().getModel(); if (m1.isSelected() && m2.isSelected()) { float[] both = vizModel.getEdgeBothSelectionColor(); r = both[0]; g = both[1]; b = both[2]; } else if (m1.isSelected()) { float[] out = vizModel.getEdgeOutSelectionColor(); r = out[0]; g = out[1]; b = out[2]; } else if (m2.isSelected()) { float[] in = vizModel.getEdgeInSelectionColor(); r = in[0]; g = in[1]; b = in[2]; } } else { r = obj.r(); if (r == -1f) { NodeData source = obj.getSource(); r = source.r(); g = source.g(); b = source.b(); } else { g = obj.g(); b = obj.b(); } } gl.glColor4f(r, g, b, 1f); } //Display gl.glMap2f(GL.GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 2, buffer); //Map evaluators gl.glEnable(GL.GL_MAP2_VERTEX_3); gl.glMapGrid2f(segments, 0, 1, 1, 0, 1); //Grid gl.glEvalMesh2(GL.GL_FILL, 0, segments, 0, 1); //Display gl.glDisable(GL.GL_MAP2_VERTEX_3); gl.glEnd(); gl.glBegin(GL.GL_TRIANGLES); } @Override public float getCollisionDistance(double angle) { // TODO Auto-generated method stub return 0; } @Override public boolean isInOctreeLeaf(Octant leaf) { return ((ModelImpl) obj.getSource().getModel()).getOctants()[0] == leaf; } @Override public int[] octreePosition(float centerX, float centerY, float centerZ, float size) { return new int[] {}; } @Override public boolean selectionTest(Vecf distanceFromMouse, float selectionSize) { // TODO Auto-generated method stub return false; } @Override public boolean isAutoSelected() { return obj.getSource().getModel().isSelected(); } @Override public boolean onlyAutoSelect() { return true; } @Override public String toSVG() { // TODO Auto-generated method stub return null; } @Override public void setOctant(Octant octant) { this.octants[0] = octant; } @Override public Octant[] getOctants() { if (this.octants[0] == null) { Octant[] oc = ((ModelImpl) obj.getSource().getModel()).getOctants(); return oc; } return this.octants; } @Override public boolean isValid() { return octants != null && octants[0] != null; } @Override public void resetOctant() { if (this.octants != null) { this.octants[0] = null; } } }