问题描述
您在一个平面上有两个三角形a1 b1 c1和a2 b2 c3。您的任务是确定它们是否存在,即它们对应的角度是否具有相同的测量值。
坐标是
数组[]
let coord = [0,1,-3,0];
其中a1是(coord [0],coord [1]),b1(coord [2],coord [3])...
let s = [0,0]
function areTrianglesSimilar(c) {
let result = null
let line1 = (Math.abs(c[2]) - Math.abs(c[0])) + (Math.abs(c[3]) - Math.abs(c[1]))
let line2 = (Math.abs(c[4]) - Math.abs(c[0])) + (Math.abs(c[5]) - Math.abs(c[1]))
let line3 = Math.abs(Math.sqrt( Math.pow(line1,2)+ Math.pow(line2,2)))
console.log(line1,line2,line3)
let angle1 = Math.atan2(line1,line2) * 180 / Math.PI
let angle2 = Math.atan2(line1,line3) * 180 / Math.PI
let angle3 = 180 - (angle1 + angle2)
console.log(angle1,angle2,angle3)
let arr1 = []
arr1.push(angle1,angle3)
let line4 = (Math.abs(c[8]) - Math.abs(c[6])) + (Math.abs(c[9]) - Math.abs(c[7]))
let line5 = (Math.abs(c[10]) - Math.abs(c[0])) + (Math.abs(c[11]) - Math.abs(c[1]))
let line6 = Math.abs(Math.sqrt( Math.pow(line4,2)+ Math.pow(line5,2)))
console.log(line4,line5,line6)
let angle4 = Math.atan2(line4,line5) * 180 / Math.PI
let angle5 = Math.atan2(line4,line6) * 180 / Math.PI
let angle6 = 180 - (angle4 + angle5)
console.log(angle6,angle5,angle4)
if (arr1.includes(angle4) && arr1.includes(angle5) && arr1.includes(angle6)){
return result = true
} else return result = false
}
console.log(areTrianglesSimilar(s))
这是我的尝试,但是没有通过所有测试,还有更好的主意吗?
感谢Mbo
function areTrianglesSimilar(c) {
let dx1 = c[2] - c[0];
let dy1 = c[3] - c[1];
let dx2 = c[4] - c[0];
let dy2 = c[5] - c[1];
let dx3 = c[4] - c[2];
let dy3 = c[5] - c[3];
let l1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
let l2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
let l3 = Math.sqrt(dx3 * dx3 + dy3 * dy3);
console.log(l1,l2,l3);
let angle12 = Math.acos((dx1 * dx2 + dy1 * dy2) / (l1 * l2));
let angle13 = Math.acos((dx1 * dx3 + dy1 * dy3) / (l1 * l3));
let angle23 = Math.acos((dx3 * dx2 + dy3 * dy2) / (l3 * l2));
console.log(angle12,angle13,angle23);
let dx4 = c[8] - c[6];
let dy4 = c[9] - c[7];
let dx5 = c[10] - c[6];
let dy5 = c[11] - c[7];
let dx6 = c[10] - c[8];
let dy6 = c[11] - c[9];
let l4 = Math.sqrt(dx4 * dx4 + dy4 * dy4);
let l5 = Math.sqrt(dx5 * dx5 + dy5 * dy5);
let l6 = Math.sqrt(dx6 * dx6 + dy6 * dy6);
console.log(l4,l5,l6);
let angle45 = Math.acos((dx4 * dx5 + dy4 * dy5) / (l4 * l5));
let angle46 = Math.acos((dx4 * dx6 + dy4 * dy6) / (l4 * l6));
let angle56 = Math.acos((dx6 * dx5 + dy6 * dy5) / (l6 * l5));
console.log(angle45,angle46,angle56);
if (angle12 == angle45 && angle13 == angle46){
console.log('result'+':'+ true);
} else console.log("result" + ":" + false);
}
let coordinates = [3,4,7,6,-2,-1,5,-7];
console.log(areTrianglesSimilar(coordinates))
解决方法
这里有很多错误。除了这些,您可能应该考虑将代码重构为单独的函数,这些函数封装了常用的计算。这将减少不必要的重复,并减少复制粘贴错别字的可能性。还将使代码更具自我记录性,使人们可以了解您在做的更好。
假设您要确定三角形的角度并进行比较(但是您也可以使用边长比,如@MBo所指出的那样),我遵循的一般方法是:
-
编写一个函数,将坐标数组转换为一对
Triangle
对象,其中Triangle
是Point
对象中三分之三tuple的定义像这样:type Triangle = [Point,Point,Point]; interface Point { x: number,y: number }; function toTrianges(coords: number[]): [Triangle,Triangle] { // implement this }
-
编写一个函数,该函数接受三个
Point
,A,B和C,然后返回角度∡ABC(以B为顶点)的量度(的绝对值)。 ,度:function measureAngleABC(a: Point,b: Point,c: Point): number { // implement this }
-
为此,您可能需要编写将两个
Point
的A和B转换成Vector
从A到B并操纵向量的函数:>type Vector = Point; function vector(a: Point,b: Point): Vector { /* impl */ } function vectorLength(v: Vector): number { /* impl */ } function dotProduct(v1: Vector,v2: Vector): number { /* impl */ }
请注意,可以通过检查两个向量的长度及其dot product来确定两个向量之间的(无符号)角度。
-
一旦有了这些,您应该可以将
Triangle
变成其(无符号)角度的(排序的)三元组:type TriangleAngles = [number,number,number]; function angles(triangle: Triangle): TriangleAngles { /* impl * }
-
最后,编写一个函数,比较两个
TriangleAngles
是否等于 。使用===
(即fraught with troubles)不是 actual 等式。由于浮点number
的精度不是无限的,因此应该产生相同数量的两个不同计算实际上可能会产生两个不同的浮点结果。著名的例子是0.1 + 0.2 === 0.3
是false
。比较两个TriangleAngles
时,需要确定“足够接近”到什么程度才能调用两个相似的三角形:function areNearlyEqual(ta1: TriangleAngles,ta2: TriangleAngles): boolean { // impl here }
我不会写出如何实现这些功能,因为这看起来像是一项使您从实际受益最大的练习,而不是有人为您这样做。
无论如何,这是我在您的代码中看到的错误:
-
(Math.abs(c[10]) - Math.abs(c[0])) + (Math.abs(c[11]) - Math.abs(c[1]))
行看起来像是带有索引的错字,因为您似乎正在将一个三角形中的一个点与另一个三角形上的一个点进行比较。如果您进行重构,以便从数字数组移至一对Triangle
之类的东西,这种错别字的可能性将大大降低。 -
对于某个索引
Math.abs(c[k])
,所有形式为k
的代码都是高度可疑的。c[k] === 100
与c[k] === -100
相同。如果您采用三角形并翻转其顶点之一的x或y坐标的符号,几乎可以肯定的是,通过在x或y轴上反射该顶点来改变三角形的形状:如果您的代码无法分辨出这两个三角形之间的差异,则将无法准确确定两个三角形是否相似。
-
线
let line1 = (Math.abs(c[2]) - Math.abs(c[0])) + (Math.abs(c[3]) - Math.abs(c[1]))
及其弟兄们似乎在看一个三角形的边之一,并将其长度的x分量加到其y分量的 获得单个数字的长度。这并不代表我能想到的任何事情。长度x分量和长度y分量的 vector 很重要,但是当您仅将分量添加在一起时,就会丢弃您需要的信息。您可以通过提出一个三角形来自己验证这一点,在该三角形上交换c[2]
和c[3]
会改变其形状,但是上面的代码不会有任何区别。 -
第
let line3 = Math.abs(Math.sqrt( Math.pow(line1,2)+ Math.pow(line2,2)))
行似乎假设line1
和line2
代表直角三角形两侧的长度,而line3
是斜边的长度。但是除非您的两侧真的彼此垂直,否则这不是真的。 -
线
let angle2 = Math.atan2(line1,line3) * 180 / Math.PI
在计算角度,但是什么角度?您只能使用反正切线从直角三角形的相对侧和相邻侧获取角度。但是这里可能没有直角三角形,并且由于早先假设line3
是直角三角形的斜边,其中边的一侧是line1
,所以line3
现在不可能垂直的腿。
嗯,我想我必须在这里停下来。只需说一下,如果您可以通过调整算法使它起作用,我将感到非常惊讶。我强烈建议您从执行定义良好的计算的可重用函数开始。
祝你好运。
,您的计算是完全错误的。点积法:
dx1 = c[2] - c[0]
dy1 = c[3] - c[1]
dx2 = c[4] - c[0]
dy2 = c[5] - c[1]
dx3 = c[4] - c[2]
dy3 = c[5] - c[3]
l1 = Math.sqrt(dx1*dx1+dy1*dy1)
l2 = Math.sqrt(dx2*dx2+dy2*dy2)
l3 = Math.sqrt(dx3*dx3+dy3*dy3)
angle12 = Math.acos((dx1*dx2+dy1*dy2)/(l1*l2)
和angle13类似,以后您只需要比较两个角度是否相等
if angle12 == angle45 and angle13 == angle46 ...
或使用一些epsylon值来避免浮动计算错误
if abs(angle12 -angle45) < 0.0000001 ...
此外,您可以避开角度并比较边长比
if l1/l4==l2/l5 and l1/l4==l3/l6...