首页 > 代码库 > [从头学数学] 第172节 直线与方程

[从头学数学] 第172节 直线与方程

剧情提要:
[机器小伟]在[project师阿伟]的陪同下进入了结丹初期的修炼。
这次要修炼的目标是[直线与方程]。



正剧開始:

星历2016年04月11日 09:30:00, 银河系厄尔斯星球中华帝国江南行省。


[project师阿伟]正在和[机器小伟]一起研究[直线与方程]。

技术分享


開始今天的修炼之前,小伟先整理了一下这件法器:

<span style="font-size:18px;">	if (1) {
		var r = 20;
		config.setSector(1,1,1,1);
		config.graphPaper2D(0, 0, r);
		config.axis2D(0, 0, 180);
		
		var transform = new Transform();
		
		var a = 4, b = 3, h = 2;
		var edges = 4;
		var array = shape.trapezoid(0, 0, 0, a, b, Math.PI/3);
		var scale = 2.5*r;
		
		array = transform.flipX(array);
		shape.angleDraw(transform.translate(array, -200/scale, 0), 'cyan', scale);
		shape.areaDraw(array, 'red', scale);
	
	}</span>



技术分享

看来用得上它的地方非常多。小伟非常惬意。


技术分享


技术分享

技术分享

技术分享


<span style="font-size:18px;">def slopeCalc(x1, y1, x2, y2):    
    if (x1 == x2):
        print('k = Inf');
    else:
        print('k = {0}'.format((y2-y1)/(x2-x1)));</span>

技术分享

>>> 
[3, 2] 与 [-4, 1] 两点的斜率是 0.14285714285714285;
[-4, 1] 与 [0, -1] 两点的斜率是 -0.5;
[0, -1] 与 [3, 2] 两点的斜率是 1.0;


<span style="font-size:18px;">def slopeCalc(x1, y1, x2, y2):    
    if (x1 == x2):
        return float('inf');
    else:
        return (y2-y1)/(x2-x1);

def tmp():
    triangle = [[3, 2],[-4, 1], [0, -1]];
    size = len(triangle);
    for i in range(size):
        x1 = triangle[i%3][0];
        y1 = triangle[i%3][1];
        x2 = triangle[(i+1)%3][0];
        y2 = triangle[(i+1)%3][1];

        print('[{0}, {1}] 与 [{2}, {3}] 两点的斜率是 {4};'              .format(x1, y1, x2, y2, slopeCalc(x1,y1,x2,y2)));
    
</span>

技术分享

<span style="font-size:18px;">	if (1) {
		var r = 20;
		config.setSector(1,1,1,1);
		config.graphPaper2D(0, 0, r);
		config.axis2D(0, 0, 180);
		
		var transform = new Transform();
		
		var a = 4, b = 3, h = 2;
		var edges = 4;
		var array = [[3,2],[-4,1],[0,-1]];
		var scale = 2.5*r;
		
		shape.areaDraw(transform.translate(array, 0, -150/scale), 'red', scale);
		shape.angleDraw([].concat(array), 'orange', scale);
		
	
	}</span>


技术分享

技术分享

<span style="font-size:18px;">	if (1) {  
        var r = 20;        
        config.setSector(1,1,1,1);          
        config.graphPaper2D(0, 0, r);        
        config.axis2D(0, 0,180, 1.5);          
            
        //坐标轴设定    
        var scaleX = 2*r, scaleY = 2*r;      
        var spaceX = 2, spaceY = 2;       
        var xS = -10, xE = 10;      
        var yS = -10, yE = 10;      
        config.axisSpacing(xS, xE, spaceX, scaleX, 'X');        
        config.axisSpacing(yS, yE, spaceY, scaleY, 'Y');        
                
        var transform = new Transform();        
        //存放函数图像上的点    
        var a = [], b = [], c = [], d = [];      
              
        //须要显示的函数说明    
        var f1 = 'y=x', f2 = 'y=-x', f3 = 'y=2x', f4 = 'y=-3x';    
        //函数描点    
        for (var x = xS; x <= xE; x+=1) {      
            if (x != 0) {    
                a.push([x, x]);      
                b.push([x, -x]);  
                c.push([x, 2*x]);  
                d.push([x, -3*x]);  
  
            }    
        }      
              
        //存放暂时数组    
        var tmp = [];    
              
        //显示变换    
        if (a.length > 0) {    
            a = transform.scale(transform.translate(a, 0, 0), scaleX/spaceX, scaleY/spaceY);     
            //函数1    
            tmp = [].concat(a);        
            shape.pointDraw(tmp, 'red');        
            tmp = [].concat(a);        
            shape.multiLineDraw(tmp, 'pink');      
                  
            plot.setFillStyle('red');    
            plot.fillText(f1, 100, -90, 200);      
        }    
            
        if (b.length > 0) {    
            b = transform.scale(transform.translate(b, 0, 0), scaleX/spaceX, scaleY/spaceY);                
            //函数2    
            tmp = [].concat(b);        
            shape.pointDraw(tmp, 'blue');        
            tmp = [].concat(b);        
            shape.multiLineDraw(tmp, '#22CCFF');     
                
            plot.setFillStyle('blue');    
            plot.fillText(f2, 100, -120, 200);     
    
        }    
               
        if (c.length > 0) {    
            c = transform.scale(transform.translate(c, 0, 0), scaleX/spaceX, scaleY/spaceY);      
            tmp = [].concat(c);        
            shape.pointDraw(tmp, 'green');        
            tmp = [].concat(c);        
            shape.multiLineDraw(tmp, '#CCFF22');      
            plot.setFillStyle('green');      
            plot.fillText(f3, 100, -150, 200);     
        }    
            
        if (d.length > 0) {    
            d = transform.scale(transform.translate(d, 0, 0), scaleX/spaceX, scaleY/spaceY);      
            tmp = [].concat(d);        
            shape.pointDraw(tmp, 'orange');        
            tmp = [].concat(d);        
            shape.multiLineDraw(tmp, '#CC8800');      
            plot.setFillStyle('orange');      
            plot.fillText(f4, 100, -180, 200);     
        }    
    
             
    
    }</span>

技术分享

技术分享

技术分享


>>> 
[2, 3] 与 [-4, 0] 两点的斜率是 0.5;
[-4, 0] 与 [-3, 1] 两点的斜率是 1.0;
[-3, 1] 与 [2, 3] 两点的斜率是 0.4;
[2, 3] 与 [-4, 0] 两点的斜率是 0.5;


<span style="font-size:18px;">def slopeCalc(x1, y1, x2, y2):    
    if (x1 == x2):
        return float('inf');
    else:
        return (y2-y1)/(x2-x1);

def tmp():
    points = [[2,3],[-4,0],[-3,1],[-1,2]];
    size = len(points);
    for i in range(size):
        x1 = points[i%3][0];
        y1 = points[i%3][1];
        x2 = points[(i+1)%3][0];
        y2 = points[(i+1)%3][1];

        print('[{0}, {1}] 与 [{2}, {3}] 两点的斜率是 {4};'              .format(x1, y1, x2, y2, slopeCalc(x1,y1,x2,y2)));</span>


技术分享

<span style="font-size:18px;">	if (1) {
		var r = 20;
		config.setSector(1,1,1,1);
		config.graphPaper2D(0, 0, r);
		config.axis2D(0, 0, 180);
		
		var transform = new Transform();
		
		var a = 4, b = 3, h = 2;
		var edges = 4;
		var array = [[2,3],[-4,0],[-3,1],[-1,2]];
		var scale = 3*r;
		
		shape.areaDraw(transform.translate(array, 0, -150/scale), 'red', scale);
		shape.angleDraw([].concat(array), 'orange', scale, 'AQPB');
		
	
	}</span>


技术分享

技术分享

<span style="font-size:18px;">	if (1) {
		var r = 20;
		config.setSector(1,1,1,1);
		config.graphPaper2D(0, 0, r);
		config.axis2D(0, 0, 180);
		
		var transform = new Transform();
		
		var a = 4, b = 3, h = 2;
		var edges = 4;
		var array = [[0,0],[2,-1],[4,2],[2,3]];
		var scale = 3*r;
		
		shape.areaDraw(transform.translate(array, 0, -150/scale), 'red', scale);
		shape.angleDraw([].concat(array), 'orange', scale, 'CDAB');
		
	
	}</span>


>>> 
[0, 0] 与 [2, -1] 两点的斜率是 -0.5;
[2, -1] 与 [4, 2] 两点的斜率是 1.5;
[4, 2] 与 [0, 0] 两点的斜率是 0.5;
[0, 0] 与 [2, -1] 两点的斜率是 -0.5;


技术分享

技术分享

技术分享


>>> 
[-6, 0] 与 [3, 6] 两点的斜率是 0.6666666666666666;
[3, 6] 与 [0, 3] 两点的斜率是 1.0;
[0, 3] 与 [6, -6] 两点的斜率是 -1.5;
[6, -6] 与 [-6, 0] 两点的斜率是 -0.5;


<span style="font-size:18px;">def slopeCalc(x1, y1, x2, y2):    
    if (x1 == x2):
        return float('inf');
    else:
        return (y2-y1)/(x2-x1);

def tmp():
    points = [[-6,0],[3,6],[0,3],[6,-6]];
    size = len(points);
    for i in range(size):
        x1 = points[i%size][0];
        y1 = points[i%size][1];
        x2 = points[(i+1)%size][0];
        y2 = points[(i+1)%size][1];

        print('[{0}, {1}] 与 [{2}, {3}] 两点的斜率是 {4};'              .format(x1, y1, x2, y2, slopeCalc(x1,y1,x2,y2)));
    
</span>

技术分享

技术分享

<span style="font-size:18px;">	if (1) {
		var r = 20;
		config.setSector(1,1,1,1);
		config.graphPaper2D(0, 0, r);
		config.axis2D(0, 0, 180);
		
		var transform = new Transform();
		
		var a = 4, b = 3, h = 2;
		var edges = 4;
		var array = [[5,-1],[1,1],[2,3]];
		var scale = 2*r;
		
		shape.areaDraw(transform.translate(array, 0, -50/r), 'red', scale);
		shape.angleDraw([].concat(array), 'orange', scale, 'BPAQ');
		
	
	}
	</span>

技术分享


这个问题的答案是这种:魔术师撒谎了。

魔术师改进后的地毯不是矩形的。


技术分享

<span style="font-size:18px;">	if (1) {
		var r = 20;
		config.setSector(1,1,1,1);
		config.graphPaper2D(0, 0, r);
		config.axis2D(0, 0, 180);
		
		var transform = new Transform();
		
		
		var a = 4, b = 3, h = 2;
		var edges = 4;
		var array = [[0,0],[0,-8],[8,0],[5,-8]];
		var scale = r;
		array = shape.angularSort(array);
		
		array = transform.translate(array, 0, 8);
		shape.areaDraw(transform.translate(array, 0, -200/scale), 'red', scale);
		shape.angleDraw([].concat(array), 'orange', scale);
		
	
		var triangle = new Triangle();
		var array2 = triangle.know2edges([5, 13], 90);
		
		array2 = transform.translate(array2, -10, 5);
		
		shape.angleDraw([].concat(array2), 'purple', scale);
	}</span>

多出来0.5个角度。

总面积:

>>> 52*2+65
169


技术分享

技术分享

技术分享

技术分享

技术分享

技术分享

技术分享


>>> 
[-5, 0] 与 [3, -3] 两点的斜率是 -0.375;
[-5, 0] 与 [0, 2] 两点的斜率是 0.4;
[-5, 0] 与 [1.5, -0.5] 两点的斜率是 -0.07692307692307693;
[3, -3] 与 [0, 2] 两点的斜率是 -1.6666666666666667;
[3, -3] 与 [1.5, -0.5] 两点的斜率是 -1.6666666666666667;
[0, 2] 与 [1.5, -0.5] 两点的斜率是 -1.6666666666666667;


<span style="font-size:18px;">def tmp():
    points = [[-5,0],[3,-3],[0,2],[1.5,-0.5]];
    size = len(points);
    for i in range(size):
        for j in range(i+1, size):
            x1 = points[i%size][0];
            y1 = points[i%size][1];
            x2 = points[j%size][0];
            y2 = points[j%size][1];

            print('[{0}, {1}] 与 [{2}, {3}] 两点的斜率是 {4};'                  .format(x1, y1, x2, y2, slopeCalc(x1,y1,x2,y2)));</span>


技术分享


技术分享

技术分享

技术分享

技术分享

技术分享


技术分享

<span style="font-size:18px;">	if (1) {
		//运用行列式解线性方程组
		var matrix = new Matrix();  
		var matrixArray = new Array();  
		var rowArray = new Array();  
		var ma, mb; 
		
		//二元一次方程组[[A1,B1,C1], [A2,B2,C2]]
		//Ax+By+C=0
		var a = [[3, 4, -2], [2,1,2]];
		  
		//二阶
		var rank = 2;
		for (var i = 0; i < rank; i++) {  
			matrixArray.push([a[i][0], a[i][1]]);  
		}  		
		
		ma = matrix.deepCopy(matrixArray); 		
		for (var i = 0; i < rank; i++) {  
			ma[i][0] = -a[i][2];  
		}  
		
		
		mb = matrix.deepCopy(matrixArray);  
		for (var i = 0; i < rank; i++) {  
			mb[i][1] = -a[i][2];  
		}  
		  
		  
		var d, da, db;
		d = matrix.delta(matrixArray);  
		da = matrix.delta(ma);  
		db = matrix.delta(mb);  
		  
		  
		matrix.print(matrixArray);  
		  
		document.write('d = ' + d+'<br/>');  
			matrix.print(ma);  
		document.write('da = ' + da+'<br/>');  
			matrix.print(mb);  
		document.write('db = '+db+'<br/>');  
		  
		var s = 'x = da/d = '+ (da/d).toFixed(2)+', y = db/d = '+(db/d).toFixed(2);  
		document.write(s+'<br/>');  
      
	
	
	}</span>


3.00 , 4.00 , 
2.00 , 1.00 , 
d = -5
2.00 , 4.00 , 
-2.00 , 1.00 , 
da = 10
3.00 , 2.00 , 
2.00 , -2.00 , 
db = -10
x = da/d = -2.00, y = db/d = 2.00


技术分享


1.00 , -1.00 , 
3.00 , 3.00 , 
d = 6
0.00 , -1.00 , 
10.00 , 3.00 , 
da = 10
1.00 , 0.00 , 
3.00 , 10.00 , 
db = 10
x = da/d = 1.67, y = db/d = 1.67


//二元一次方程组[[A1,B1,C1], [A2,B2,C2]]
		//Ax+By+C=0
		var a = [[1,-1,0], [3,3,-10]];


3.00 , -1.00 , 
6.00 , -2.00 , 
d = 0
-4.00 , -1.00 , 
1.00 , -2.00 , 
da = 9
3.00 , -4.00 , 
6.00 , 1.00 , 
db = 27
x = da/d = Infinity, y = db/d = Infinity


说明第(2)小题无交点

<span style="font-size:18px;">		//二元一次方程组[[A1,B1,C1], [A2,B2,C2]]
		//Ax+By+C=0
		var a = [[3,-1,4], [6,-2,-1]];</span>



3.00 , 4.00 , 
6.00 , 8.00 , 
d = 0
5.00 , 4.00 , 
10.00 , 8.00 , 
da = 0
3.00 , 5.00 , 
6.00 , 10.00 , 
db = 0
x = da/d = NaN, y = db/d = NaN


第(3)小题这是有无穷多组解的节奏。


		//二元一次方程组[[A1,B1,C1], [A2,B2,C2]]
		//Ax+By+C=0
		var a = [[3,4,-5], [6,8,-10]];


算得对不正确呢?

技术分享


既然[人叫板老师]也认为是这种答案,那就说明小伟的工具是可用的。


技术分享

技术分享

技术分享

技术分享

#点到直线的距离[x,y]-->ax+by+c=0
def disOfP2L(x, y, a, b, c):
    return abs(a*x+b*y+c)/(a*a+b*b)**0.5;

技术分享

>>> 
1.6666666666666667

print(disOfP2L(-1,2,3,0,-2));


技术分享
	if (1) {
		var r = 20;
		config.setSector(1,1,1,1);
		config.graphPaper2D(0, 0, r);
		config.axis2D(0, 0, 180);
		
		var transform = new Transform();
		
		
		var array = [[1,3],[3,1],[-1,0]];
		var scale = 2*r;
		array = shape.angularSort(array);

		shape.areaDraw(transform.translate(array, 0, -100/scale), 'red', scale);
		shape.angleDraw([].concat(array), 'orange', scale, 'ACB');
		
	}
	

技术分享


技术分享


>>> 23/159*53**0.5
1.053097656939949


2.00 , -7.00 , 
6.00 , -21.00 , 
d = 0
8.00 , -7.00 , 
1.00 , -21.00 , 
da = -161
2.00 , 8.00 , 
6.00 , 1.00 , 
db = -46
x = da/d = -Infinity, y = db/d = -Infinity
两条直线平行。 距离是:1.053


这两条直线还真是平行。


<span style="font-size:18px;">	if (1) {
		//运用行列式解线性方程组
		var matrix = new Matrix();  
		var matrixArray = new Array();  
		var rowArray = new Array();  
		var ma, mb; 
		
		//二元一次方程组[[A1,B1,C1], [A2,B2,C2]]
		//Ax+By+C=0
		var a = [[2,-7,-8], [6,-21,-1]];
		  
		//二阶
		var rank = 2;
		for (var i = 0; i < rank; i++) {  
			matrixArray.push([a[i][0], a[i][1]]);  
		}  		
		
		ma = matrix.deepCopy(matrixArray); 		
		for (var i = 0; i < rank; i++) {  
			ma[i][0] = -a[i][2];  
		}  
		
		
		mb = matrix.deepCopy(matrixArray);  
		for (var i = 0; i < rank; i++) {  
			mb[i][1] = -a[i][2];  
		}  
		  
		  
		var d, da, db;
		d = matrix.delta(matrixArray);  
		da = matrix.delta(ma);  
		db = matrix.delta(mb);  
		  
		  
		matrix.print(matrixArray);  
		  
		document.write('d = ' + d+'<br/>');  
			matrix.print(ma);  
		document.write('da = ' + da+'<br/>');  
			matrix.print(mb);  
		document.write('db = '+db+'<br/>');  
		  
		var s = 'x = da/d = '+ (da/d).toFixed(2)+', y = db/d = '+(db/d).toFixed(2);  
		document.write(s+'<br/>');  
		
		if (d == 0 && (da != db)) {
			var r = 0;
			if (a[0][0] != 0) {
				r = a[1][0]/a[0][0];
			}
			else {
				r = a[1][1]/a[0][1];
			}
			
			var distance = (a[1][2]/r-a[0][2])/Math.sqrt(a[0][0]*a[0][0] + a[0][1]*a[0][1]);
			document.write('两条直线平行, 距离是:'+ distance.toFixed(3)+'<br/>');  
		}
      
	
	
	}</span>


技术分享

技术分享


这里贴一下小伟用到的Shape类和Matrix类。以防遗漏。


/**
* @usage   经常使用形状类
* @author  mw
* @date    2015年11月29日  星期日  10:21:18 
* @param
* @return
*
*/

var shape = function Shape() {
	
	//以给定点为中点的矩形
	this.strokeRect = function(x, y, w, h) {
		w = Math.abs(w);
		h = Math.abs(h);
		return plot.strokeRect(x-w/2, y-h/2, w, h);
	}
	
	//以给定点为中点的矩形
	this.fillRect = function(x, y, w, h) {
		w = Math.abs(w);
		h = Math.abs(h);
		return plot.fillRect(x-w/2, y-h/2, w, h);
	}
	
/**
* @usage   绘制点阵列
* @author  mw
* @date    2016年02月21日  星期日  15:16:47 
* @param
* @return
*
*/
	this.pointDraw = function(array, style, scale, showLable, lable) {
		//已经考虑到y轴坐标的取反问题。仅仅需传入原始坐标数组就可以
		style = style ?

style : 'black'; scale = scale ? scale : 1; lable = lable ? lable : 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; lables = lable.length; showLable = showLable ?

showLable : 0; var x = y = index = 0; //点的大小 var pSize = 3; plot.save() .setFillStyle(style); var a = new Array(); a = array[0]; //y坐标取反是由于canvas中y坐标以向下为正。与笛卡尔坐标系相反 if (a.length != 2) { //坐标是流水模式。既x1, y1, x2, y2,... while (array.length > 0) { x = array.shift()*scale; y = -array.shift()*scale; shape.fillCircle(x, y, pSize); if (showLable) { plot.fillText(lable[index++%lables], x+5, y+10, 30); } } } else { //坐标是有序对模式,即[x1, y1], [x2, y2], ... while (array.length > 0) { a = array.shift(); x = a[0]*scale; y = -a[1]*scale; shape.fillCircle(x, y, pSize); if (showLable) { plot.fillText(lable[index++%lables], x+5, y+10, 30); } } } plot.restore(); } //连接成折线 this.multiLineDraw = function(array,style, scale) { //已经考虑到y轴坐标的取反问题。仅仅需传入原始坐标数组就可以 style = style ? style : 'black'; scale = scale ?

scale : 1; plot.save() .setStrokeStyle(style); var a = new Array(); var x = y = index = 0; a = array[0]; if (a.length < 2) { x = array.shift()*scale; y = -array.shift()*scale; if (array.length > 2 && array.length % 2 == 0) { plot.beginPath() .moveTo(x, y); while (array.length > 0) { x = array.shift()*scale; y = -array.shift()*scale; plot.lineTo(x, y); } plot.moveTo(x, y) .closePath() .stroke(); } } else if (a.length == 2) { if (array.length > 2) { a = array.shift(); x = a[0]*scale; y = -a[1]*scale; plot.beginPath() .moveTo(x, y); while (array.length > 0) { a = array.shift(); x = a[0]*scale; y = -a[1]*scale; plot.lineTo(x, y); } plot.moveTo(x, y) .closePath() .stroke(); } else { var a = array.shift(); var b = array.shift(); plot.beginPath() .moveTo(a[0]*scale, -a[1]*scale) .lineTo(b[0]*scale, -b[1]*scale) .closePath() .stroke(); } } plot.restore(); } this.fillDraw = function(array, style, scale) { //已经考虑到y轴坐标的取反问题。仅仅需传入原始坐标数组就可以 style = style ? style : 'black'; scale = scale ? scale : 1; plot.save() .setFillStyle(style); var a = array[0]; if (a.length != 2) { if (array.length > 2 && array.length % 2 == 0) { plot.beginPath() .moveTo(array.shift()*scale, -array.shift()*scale); while (array.length > 0) { plot.lineTo(array.shift()*scale, -array.shift()*scale); } plot.closePath() .fill(); } } else { if (array.length > 2) { a = array.shift(); plot.beginPath() .moveTo(a[0]*scale, -a[1]*scale); while (array.length > 0) { a = array.shift(); plot.lineTo(a[0]*scale, -a[1]*scale); } plot.closePath() .fill(); } } plot.restore(); } this.strokeDraw = function(array,style, scale) { //已经考虑到y轴坐标的取反问题,仅仅需传入原始坐标数组就可以 style = style ? style : 'black'; scale = scale ?

scale : 1; plot.save() .setStrokeStyle(style); var a = array[0]; if (a.length != 2) { if (array.length > 2 && array.length % 2 == 0) { plot.beginPath() .moveTo(array.shift()*scale, -array.shift()*scale); while (array.length > 0) { plot.lineTo(array.shift()*scale, -array.shift()*scale); } plot.closePath() .stroke(); } } else { if (array.length > 2) { a = array.shift(); plot.beginPath() .moveTo(a[0]*scale, -a[1]*scale); while (array.length > 0) { a = array.shift(); plot.lineTo(a[0]*scale, -a[1]*scale); } plot.closePath() .stroke(); } } plot.restore(); } this.angleDraw = function(array, style, scale, vertexLabel) { //vertexLabel是顶点编号顺序字符串 ABC,... style = style ? style : 'black'; //array是一个存放二维坐标点序列的数组 var a0 = new Array(); var len = array.length; var len_1 = array[0].length; for (var i = 0; i < len; i++) { a0.push(array[i]); } scale = scale ? scale : 1; len = a0.length; if (scale != 1 && scale > 0) { for (var i = 0; i < len; i++) { for (var j = 0; j < 2; j++) { a0[i][j]*=scale; } } } //进行环状排序,这样传入的array就能够随意顺序放置坐标点。 var a = this.angularSort(a0); //分两次绘点和连线 var tmp = [].concat(a); this.pointDraw(tmp, style); tmp = [].concat(a); this.strokeDraw(tmp, style); var d1, d2, d3, angle; var x1,y1, x2, y2, x3, y3; var s; //坐标点编号 var s0 = vertexLabel ?

vertexLabel : 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; //标记边的长度 var edgeLong = 0; var measure = 0; //为每一个点利用余弦定理求角 for (var i = 0; i < len; i++) { if (i == 0) { x1 = a[len-1][0]; y1 = a[len-1][1]; x3 = a[i+1][0]; y3 = a[i+1][1]; } else if (i == len-1) { x1 = a[i-1][0]; y1 = a[i-1][1]; x3 = a[0][0]; y3 = a[0][1]; } else { x1 = a[i-1][0]; y1 = a[i-1][1]; x3 = a[i+1][0]; y3 = a[i+1][1]; } x2 = a[i][0]; y2 = a[i][1]; d1 = (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2); d2 = (x2-x3)*(x2-x3)+(y2-y3)*(y2-y3); d3 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3); angle = Math.acos((d1+d2-d3)/(2*Math.sqrt(d1*d2)))/Math.PI*180; s = angle.toFixed(2)+'°'; //document.write(s+'<p>'); //标注角度和顶点编号 plot.setFillStyle('purple'); plot.fillText(s, x2, -y2-5, 100); plot.setFillStyle(style); plot.fillText(s0[i], x2, -y2+20, 20); edgeLong = (Math.sqrt(d1)/scale).toFixed(2); measure = plot.measureText(edgeLong); plot.setFillStyle('blue'); plot.fillText(edgeLong, (x1+x2-measure)/2, -(y1+y2)/2+20, measure); } } /** * @usage 计算并显示凸多边形的面积 * @author mw * @date 2016年04月11日 星期一 08:46:52 * @param * @return * */ //计算并显示凸多边形的面积 this.areaDraw = function(array, style, scale) { style = style ? style : 'black'; scale = scale ? scale : 1; var size = array.length; //document.write(areaCalc(array)); //由阵列切割出的三角形 var tri = []; var xCenter = yCenter = 0; var S = 0; var measure = 0; var sumS = 0; var text = ''; plot.save() .setFillStyle('#CC2288'); for (var i = 1; i < size-1; i++) { tri = []; tri.push(array[0]); tri.push(array[i]); tri.push(array[i+1]); xCenter = (tri[0][0]+tri[1][0]+tri[2][0])/3*scale; yCenter = -(tri[0][1]+tri[1][1]+tri[2][1])/3*scale; S = this.areaCalc(tri); if (S > 0) { shape.strokeDraw(tri, style, scale); text = 'S='+S.toFixed(2); measure = plot.measureText(text); plot.fillText(text, xCenter-measure/2, yCenter, measure); sumS += S; } } plot.fillText('总面积:'+sumS.toFixed(2), -270, -160, 200); //shape.angleDraw(array, 'blue', scale); plot.restore(); } //计算三角形的面积 this.areaCalc = function(array) { //array中包括组成三角形的三个点的坐标 array = shape.angularSort(array); var S = 0; if (array.length >=3) { var x1 = array[0][0], y1 = array[0][1], x2 = array[1][0], y2 = array[1][1], x3 = array[2][0], y3 = array[2][1]; S = 0.5*(x1*y2+x2*y3+x3*y1-x1*y3-x2*y1-x3*y2); } return S; } /** * @usage 以顶点递推方式绘制正多边形 #1 * @author mw * @date 2015年12月01日 星期二 09:42:33 * @param (x, y)图形中心坐标,r 外接圆半径 edge 边数 * @return * */ this.nEdge = function(x, y, r, edge, angle0) { edge = edge ? edge : 5; angle0 = angle0 ?

angle0 : 0; var retArray = new Array(); var perAngle = Math.PI * 2 / edge; var a = r * Math.sin(perAngle / 2); var angle = -angle0; var xOffset = r * Math.sin(perAngle / 2 - angle0); var yOffset = r * Math.cos(perAngle / 2 - angle0); var x1 = x-xOffset; var y1 = y+yOffset; for (var i=0; i < edge; i++) { retArray.push([x1, y1]); x1 = x1 + 2 * a * Math.cos(angle); y1 = y1 + 2 * a * Math.sin(angle); angle -= perAngle; } return retArray; } /** * @usage 空心星形 #2 #201 #202 * @author mw * @date 2015年12月01日 星期二 10:06:13 * @param * @return * */ this.nStar = function(x, y, r, edge, angle0, arg1, arg0) { edge = edge ?

edge : 5; angle0 = angle0 ? angle0 : Math.PI/2; var retArray=new Array(); var perAngle = Math.PI * 2 / edge; var r0 = arg0 ? arg0 * r : r / (2 * (1 + Math.cos(perAngle))); var scale = arg1 ? arg1 : 0.5; var angle = 0.5 * perAngle - angle0 * scale / 0.5; var xOffset = x; var yOffset = y; for (var i =0; i< edge; i++) { retArray.push([r0 * Math.cos(angle) + xOffset,r0 * Math.sin(angle) + yOffset] ); retArray.push([r * Math.cos(angle - scale * perAngle) + xOffset, r * Math.sin(angle - scale * perAngle) + yOffset]); angle -= perAngle; } return retArray; } /** * @usage 平行线, 平行四边形, 梯形 * @author mw * @date 2016年01月24日 星期日 11:14:43 * @param * @return * */ /* 平行线 Parallel lines 平行四边形 Parallel quadrilateral 梯形 trapezoid */ this.paraline = function(x, y, r, rot) { rot = rot ? -rot : 0; y = y ? -y : 0; plot.beginPath() .moveTo(x, y) .lineTo(x + r * Math.cos(rot), y + r*Math.sin(rot)) .moveTo(x, y + r/ 10) .lineTo(x + r * Math.cos(rot), y+r/10 + r*Math.sin(rot)) .closePath() .stroke(); }; this.paraquad = function(x, y, rot, a, b, angle) { angle = angle ?

Math.abs(angle) : 0; rot = rot ? rot : 0; //參数说明: //平行四边形的两条边a, b, 以及它们之间的夹角angle //这个平行四边形的起始点(x, y), 以及整个图形与x轴的夹角rot var retArray = new Array(); retArray.push([x, -y]); retArray.push([x + a * Math.cos(rot), -(y + a * Math.sin(rot))]); retArray.push([x + a * Math.cos(rot)+ b * Math.cos(rot+angle), -(y + a * Math.sin(rot)+ b * Math.sin(rot+angle))]); retArray.push([x + b * Math.cos(rot+angle), -(y + b * Math.sin(rot+angle))]); return retArray; } this.trapezoid = function(x, y, rot, a, b, angle) { angle = angle ? Math.abs(angle) : 0; rot = rot ? rot : 0; //參数说明: //等腰梯形的下底边a。腰b, 以及它们之间的夹角angle //如果下底 > 上底。那么上底 = (a - b * Math.cos(angle)*2)/2 //这个平行四边形的起始点(x, y), 以及整个图形与x轴的夹角rot var c = (a - b * Math.cos(angle)*2)/2; var retArray = new Array(); if (c < 0) { //说明给的条件不正确 //缺省画上底是下底一半的梯形 } else { retArray.push([x, -y]); retArray.push([x + a * Math.cos(rot), -(y + a * Math.sin(rot))]); retArray.push([x + b * Math.cos(rot+angle)+2*c * Math.cos(rot), -(y + b * Math.sin(rot+angle)+2*c*Math.sin(rot))]); retArray.push([x + b * Math.cos(rot+angle), -(y + b * Math.sin(rot+angle))]); } return retArray; } /** * @usage 用于绘制空间几何体的側面边线 * @author mw * @date 2016年04月10日 星期日 11:35:40 * @param * @return * */ this.lineDraw = function(array, style, scale) { //array的格式[ [线段起点(x,y), 线段终点(x, y)], ...], 每条线段有四个元素确定 style = style ? style : 'black'; scale = scale ? scale : 1; var newArray = new Array(); var size = array.length; var itemSize = array[0].length; var item = []; //缩放步骤 for (var i = 0; i < size; i++) { item = []; for (var j = 0; j < itemSize; j++) { if (j % 2 == 0) { //x坐标 item.push(array[i][j] * scale); } else { //y坐标 item.push(- array[i][j] * scale); } } newArray.push(item); } //document.write(newArray.join(', ')); plot.save() .setStrokeStyle(style); for (var i = 0; i < size; i++) { plot.beginPath() .moveTo(newArray[i][0], newArray[i][1]) .lineTo(newArray[i][2], newArray[i][3]) .closePath() .stroke(); } plot.restore(); } /** * @usage 用于绘制空间几何体的側面填充面域 * @author mw * @date 2016年04月10日 星期日 11:35:40 * @param * @return * */ this.faceDraw = function(array, style, scale) { //array的格式[ [线段起点(x,y), 线段终点(x, y)], ...], 每条线段有四个元素确定 style = style ? style : 'black'; scale = scale ? scale : 1; var newArray = new Array(); var size = array.length; var itemSize = array[0].length; var item = []; //缩放步骤 for (var i = 0; i < size; i++) { item = []; for (var j = 0; j < itemSize; j++) { if (j % 2 == 0) { //x坐标 item.push(array[i][j] * scale); } else { //y坐标 item.push(- array[i][j] * scale); } } newArray.push(item); } //document.write(newArray.join(', ')); plot.save() .setFillStyle(style) .setStrokeStyle('yellow') .setLineWidth(4); var x1 = x2 = y1 = y2 = 0, x3 = x4 = y3 = y4 = 0; for (var i = 0; i < size; i++) { x1 = newArray[i][0]; y1 = newArray[i][1]; x2 = newArray[i][2]; y2 = newArray[i][3]; if (i < size - 1) { x3 = newArray[i+1][0]; y3 = newArray[i+1][1]; x4 = newArray[i+1][2]; y4 = newArray[i+1][3]; } else { x3 = newArray[0][0]; y3 = newArray[0][1]; x4 = newArray[0][2]; y4 = newArray[0][3]; } plot.beginPath() .moveTo(x1, y1) .lineTo(x2, y2) .lineTo(x4, y4) .lineTo(x3, y3) .closePath() .fill(); } for (var i = 0; i < size; i++) { x1 = newArray[i][0]; y1 = newArray[i][1]; x2 = newArray[i][2]; y2 = newArray[i][3]; plot.beginPath() .moveTo(x1, y1) .lineTo(x2, y2) .closePath() .stroke(); } plot.restore(); } /** * @usage 用于获取椭圆的坐标数组 * @author mw * @date 2016年04月10日 星期日 11:35:40 * @param * @return * */ //获取椭圆上点的坐标 this.ellipse = function(a, b) { //a, b 分别为椭圆的长、短半轴 var retArray = new Array(); var thita = 0; //椭圆的圆周分成的线段数量,这个值越大越精确 var N = 32; var deltaThita = Math.PI*2/N; var x = y = 0; for (var i = 0; i < N; i++) { x = a*Math.cos(thita); y = b*Math.sin(thita); retArray.push([x, y]); thita += deltaThita; } return retArray; } /** * @usage 用于获取矩形的坐标数组 * @author mw * @date 2016年04月10日 星期日 11:35:40 * @param * @return * */ this.rect = function(w, h) { return [[-w/2, -h/2], [-w/2, h/2], [w/2, h/2], [w/2, -h/2]]; } /** * @usage 绘制圆形 * @author mw * @date 2015年11月27日 星期五 12:11:38 * @param * @return * */ this.strokeCircle = function(x, y, r) { plot.beginPath() .arc(x, y, r, 0, 2*Math.PI, true) .closePath() .stroke(); } this.fillCircle = function(x, y, r) { plot.beginPath() .arc(x, y, r, 0, 2*Math.PI, true) .closePath() .fill(); } //绘制椭圆 this.strokeEllipse = function(x, y, a, b, rotate) { //关键是bezierCurveTo中两个控制点的设置 //0.5和0.6是两个关键系数(在本函数中为试验而得) var ox = 0.5 * a, oy = 0.6 * b; var rot = rotate ? -rotate : 0; plot.save() .rotate(rot) .translate(x, y) .beginPath() //从椭圆纵轴下端開始逆时针方向绘制 .moveTo(0, b) .bezierCurveTo(ox, b, a, oy, a, 0) .bezierCurveTo(a, -oy, ox, -b, 0, -b) .bezierCurveTo(-ox, -b, -a, -oy, -a, 0) .bezierCurveTo(-a, oy, -ox, b, 0, b) .closePath() .stroke() .restore(); } //绘制椭圆 this.fillEllipse = function(x, y, a, b, rotate) { //关键是bezierCurveTo中两个控制点的设置 //0.5和0.6是两个关键系数(在本函数中为试验而得) var ox = 0.5 * a, oy = 0.6 * b; var rot = rotate ? -rotate : 0; plot.save() .rotate(rot) .translate(x, y) .beginPath() //从椭圆纵轴下端開始逆时针方向绘制 .moveTo(0, b) .bezierCurveTo(ox, b, a, oy, a, 0) .bezierCurveTo(a, -oy, ox, -b, 0, -b) .bezierCurveTo(-ox, -b, -a, -oy, -a, 0) .bezierCurveTo(-a, oy, -ox, b, 0, b) .closePath() .fill() .restore(); } /** * @usage 绘制正方体 * @author mw * @date 2016年02月01日 星期一 08:40:27 * @param * @return * */ this.drawCubic = function(x0, y0, z0, r, style, style2, style3) { plot.save(); x0*=r; y0*=r; z0*=r; z0 = z0 /2; x0 = x0 - z0*0.707; y0 = y0 + z0*0.707; z0 = 0; plot.translate(x0, y0); style = style ? style : 'black'; style2 = style2 ?

style2 : style; style3 = style3 ?

style3 : style; var transform = new Transform(); //左下角[x0, y0,边长r shape.fillDraw(shape.nEdge(0, 0,0.707*r, 4, 0), style); //顶面 shape.fillDraw(transform.flipX(shape.paraquad(-0.5*r, 0.5*r, 0, r, r/2, Math.PI/4)), style2); shape.strokeDraw(transform.flipX(shape.paraquad(-0.5*r, 0.5*r, 0, r, r/2, Math.PI/4)), 'white'); //右側面 shape.fillDraw(transform.flipX(shape.paraquad(0.5*r, -0.5*r, Math.PI/4, r/2, r, Math.PI/4)), style3); shape.strokeDraw(transform.flipX(shape.paraquad(0.5*r, -0.5*r, Math.PI/4, r/2, r, Math.PI/4)), 'white'); plot.restore(); } this.point3D = function(x0, y0, z0) { //canvas中y轴坐标向下为正。与笛卡尔坐标系相反 //所以此处先取反 // z0 = z0 /2; x0 = -(x0 - z0*0.707); y0 = y0 + z0*0.707; return [x0, y0]; } //左视投影,此时x坐标是无所谓的 this.pointLeft = function(x0, y0, z0) { return [z0, y0]; } //右视投影 this.pointRight = function(x0, y0, z0) { return [-z0, y0]; } //鸟瞰投影 this.pointTop = function(x0, y0, z0) { return [x0, -z0]; } //仰视投影 this.pointBottom = function(x0, y0, z0) { return [x0, z0]; } //主视投影 this.pointFront = function(x0, y0, z0) { return [x0, y0]; } //后视投影 this.pointBack = function(x0, y0, z0) { return [-x0, y0]; } this.strokeCubic = function(x0, y0, z0, r, style) { plot.save(); x0 *= r; y0 *= r; z0 *= r; r *= 0.5; var array = [[-r, -r], [-r, r], [r, r], [r, -r]]; var top = []; var left = []; var front = []; var x, y, z; //存放暂时点 var p = []; for (var i = 0; i < 4; i++) { x = (x0+array[i][0]); y = y0+r; z = (z0+array[i][1]); p = this.point3D(x, y, z); top.push([p[0], -p[1]]); } for (var i = 0; i < 4; i++) { x = x0+r; y = (y0+array[i][0])+2*r; z = z0+array[i][1]; p = this.point3D(x, y, z); left.push([p[0], -p[1]]); } for (var i = 0; i < 4; i++) { x = x0+array[i][0]; y = (y0+array[i][1])+2*r; z = z0+r; p = this.point3D(x, y, z); front.push([p[0], -p[1]]); } var tmp = [].concat(top); shape.fillDraw(tmp, style); tmp=[].concat(top); shape.strokeDraw(tmp, '#cccccc'); tmp = [].concat(left); shape.strokeDraw(left, 'black'); tmp = [].concat(front); shape.strokeDraw(front, 'black'); plot.restore(); } /** * @usage 把三维点阵列依照z, y, x优先级由小到大排列 * @author mw * @date 2016年02月23日 星期二 09:38:27 * @param [[x1, y1, z1], [x2,y2, z2], ...] * @return 排序后的[[x, y, z]...] * */ this.xyzSort = function(array) { var arr = new Array(); arr = array; arr.sort(function(a, b) { if (a[2] != b[2]) { return (a[2] - b[2]); } else { if (a[1] != b[1]) { return (a[1] - b[1]); } else { return (a[0] - b[0]); } } }); //document.write(arr); return arr; } //把给定的坐标点阵列数组[x, y],...依照距离它们的中心点的角度进行排列 //是为了把无序排列的闭合曲线上的点进行有序排列,兴许可再经过连线形成 //可填充的闭合曲线 this.angularSort = function(array) { var a = new Array(); a = [].concat(array); var len = a.length, len1 = a[0].length; //不符合处理条件,不进行处理 if (len <= 0 || len1 != 2) return array; //求中心点 var xTotal = 0, yTotal = 0, xCenter = 0, yCenter = 0; for (var i = 0; i < len; i++) { xTotal += a[i][0]; yTotal += a[i][1]; } xCenter = xTotal/len; yCenter = yTotal/len; //求与中心点夹角并排序 var b = new Array(); var x, y, xdiff, ydiff; for (var i = 0; i < len; i++) { x = a[i][0]; y = a[i][1]; xdiff = x-xCenter; ydiff = y-yCenter; if (Math.abs(xdiff)<0.0001) { if (ydiff > 0) { b.push([x, y, Math.PI/2]); } else { b.push([x, y, Math.PI/2*3]); } } else if ( xdiff >= 0 && ydiff > 0) {//第一象限 b.push([x, y, Math.atan(Math.abs(ydiff/xdiff))]); } else if (xdiff < 0 && ydiff >= 0) {//第二象限 b.push([x, y, Math.PI-Math.atan(Math.abs(ydiff/xdiff))]); } else if (xdiff <= 0 && ydiff < 0) {//第三象限 b.push([x, y, Math.PI+Math.atan(Math.abs(ydiff/xdiff))]); } else {//第四象限 b.push([x, y, Math.PI*2-Math.atan(Math.abs(ydiff/xdiff))]); } } b.sort(function(b1, b2) { if (Math.abs(b1[2]-b2[2]) < 0.0001) { //依照与中心点的距离大小排序 var d1 = (b1[0]-xCenter)*(b1[0]-xCenter)+ (b1[1]-yCenter)*(b1[1]-yCenter); var d2 = (b2[0]-xCenter)*(b2[0]-xCenter)+ (b2[1]-yCenter)*(b2[1]-yCenter); return -(d1-d2); } else { return (b1[2]-b2[2]); } }); var retArray = new Array(); for (var i = 0; i < len; i++) { //如果两个点在经过中心点的同一直线上。舍弃这个点 //由于它表示点阵列可能不是单一环,或不是闭合曲线 if (i > 0 && Math.abs(b[i][2]-b[i-1][2]) < 0.0001) continue; retArray.push([b[i][0], b[i][1]]); } return retArray; } /** * @usage 三视图 * @author mw * @date 2016年02月23日 星期二 09:49:23 * @param * @return * */ this.threeView = function(array, style) { var cubic = this.xyzSort(array); plot.save(); plot.setTransform(1, 0, 0, 1, 0, 0) .translate(300, 200); //三维图和三视图 var r = 50; style = style ? style : 'red'; var len = cubic.length; for (var i = 0; i < len; i++) { this.drawCubic(cubic[i][0], -cubic[i][1], cubic[i][2], r, style); } var height = 400; r = r/3; plot.setTransform(1, 0, 0, 1, 0, 0); plot.fillText('左视图', 20, 20, 100); plot.fillText('主视图', 20, 20+1*height/3, 100); plot.fillText('鸟瞰图', 20, 20+2*height/3, 100); plot.setFillStyle(style) .setStrokeStyle('white'); //左视图 plot.translate(100, 80); for (var i = 0; i < len; i++) { //y, z两坐标,z坐标变为x坐标 this.fillRect(cubic[i][2]*r, -cubic[i][1]*r, r, r); this.strokeRect(cubic[i][2]*r, -cubic[i][1]*r, r, r); } //主视图 plot.translate(0, 130); for (var i = 0; i < len; i++) { //x, y两坐标 this.fillRect(cubic[i][0]*r, -cubic[i][1]*r, r, r); this.strokeRect(cubic[i][0]*r, -cubic[i][1]*r, r, r); } //鸟瞰图 plot.translate(0, 100); for (var i = 0; i < len; i++) { //x, z两坐标。z坐标变为y坐标 this.fillRect(cubic[i][0]*r, cubic[i][2]*r, r, r); this.strokeRect(cubic[i][0]*r, cubic[i][2]*r, r, r); } plot.restore(); } //绘制球体 this.sphere = function(pos/*[x, y, z]*/, r, style) { plot.save(); var x, y; var p = [].concat(pos); if (p.length == 2) { x = p[0]; y = p[1]; } else if (p.length == 3) { var p1 = shape.point3D(p[0], -p[1], p[2]); x = p1[0]; y = p1[1]; } var r0 = 0.1*r; var grd = plot.createRadialGradient(x, y, r, x+0.3*r, y-0.3*r, r0); grd.addColorStop(0, style); grd.addColorStop(1, 'white'); plot.setFillStyle(grd); shape.fillCircle(x, y, r); plot.restore(); } return { fillRect:fillRect, strokeRect:strokeRect, fillCircle:fillCircle, strokeCircle:strokeCircle, strokeEllipse:strokeEllipse, fillEllipse:fillEllipse, //绘制点阵列 pointDraw:pointDraw, multiLineDraw:multiLineDraw, strokeDraw:strokeDraw, fillDraw:fillDraw, //空间几何体相关 lineDraw:lineDraw, faceDraw:faceDraw, //多边形角度标注 angleDraw:angleDraw, //多边形面积标注 areaDraw:areaDraw, //三角形面积计算(已知三个点坐标) areaCalc:areaCalc, //几何形状 rect:rect, ellipse:ellipse, nEdge:nEdge, nStar:nStar, paraline:paraline, paraquad:paraquad, trapezoid:trapezoid, //绘制立方体 drawCubic:drawCubic, strokeCubic:strokeCubic, //绘制球体 sphere:sphere, //三维点映射 point3D:point3D, pointLeft:pointLeft, pointRight:pointRight, pointTop:pointTop, pointBottom:pointBottom, pointFront:pointFront, pointBack:pointBack, //三视图 threeView:threeView, //顶点排序 xyzSort:xyzSort, angularSort:angularSort }; }();


/**
* @usage   矩阵类
* @author  mw
* @date    2016年03月24日  星期四  14:51:45 
* @param
* @return
*
*/
function Matrix() {
	this.delta = function(matrix) {
		var size = matrix.length;
		
		if (!matrix[0].length) {
			return 0;
		}
		else {
			if (matrix[0].length != size) {
				return 0;
			}
			
			if (size < 1) {
				return 0;
			}
			else if (size == 1) {
				return matrix[0][0];
			}
			else {
				var d = 0;
				var subMatrix = [];
				
				for (var i = 0; i < size; i++) {
					subMatrix = this.subSet(matrix, i, 0);
					d += Math.pow(-1, i)*matrix[i][0]*this.delta(subMatrix);
				}
				return d;
			}
		}
	}
	
	this.subSet = function(matrix, row, col) {	
		var size = matrix.length;
		
		if (!matrix[0].length) {
			return [];
		}
		else {
			if (matrix[0].length != size) {
				return [];
			}
			
			var newMatrix = new Array();
			var rowArray= new Array();
			
			for (var i = 0; i < size; i++) {
				if (i == row) {
					continue;
				}
				else {
					rowArray = [];
				
					for (var j = 0; j < size; j++) {
						if (j == col) {
							continue;
						}
						else {
							rowArray.push(matrix[i][j]);
						}
					}
					
					newMatrix.push(rowArray)
				}
			}
			
			return newMatrix;
		}
	}
	
	this.identityMatrix = function(rank) {
		var newMatrix = new Array();
		var rowArray= new Array();
		
		for (var i = 0; i < rank; i++) {
			rowArray = [];
			
			for (var j = 0; j < rank; j++) {
				if (j == i) {
					rowArray.push(1);
				}
				else {
					rowArray.push(0);
				}
			}
			
			newMatrix.push(rowArray);
		}
		
		return newMatrix;
	}
	
	//把从1-n的n个数按顺序放到矩阵中
	this.sequenceMatrix = function(rank) {
		var newMatrix = new Array();
		var rowArray= new Array();
		
		var count = 0;
		for (var i = 0; i < rank; i++) {
			rowArray = [];
			
			for (var j = 0; j < rank; j++) {
				count++;
				rowArray.push(count);
				
			}
			
			newMatrix.push(rowArray);
		}
		
		return newMatrix;
	}
	
	
	this.print = function(matrix) {
		var size = matrix.length;
		
		if (!matrix[0].length) {
			return [];
		}
		else {
			var rSize = matrix[0].length;
			
			var s = '';
			
			for (var i = 0; i < size; i++) {
				s = '';
				
				for (var j = 0; j < rSize; j++) {
					s += matrix[i][j].toFixed(2) + ' , ';
				}
				
				document.write(s+'<br/>');
			}
		}
	}
					
	this.deepCopy = function(matrix) {
		var size = matrix.length;
		
		if (!matrix[0].length) {
			return [];
		}
		else {
			var rSize = matrix[0].length;
			
			var newMatrix = new Array();
			var rowArray= new Array();
			
			for (var i = 0; i < size; i++) {
				rowArray = [];
				
				for (var j = 0; j < rSize; j++) {
					rowArray.push(matrix[i][j]);
				}
				newMatrix.push(rowArray);
			}
			return newMatrix;
		}
	}
	
}

/**
* @usage   对点阵列数组进行平移。旋转,缩放,对称等变形
* @author  mw
* @date    2016年03月20日  星期日  13:24:58 
* @param   传入点阵列矩阵
* @return  输出变形后的点阵列矩阵
*
*/
function Transform() {
	this.translate = function(array, xOffset, yOffset) {
		var len = array.length;
		
		if (len == 0) {
			return [];
		}
		else {
			var len1 = array[0].length;
			
			if (len1 != 2) {
				//假设不是点阵列[..., [x,y], [x1,y1], ...]的格式。临时不加处理
				return array;
			}
			else {
				var retArray = new Array();
				var x = 0, y = 0;
				
				for (var i = 0; i < len; i++) {
					x = array[i][0] + xOffset;
					y = array[i][1] + yOffset;
					
					retArray.push([x, y]);
				}
			}
		}
		
		return retArray;
	}
	
	this.scale = function(array, xScale, yScale) {
		var len = array.length;		
		
		if (len == 0) {
			return [];
		}
		else {
			xScale = xScale ? xScale : 1;
			yScale = yScale ?

yScale : xScale; var len1 = array[0].length; if (len1 != 2) { //假设不是点阵列[..., [x,y], [x1,y1], ...]的格式,临时不加处理 return array; } else { var retArray = new Array(); var x = 0, y = 0; for (var i = 0; i < len; i++) { x = array[i][0] * xScale; y = array[i][1] * yScale; retArray.push([x, y]); } } } return retArray; } this.rotate = function(array, angle) { var len = array.length; if (len == 0) { return []; } else { var len1 = array[0].length; if (len1 != 2) { //假设不是点阵列[..., [x,y], [x1,y1], ...]的格式,临时不加处理 return array; } else { var retArray = new Array(); var x = 0, y = 0; var sinA, cosA; for (var i = 0; i < len; i++) { sinA = Math.sin(angle); cosA = Math.cos(angle); x = array[i][0] * cosA - array[i][1]*sinA; y = array[i][0] * sinA + array[i][1]*cosA; retArray.push([x, y]); } } } return retArray; } this.flipX = function(array) { return this.flipImplement(array, 'X'); } this.flipY = function(array) { return this.flipImplement(array, 'Y'); } this.flipXY = function(array) { return this.flipImplement(array, 'XY'); } //关于直线y=kx轴对称 this.flip = function(array, slope) { //slope为斜率k var mode = slope.toFixed(3); return this.flipImplement(array, mode); } this.flipImplement = function(array, mode) { var len = array.length; if (len == 0) { return []; } else { var len1 = array[0].length; if (len1 != 2) { //假设不是点阵列[..., [x,y], [x1,y1], ...]的格式,临时不加处理 return array; } else { var retArray = new Array(); var x = 0, y = 0; var sinA, cosA; var m = 0, n = 0; if (mode == 'X') { for (var i = 0; i < len; i++) { //关于X轴对称, x = array[i][0]; y = -array[i][1]; retArray.push([x, y]); } } else if (mode == 'Y') { for (var i = 0; i < len; i++) { //关于Y轴对称, x = -array[i][0]; y = array[i][1]; retArray.push([x, y]); } } else if (mode == 'XY') { for (var i = 0; i < len; i++) { //中心对称 x = -array[i][0]; y = -array[i][1]; retArray.push([x, y]); } } else { //模式为斜率 y = kx中k的字符串 k = parseFloat(mode); for (var i = 0; i < len; i++) { //可扩展 //此处先放大100倍再缩小是由于对于小尺寸 //计算误差太大。而假设尺寸太大, //标注会占用太多地方。造成文字拥挤。无法读取 m = array[i][0]*10000; n = array[i][1]*10000; //x = (m-2*k+2*k*n-m*k*k)/(1+k*k); x = (1-k*k)*m+2*k*(n-1)/(1+k*k); //y = (-n+2*k*m+n*k*k)/(1+k*k); y = (2*k*m-(1-k*k)*n)/(1+k*k); retArray.push([x/10000, y/10000]); } } } } return retArray; } }




本节到此结束。欲知后事怎样,请看下回分解。

[从头学数学] 第172节 直线与方程