[英]How to change point size or shape in FastScatterPlot (JFreeChart)?
我有大量的2D坐標集合(即,很容易以100k至200k x,y對的順序),我希望將其可視化為散點圖。 對於打算用於的應用程序,有很多要點是有道理的,出於各種原因,我無法/不會減少數量。 為了用Java繪制,我使用JFreeChart。 我玩過ChartFactory.createScatterPlot()
和50k隨機生成的點,盡管這給設置外觀(點大小/顏色/形狀)提供了最大的靈活性,但顯示許多點的速度很慢。 這意味着,它需要花費一些時間才能顯示,並且縮放也延遲/不平滑。 但是,一旦實際上只有幾個點可見(即深度放大),可視化就會很好地響應。
相反, FastScatterPlot()
可以輕松繪制500k隨機生成的2D點,但是外觀並不是很好,因為到目前為止我只能設置顏色(使用例如setPaint(Color.BLUE)
),但是不能設置形狀或尺寸。 大小特別成問題,因為各個點的確很小。
如何在FastScatterPlot
更改點的大小或形狀?
與此相關的是,是否有一種方法可以使ChartFactory.createScatterPlot()
返回的圖表更具響應性?
我的數據是固定的,並且渲染原則上不必在運行時期間發生更改,因此,如果存在斷開任何偵聽器的方法或此類方法以提高性能,這也是一種選擇。
提前致謝。
為了提高速度,您可以嘗試render()
方法的源注釋中建議的替代FastScatterPlot
計算。 個人資料進行比較。 對於大小,可以使用相同的方法更改渲染的大小。 以下將使每個點的大小增加三倍。
g2.fillRect(transX, transY, 2, 2);
多虧了rashgod的提示,我決定以以下方式簡單地擴展FastScatterPlot
。 現在,您可以在ExtendedFastScatterPlot
的構造函數中指定顏色,大小和形狀,它對於50萬個點非常有效。 與對所有點使用fillRect()
相比,對一半的點使用fillOval()
似乎會減慢速度,但這並不是真正的問題,只要圖解總體上可以接受即可。 與XYPlot
相比,它現在響應XYPlot
。 付出一點努力,物超所值!
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.geom.Rectangle2D;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CrosshairState;
import org.jfree.chart.plot.FastScatterPlot;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.ui.RectangleEdge;
public class ExtendedFastScatterPlot extends FastScatterPlot {
/**
*
*/
private static final long serialVersionUID = 1L;
int[] sizes;
Paint[] colors;
int[] shapes;
public ExtendedFastScatterPlot(float[][] data, NumberAxis domainAxis, NumberAxis rangeAxis, int[] sizes, Paint[] colors, int[] shapes) {
super(data,domainAxis,rangeAxis);
this.sizes = sizes;
this.colors = colors;
this.shapes = shapes;
}
@Override
public void render(Graphics2D g2, Rectangle2D dataArea, PlotRenderingInfo info, CrosshairState crosshairState) {
//g2.setPaint(Color.BLUE);
if (this.getData() != null) {
for (int i = 0; i < this.getData()[0].length; i++) {
float x = this.getData()[0][i];
float y = this.getData()[1][i];
int size = this.sizes[i];
int transX = (int) this.getDomainAxis().valueToJava2D(x, dataArea, RectangleEdge.BOTTOM);
int transY = (int) this.getRangeAxis().valueToJava2D(y, dataArea, RectangleEdge.LEFT);
g2.setPaint(this.colors[i]);
if( 1 == this.shapes[i])
{
g2.fillRect(transX, transY, size, size);
}
else
{
g2.fillOval(transX, transY, size, size);
}
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.