首页 > 解决方案 > 三角形相似吗?

问题描述

您在一个平面上有两个三角形 a1 b1 c1 和 a2 b2 c3。您的任务是确定它们是否存在,即它们对应的角度是否具有相同的测量值。

坐标是一个

大批 []

let coord = [0, 0, 0, 1, 1, 0, 0, 0, 0, -3, -3, 0];

其中 a1 是 (coord[0],coord[1]), b1 (coord[2],coord[3]) ...

let s = [0, 0, 0, 1, 1, 0, 0, 0, 0, -3, -3, 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, angle2, 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))

这是我的尝试,但没有通过所有测试,有更好的主意吗?

感谢姆博

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, 4, 7, 6, 1, -2, -1, 0, 5, 4, -7];

console.log(areTrianglesSimilar(coordinates))

标签: javascripttypescriptgeometry

解决方案


这里有很多错误。除了这些,您可能应该考虑将代码重构为单独的函数,这些函数封装了通常执行的计算。这将减少不必要的重复并减少复制粘贴拼写错误的可能性。它还将使代码更具自我记录性,从而使人们能够更好地理解您在做什么。

假设您想确定三角形的角度并比较它们(但您也可以使用@MBo 指出的边长比),我将遵循的一般方法是:

  • 编写一个函数将坐标数组转换为一对Triangle对象,其中 a是对象Triangle的三元Point,定义如下:

    type Triangle = [Point, Point, Point];
    interface Point { x: number, y: number };
    
    function toTrianges(coords: number[]): [Triangle, Triangle] {
      // implement this
    }
    
  • 编写一个函数,它接受三个Points、A、B 和 C,并返回角度 ∡ABC(以 B 作为顶点)的(绝对值)度量,例如度数:

    function measureAngleABC(a: Point, b: Point, c: Point): number {
        // implement this
    }
    
  • 为了做到这一点,您可能想要编写将两个Points 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 */ }
    

    请注意,两个向量之间的(无符号)角度可以通过检查它们的长度和它们的点积来确定。

  • 一旦你有了这些,你应该能够将 aTriangle变成它的(无符号)角度的(排序的)三元组:

    type TriangleAngles = [number, number, number];
    function angles(triangle: Triangle): TriangleAngles { /* impl * }
    
  • 最后,编写一个比较两个近似TriangleAngles相等的函数。不是真正的平等使用,它充满了麻烦。由于浮点s 没有无限精度,因此应该产生相同数量的两个不同计算实际上可能会产生两个不同的浮点结果。著名的例子就是。当您比较两个时,您需要确定“足够接近”的接近程度以调用两个相似的三角形:===number0.1 + 0.2 === 0.3falseTriangleAngles

    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]))看起来像一个带有索引的错字,因为您似乎是在比较一个三角形中的一个点和另一个三角形上的一个点。如果您进行重构以便从数字数组移动到像一对Triangles 之类的东西,那么这种错字的可能性就会大大降低。

  • 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-component-of-length 和 y-component-of-length的向量很重要,但是当您只是将这些组件相加时,您会丢弃您需要的信息。您可以通过想出一个三角形来验证这一点,该三角形可以交换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现在不可能是垂直腿之一。

嗯,我想我必须在这里停下来。我只想说,如果你能通过调整它来让这个算法工作,我会感到非常惊讶。我强烈建议从执行定义明确的计算的可重用函数重新开始。

祝你好运。


推荐阅读