当您想绘制一架 2-D 飞机上的点时,必须找出每个点的 X 坐标和 Y 坐标。绘图的奇妙之处在于能够将某一个给定数据值从一个范围按比例缩放到另一个范围中,也就是说,如果给定一组值,如 {10,20,30},那么您应该能够确定 2-D 飞机上具体哪些点(X 坐标和 Y 坐标)表示的是 10、20 和 30 这些数据值。
绘制总是在按照某一个限定缩放比例进行的。换句话说,在同一限定区域内,可以绘制任意数量的点。因为该区域是固定的,所以您总是可以找到 X 坐标轴的跨度(长度)和 Y 坐标轴的跨度(高度)。X 坐标轴和 Y 坐标轴的跨度只是等式的一部分。另一部分是找出数据值的范围,并根据每个数据值在新范围内的等效值来计算这些值的坐标。
计算 X 坐标和 Y 坐标
X 坐标:X 坐标是某一个点距离原点的水平距离。计算元素的数量,然后将 X 坐标轴的跨度分成 n 个区段,其中,n 是给定集合中的元素的数量,通过这种方式,可以计算某一集合中的所有点的横向坐标。用这种分割方法可以获得每个区段的长度。集合中的第一个点位于等于区段长度的第一段距离内。后续的每个点则位于区段长度加上原点到前一个点的距离的那一段距离内。
例如,给出一个集合 {10,20,30,40},您立刻就可以知道要绘制 4 个点,因为集合中包含 4 个元素。所以,应该将 X 坐标轴的跨度分成 4 个相等的区段,每个区段的长度 = 跨度/4。因此,如果 X 坐标轴的跨度是 800,那么区段的长度将是 800/4,即 200。第一个元素(10)的 X 坐标将是 200,第二个元素(20)的 X 坐标将是 400,依此类推。 清单 2. 计算 X 坐标
private int[] getXCoordinates(ArrayList seriesData){
int xSpan = (int)GraFixConstants.xSpan;
int longestSeries = Utilities.getLongestSeries(seriesData);
int numSegments =
((double[])seriesData.get(longestSeries)).length;
int sectionWidth =
(int)xSpan / numSegments; //want to divide span of xAxis
int xPositions[] =
new int[numSegments]; // will contain X-coordinate of all dots.
for(int i=0; i<numSegments; i++){
xPositions[i]=
(i+1)*sectionWidth;//dots spaced at distance of sectionWidth
}
return xPositions;
}
Y 坐标:Y 坐标是某一个点距离原点的纵向距离。计算 Y 坐标要将某一个值按比例从一个范围缩放到另一个范围。例如,给出相同的集合 {10,20,30,40},您可以看出,数据的范围是 0 到 40,新的范围就是 Y 坐标轴的跨度(高度)。假设 Y 坐标轴的高度为 400,那么第一个元素(10)的高度将是100,第二个元素的高度将是 200,依此类推。
public class MainGraFixView extends ViewPart{
public void createPartControl(Composite parent) {
//create or get data in an arraylist
ArrayList seriesData = dataGenerator();
//instantiate a plotter, and provide data to it.
DirectedGraphXYPlotter dgXYGraph = new DirectedGraphXYPlotter(parent);
dgXYGraph.setData(seriesData);
dgXYGraph.plot(); //ask it to plot
}
public void setFocus() {
}
}
//This is a sample, you will need to add actual Node(s) to this NodeList.
NodeList nodes = new NodeList(); //create a list of nodes.
//This is a sample, you will need to add actual Edge(s) to this EdgeList.
EdgeList edges = new EdgeList(); //create a list of edges.
DirectedGraph graph = new DirectedGraph();
graph.nodes = nodes;
graph.edges = edges;
new BreakCycles().visit(graph);//ask BreakCycles to visit the graph.
//now our "graph" is ready to be used.
现在,已经知道 DirectedGraph 包含许多 Node,其中,每个 Node 都可能包含一些数据,并且还存储了这些数据的 X 坐标和 Y 坐标,以及一个 Edges 的列表,每个 Edge 都知道在自己的两端分别有一个 Node,您可以通过以下技术,使用这些信息来绘图,其中涉及两个部分:
private void populateNodesAndEdges(){
_seriesScaledValues = new ArrayList(getScaledValues(_seriesData));
_nodeLists = new ArrayList();
_edgeLists = new ArrayList();
for(int i=0; i<_numSeries; i++){
_nodeLists.add(new NodeList());// one NodeList per series.
_edgeLists.add(new EdgeList());// one EdgeList per series.
}
//populate all NodeLists with the Nodes.
for(int i=0; i<_numSeries; i++){//for each series
double data[] = (double[])_seriesData.get(i);//get the series
int xCoOrds[] = getXCoordinates(_seriesData);
int yCoOrds[] = getYCoordinates(i, data);
//each NodeList has as many Nodes as points in a series
for(int j=0; j<data.length; j++){
Double doubleValue = new Double(data[j]);
Node node = new Node(doubleValue);
node.x = xCoOrds[j];
node.y = yCoOrds[j];
((NodeList)_nodeLists.get(i)).add(node);
}
}
//populate all EdgeLists with the Edges.
for(int i=0; i<_numSeries; i++){
NodeList nodes = (NodeList)_nodeLists.get(i);
for(int j=0; j<nodes.size()-1; j++){
Node leftNode = nodes.getNode(j);
Node rightNode = nodes.getNode(j+1);
Edge edge = new Edge(leftNode,rightNode);
edge.start = new Point(leftNode.x, leftNode.y);
edge.end = new Point(rightNode.x, rightNode.y);
((EdgeList)_edgeLists.get(i)).add(edge);
}
}
int breakpoint = 0;
}
private void drawDotsAndConnections(IFigure contents, DirectedGraph graph){
for (int i = 0; i < graph.nodes.size(); i++) {
Node node = graph.nodes.getNode(i);
drawNode(contents, node);
}
for (int i = 0; i < graph.edges.size(); i++) {
Edge edge = graph.edges.getEdge(i);
drawEdge(contents, edge);
}
}
private void drawNode(IFigure contents, Node node){
Dot dotFigure = new Dot();
node.data = dotFigure;
int xPos = node.x;
int yPos = node.y;
contents.add(dotFigure);
contents.setConstraint(dotFigure, new Rectangle(xPos,yPos,-1,-1));
}
private void drawEdge(IFigure contents, Edge edge){
PolylineConnection wireFigure = new PolylineConnection();
//edge.source is the Node to the left of this edge
EllipseAnchor sourceAnchor = new EllipseAnchor((Dot)edge.source.data);
//edge.target is the Node to the right of this edge
EllipseAnchor targetAnchor = new EllipseAnchor((Dot)edge.target.data);
wireFigure.setSourceAnchor(sourceAnchor);
wireFigure.setTargetAnchor(targetAnchor);
contents.add(wireFigure);
}