-1

我有使用 cairo 库绘制 png 并调用以下函数的遗留代码。我无法理解以下代码。我知道这是一个奇怪的问题,需要一些代码并提出问题。但如果有人提供,那就太好了。

#define IMAGE_SIZE_W 1024
#define IMAGE_SIZE_H 768

#define GRAPH_MARGIN_L 48
#define GRAPH_MARGIN_R 21
#define GRAPH_MARGIN_B 27
#define GRAPH_MARGIN_T 22

#define GRAPH_SIZE_W (IMAGE_SIZE_W-(GRAPH_MARGIN_L+GRAPH_MARGIN_R))
#define GRAPH_SIZE_H (IMAGE_SIZE_H-(GRAPH_MARGIN_B+GRAPH_MARGIN_T))
#define SCALE_TO_CANVAS(v,low,high,fws,margin,a,b) (((a+b*((v-low)/(high-low)))*fws)+margin)

#define SCALE_TO_CANVAS_Y(v,low,high) SCALE_TO_CANVAS(v,low,high,GRAPH_SIZE_H,GRAPH_MARGIN_T,1,-1)
#define SCALE_TO_CANVAS_X(v,low,high) SCALE_TO_CANVAS(v,low,high,GRAPH_SIZE_W,GRAPH_MARGIN_L,0,1)

void line_to_point(cairo_t *cr,float x, float y){
   cairo_line_to(cr,x,y);
}
void move_to_point(cairo_t *cr,float x, float y){
   cairo_move_to(cr,x,y);
}

我们有 x 和 y 中的数据并绘制 x 和 y。调用者函数是 /* x 和 y 行的计数器编号

for(i = 0; i< counter; i++)
{
 move_to_point(cr,SCALE_TO_CANVAS_X(xvals[i-1],lowX,highX),SCALE_TO_CANVAS_Y(yvals[i-1],lowY,highY));
line_to_point(cr,SCALE_TO_CANVAS_X(x,lowX,highX),SCALE_TO_CANVAS_Y(y,lowY,highY));
}

比在它调用 write_png 之后,这是一种直接的函数。

如果你看,SCALE_TO_CANVAS 做了很多我无法弄清楚的计算。cairo_line_to x 和 y 已修改值并绘制它。

4

1 回答 1

0

我没有仔细看,但我猜您的 x 数据介于 lowX 和 highX 之间,而您的 y 数据介于 lowY 和 highY 之间。该数据经过缩放,使其适合图像表面(这意味着在 0x0 和 1024x768 之间)。

此外,这似乎在所有方面都增加了一个边距(L/R/B/T 表示左、右、下、上)。

如果您想解释所使用的数学而不仅仅是其含义,请问。

编辑:

好的,我们有描述图表中点的数据。我们输入数据的左上角在位置(lowX,lowY),右下角在(highX,highY)。

我们正在绘制的区域的大小为 1024x768。因此,我们希望缩放输入数据以使其适合该空间。为了让事情变得更复杂一些,我们希望在图表周围保留一个空白边距。这需要左侧的 GRAPH_MARGIN_L 像素,顶部的 GRAPH_MARGIN_T 像素等。

因此绘图区域的左上角位于 (GRAPH_MARGIN_L, GRAPH_MARGIN_T),右下角位于 (1024-GRAPH_MARGIN_R, 768-GRAPH_MARGIN_B)。所以我们正在寻找一个将 (lowX, lowY) 映射到 (GRAPH_MARGIN_L, GRAPH_MARGIN_T) 和 (highX, highY) 到 (1024-GRAPH_MARGIN_R, 768-GRAPH_MARGIN_B) 的公式。

下面,我们只看点的两个坐标之一,例如 x 坐标。对于点 x,我们首先计算一个百分比来描述它沿轴的距离。0% 应该表示“在顶部/左端”,100% 是“在底部/右端”。可用空间从 lowX 开始到 highX,因此有 highX-lowX 可能的值。因此,x-lowX(因此“top/left”实际上为零)落在这个范围内,而 (x-lowX)*100/(highX-lowX) 是我们正在寻找的百分比。

这个百分比现在应该映射到目标区域。首先,我们将它乘以目标空间的宽度(除以 100,这样百分比就消失了),这样我们就有了一个跨越可能范围的值。然后我们必须添加可能的最低值,而不是从零开始并上升到可能的宽度(即高-低),我们有一个介于低和高之间的值。

总之,公式变为 minimumTargetX+(x-lowX)/(highX-lowX)*widthOfTheTargetArea,或根据您的定义:GRAPH_MARGIN_L+(x-lowX)/(highX-lowX)*GRAPH_SIZE_W。

GRAPH_TO_CANVAS 中使用的附加变量 a 和 b 用于“交换方向”。似乎不是在左上角有 (0, 0) 而正坐标在右/下,而是在左下角有 (0, 0) 而正坐标在右/最佳。为了解决这个问题,将上面计算的百分比乘以 -1 并将 1 添加到坐标中,以使映射真正将点映射到应有的点。这些是 GRAPH_TO_CANVAS 宏的最后两个参数。

我希望这可以帮助您理解宏。

于 2013-12-01T10:11:55.907 回答