# aardio 范例: 画曲线

```aardio
import win.ui;
/*DSG{{*/
var winform = win.form(text="画曲线";right=746;bottom=469)
winform.add(
edit={cls="edit";left=102;top=322;right=703;bottom=352;edge=1;multiline=1;z=2};
plusCanvas={cls="plus";left=32;top=25;right=703;bottom=302;align="right";bgcolor=0xFFFFFF;border={color=0xFF808080;width=1};db=1;dl=1;dr=1;dt=1;iconStyle={font=LOGFONT()};iconText="0";textPadding={top=10;right=100};valign="top";z=1};
static={cls="static";text="增长率：";left=32;top=365;right=94;bottom=385;align="right";transparent=1;z=5};
static2={cls="static";text="拐点：";left=32;top=400;right=94;bottom=420;align="right";transparent=1;z=6};
trackbarGrowth={cls="plus";left=102;top=367;right=703;bottom=382;bgcolor=0xFFD9AB23;border={radius=-1};color=0x005CFF;db=1;dr=1;foreRight=15;forecolor=0xFF1C77FF;paddingBottom=5;paddingTop=5;z=3};
trackbarMidpoint={cls="plus";left=102;top=407;right=703;bottom=422;bgcolor=0xFFD9AB23;border={radius=-1};color=0x005CFF;db=1;dr=1;foreRight=15;forecolor=0xFF1C77FF;paddingBottom=5;paddingTop=5;z=4}
)
/*}}*/

//更新绘图数据
winform.plusCanvas.updateCurve = function(calc,xMin,xMax,xStep,yMax){
	
		var width,height = owner.width,owner.height;
		if(!yMax) yMax = calc(xMax,yMax);
		
		var scaleX = width / (xMax - xMin);  
		var scaleY = height / yMax;
			
		var coordinates = [];
		for(x = xMin; xMax; xStep){ 
			
			//转换为 plus 控件内部坐标
			..table.push(
				coordinates,(x - xMin) * scaleX, 
				height - (calc(x,yMax) * scaleY) );
		}
		
		owner.coordinates = coordinates;
		
		owner.text = math.stringify( calc(xMax,yMax),2 );
		owner.iconText = math.stringify( calc(10168,yMax),2 );
}

//绘图事件
winform.plusCanvas.onDrawContent = function(graphics, rc, txtColor, rcContent, foreColor, font){
	var coordinates = owner.coordinates;
	if(!#coordinates) return; 
		
	var pen = gdip.pen(0xFFFF0000, 2);  
	
	/*
	注意 coordinates 至少包含 3 个坐标点才能画出曲线，如果仅 2 个坐标点只能画出直线
	
	coordinates 支持两种格式的数组
	- [x1,y1,x2,y2,...] // 也就是数值数组，每两个数值表示一个坐标点
	- [{float x;float y},{float x;float y},...] //也就是 POINTF 结构体数组
	*/
	graphics.drawCurve(pen, coordinates);
	pen.delete();
}

//滑块变动时重新计算曲线坐标
var onPosChanged = function(pos, triggeredByUser){

	var growthRate = winform.trackbarGrowth.progressPos / 100000.0;
	var midpoint = winform.trackbarMidpoint.progressPos / 100.0 * 121759;
		
	winform.plusCanvas.updateCurve(
		lambda (xValue,yMax) yMax / (1 + math.exp(-growthRate * (xValue - midpoint))),
		1/*xMin*/,100000/*xMax*/,1000/*xStep*/,25000
	);

	winform.plusCanvas.redrawTransparent();
	
	winform.edit.text = `增长率: ` + string.format('%.5f', growthRate) 
				+ ' 拐点: ' + math.round(midpoint);
}

// 初始化新增的滑块
winform.trackbarGrowth.setTrackbarRange(1, 100);
winform.trackbarGrowth.progressPos = 10; // 默认值
winform.trackbarGrowth.onPosChanged = onPosChanged; // 联动更新

winform.trackbarMidpoint.setTrackbarRange(1, 100);
winform.trackbarMidpoint.progressPos = 30; // 默认值
winform.trackbarMidpoint.onPosChanged = onPosChanged; // 联动更新

//控件大小改变时重新计算坐标
winform.plusCanvas.adjust = function(){
	onPosChanged();
}

winform.show();
win.loopMessage();
```