Ответы пользователя по тегу Python
  • Есть массив треугольников, заданных координатами вершин. Как определить номера треугольников, подобных первому?

    1. Проверять подобие по соотношениям периметра и площади -- недостаточно. Контрпример есть в комментарии @tsarevfs, теоретическое обоснование -- в комментарии @jcmvbkbc.

    2. Если треугольники заданы координатами вершин -- проще всего проверять третий признак подобия (все три стороны одного треугольника пропорциональны сторонам другого).

    3. Если координаты вершин -- небольшие целые числа, то лучше проверять пропорциональность не самих сторон, а их квадратов, причем проверять не отношения сторон, а произведения "крест-накрест".
    Чтобы сравнивать только потенциально соответственные стороны -- сортировать длины сторон (на самом деле квадраты длин) в каждом треугольнике по возрастанию.

    Например, вот так можно модифицировать исходный код:
    # квадрат расстояния между двумя точками
    def length2(a, b):
        return (a[0] - b[0])**2 + (a[1] - b[1])**2
    
    # подобны ли 2 треугольника, заданные отсортированными массивами длин сторон
    def is_sim(sample, triangle):
        if sample[0] * triangle[1] != sample[1] * triangle[0]:
            return False
        elif sample[0] * triangle[2] != sample[2] * triangle[0]:
            return False
        elif sample[1] * triangle[2] != sample[2] * triangle[1]:
            return False
        else:
            return True
    
    # преобразование массивов координат в массивы длин сторон
    def make_triangles(v):
        triangles = []
        for i in v:
            a2 = length2(i[0], i[1])
            b2 = length2(i[0], i[2])
            c2 = length2(i[1], i[2])
            triangle = [a2, b2, c2]
            triangle.sort()
            triangles.append(triangle)
        return triangles
    
    # основной код
    triangles = make_triangles(v)
    
    for i in range(1, len(triangles) ):
        if is_sim(triangles[0], triangles[i]):
            print "found similar trinangle: %s" % v[i]


    Если координаты могут быть большими и/или вещественными, то лучше вернуться к длинам и отношениям, но при сравнении в фунции is_sim полагаться не на точное равенство, а с допуском ("с эпсилонами", см. комментарии @bluesky и @tsarevfs)

    И на всякий случай: в комментариях были сомнения про зеркально-симметричные треугольники. Так вот, зеркальное отражение подобно исходному треугольнику, и порядок обхода сторон для сравнения роли не играет.
    Ответ написан
    Комментировать