/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package automenta.vivisect.graph;
import automenta.vivisect.Vis;
import automenta.vivisect.graph.GraphDisplay.Shape;
import static automenta.vivisect.graph.GraphDisplay.Shape.Ellipse;
import automenta.vivisect.swing.PCanvas;
import com.google.common.collect.ClassToInstanceMap;
import com.google.common.collect.MutableClassToInstanceMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import processing.core.PGraphics;
/**
*
* @author me
*/
public class VertexVis<V, E> {
public final V vertex;
public float x;
public float y;
public float tx;
public float ty;
public float radius;
public float stroke;
public float scale;
public String label;
public int color;
public int textColor;
public float textScale;
public int strokeColor;
public Set<E> edges;
public Shape shape;
public float speed;
public ClassToInstanceMap<Object> props;
public List<Vis> children = null;
private final PCanvas canvas;
public VertexVis(PCanvas canvas, V o) {
this.canvas = canvas;
this.vertex = o;
x = (float) Math.random();
y = (float) Math.random();
tx = x;
ty = y;
stroke = 0;
strokeColor = 0;
speed = 0.9f;
scale = 1f;
textScale = 1f;
}
@Override
public String toString() {
return "vis[" + vertex.toString() + "]";
}
@Override
public int hashCode() {
return vertex.hashCode();
}
@Override
public boolean equals(Object obj) {
return vertex.equals(obj);
}
public boolean draw(final AbstractGraphVis c, final PGraphics p) {
boolean needsUpdate = update(c);
//System.out.println(radius + " " + color + " " + label + " " + x + " " + y);
float r = radius * scale;
if (r == 0) {
return needsUpdate;
}
if (stroke > 0) {
p.stroke(strokeColor);
p.strokeWeight(stroke * scale);
}
p.fill(color); //, alpha * 255 / 2);
if (shape == null) shape = Ellipse;
switch (shape) {
case Rectangle:
p.rect(x * scale - r / 2f, y * scale - r / 2f, r, r);
break;
case Ellipse:
default:
p.ellipse(x * scale, y * scale, r, r);
break;
}
if ((label != null) && (textScale > 0)) {
p.fill(textColor); //, alpha * 255 * 0.75f);
p.textSize(r / 2f * textScale);
p.text(label, x * scale, y * scale);
}
if (stroke > 0) {
//reset stroke
p.noStroke();
}
if ((children!=null) && (!children.isEmpty())) {
p.pushMatrix();
p.translate(x*scale, y*scale);
p.scale(radius/32f, radius/32f);
for (int i = 0; i < children.size(); i++) {
final Vis child = children.get(i);
child.draw(p);
}
p.popMatrix();
}
return needsUpdate;
}
protected boolean update(AbstractGraphVis c) {
if (this.edges == null) {
if (c.currentGraph != null) {
this.edges = c.currentGraph.edgesOf(vertex);
}
}
x = (x * (1.0f - speed) + tx * (speed));
y = (y * (1.0f - speed) + ty * (speed));
if ((Math.abs(tx - x) + Math.abs(ty - y)) > AbstractGraphVis.vertexTargetThreshold) {
//keep animating if any vertex hasnt reached its target
return false;
}
return true;
}
public Set<E> getEdges() {
return edges;
}
public V getVertex() {
return vertex;
}
// void update(final V o) {
// GraphDisplay<V, E> d = canvas.display;
// this.edges = null;
// this.textColor = d.getTextColor(o);
// this.radius = d.getVertexSize(o);
// this.color = d.getVertexColor(o);
// this.label = d.getVertexLabel(o);
// this.stroke = d.getVertexStroke(o);
// this.strokeColor = d.getVertexStrokeColor(o);
// }
public void setPosition(final float x, final float y) {
this.tx = x;
this.ty = y;
}
public void movePosition(final float dx, final float dy) {
this.tx += dx;
this.ty += dy;
}
public float getX() {
return tx;
}
public float getY() {
return ty;
}
public float getRadius() {
return radius;
}
public void addChild(Vis v) {
if (children == null)
children = new ArrayList();
children.add(v);
v.init(canvas);
}
public <C extends Object> C the(Class<C> c) {
if (props == null)
return null;
return props.getInstance(c);
}
public <D extends Object> void the(Class<D> key, D value) {
if (props == null)
props = MutableClassToInstanceMap.create();
props.putInstance(key, value);
}
}