package nars.gui.output.chart;
import automenta.vivisect.swing.NPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.SwingUtilities;
import nars.util.EventEmitter.EventObserver;
import nars.util.Events;
import nars.NAR;
import nars.entity.Concept;
import nars.entity.Sentence;
import nars.entity.Task;
/**
* 2D bubble chart with configurable dimensions
* TODO reimplement colorization
*/
public class BubbleChart extends NPanel implements EventObserver {
private final NAR nar;
private BufferedImage buffer;
private boolean needsPaint;
public enum Dimension {
One, Time, Frequency, Confidence, Priority, Complexity
}
public Dimension x = Dimension.Frequency;
public Dimension y = Dimension.Confidence;
public Dimension size = Dimension.One;
public BubbleChart(NAR n) {
super(new BorderLayout());
this.nar = n;
}
@Override
protected void onShowing(boolean showing) {
if (showing) {
nar.memory.event.on(Events.FrameEnd.class, this);
}
else {
nar.memory.event.off(Events.FrameEnd.class, this);
}
}
@Override public void event(Class event, Object... arguments) {
update();
}
@Override
protected void paintComponent(Graphics g) {
if (buffer!=null) {
g.drawImage(buffer, 0, 0, null);
}
}
public void update() {
int w = getWidth();
int h = getHeight();
if ((buffer == null) || (buffer.getWidth()!=w) || (buffer.getHeight()!=h)) {
buffer = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
}
Graphics2D g = (Graphics2D)buffer.getGraphics();
g.setPaint(Color.BLACK);
g.fillRect(0, 0, w, h);
float minPriority = 0.02f;
float asize = (w + h)/2;
float esize = 0.05f * asize;
float minEsize = (int)(0.01f * asize);
int border = (int)esize/2;
int dw = w - border*2;
int dh = h - border*2;
float conceptOpacity = 0.65f;
float statementOpacity = 0.9f;
for (final Concept c : nar.memory) {
float priority = c.getPriority();
if (priority < minPriority)
continue;
if (c.beliefs.size() > 0) {
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int maxY = Integer.MIN_VALUE;
//Color cc = Video.getColor(c.term.toString(), 0.5f, 0.6f);
for (Task ts : c.beliefs) {
Sentence s = ts.sentence;
if (s.truth!=null) {
float freq = s.truth.getFrequency();
float conf = s.truth.getConfidence();
int x = (int)(freq * dw);
int y = dh - (int)(conf * dh);
int px = (int)Math.max(minEsize, (int)(c.getPriority() * esize));
int py = px;
//Color color = new Color(Video.(cc, statementOpacity * c.getPriority());
//g.setPaint(color);
int ix = x-px/2;
int iy = y-py/2;
int jx = x+px/2;
int jy = y+py/2;
g.fillOval(border+ix, border+iy, px, py);
if (ix < minX) minX = ix;
if (iy < minY) minY = iy;
if (jx > maxX) maxX = jx;
if (jy > maxY) maxY = jy;
}
}
int padding = 4;
int cw = padding * 2 + maxX-minX;
int ch = padding * 2 + maxY-minY;
float areafactor = Math.max(1f, asize/(cw + ch));
//Color occ = Video.getColor(cc, conceptOpacity * c.getPriority()/areafactor);
//g.setPaint(occ);
g.fillOval(border+minX-padding, border+minY-padding, cw, ch);
}
}
if (!needsPaint) {
needsPaint = true;
SwingUtilities.invokeLater(paintLater);
}
}
final Runnable paintLater = new Runnable() {
@Override public void run() {
repaint();
needsPaint = false;
}
};
}