[从头学数学] 第172节 直线与方程
Posted cynchanpin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[从头学数学] 第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节 直线与方程的主要内容,如果未能解决你的问题,请参考以下文章