1. Пользоваться форумом на планшетах и телефонах стало удобнее благодаря Tapatalk

Нужна помошь знатоков по векторным операциям

Тема в разделе "Maya", создана пользователем Andots, 19 авг 2016.

Модераторы: Dark™, Skif
  1. Andots

    Andots Знаток

    С нами с:
    12.03.2009
    Сообщения:
    543
    Симпатии:
    97
    Баллы:
    31
    Доброго дня. Нужна подсказка, если конечно знает кто.

    есть 3 точки с известными координатами.

    нужно математически найти на виртуальной прямой между точками p1 и p2 ближайшую точку от p3
    vec.jpg
    Интерполяцию (int) между p1 и p2 я сделал и могу получить координаты всех точек в зависимости от дистанции (trans) на этой прямой.
    p1 = (x,y,z)
    p2 = (x,y,z)
    p3 = (x,y,z)
    trans = any

    v1, v2 = om.MVector(p1), om.MVector(p2)

    ds = v2 - v1
    dist = om.MVector(v2-v1).length()
    int = v1+(trans/dist*ds)

    честно говоря векторную алгебру уже не помню и поиск по гуглу мало что дал. Но мало ли, мож кто из APIшников сюда заглядывает и подскажет что.

    PS. Глупости вроде "Есть же констрейн closestpoint" не предлагать. Нужен математический способ.
     
    Последнее редактирование: 19 авг 2016
  2. Lemieux

    Lemieux Знаток

    С нами с:
    08.06.2011
    Сообщения:
    810
    Симпатии:
    74
    Баллы:
    32
    А через высоту треугольника нельзя найти?
     
    Andots нравится это.
  3. Andots

    Andots Знаток

    С нами с:
    12.03.2009
    Сообщения:
    543
    Симпатии:
    97
    Баллы:
    31
    Да фиг его знает, в двухмерном пространстве на листке бумаги я бы нашел.. Но 3х мерное немного мозги закручивает, никак не могу сообразить. Как это все векторами выразить, что то крутиться в голове но не могу зацепиться. Не надо мне было с девками в ботаническом саду бухать когда нам в универе векторную алгебру преподавали. Эхх ))))

    Вообще наверно кое что можно сделать.. Получить длины всех ребер треугольныка. 1 угол я знаю он 90 град т.е квадрат гипотенузы равен сумме квадратов катетов.. гипотенузу тоже знаю... Блин, а вот катеты не знаю)) хотя знаю 2 гипотенузы и 1 катет общий..Достаточно найти длину любого катета и через интерполяцию получу коорд точки. Мда общий катет это высота треугольника. Жесть, здравствуй школа.
     
    Последнее редактирование: 19 авг 2016
  4. Lemieux

    Lemieux Знаток

    С нами с:
    08.06.2011
    Сообщения:
    810
    Симпатии:
    74
    Баллы:
    32
    Углы тут нужны только для частных случаев. А так, у тебя же известны координаты точек, можно посчитать для сторон треугольника, дальше высоту, а потом и вычислить точку.
     
  5. Andots

    Andots Знаток

    С нами с:
    12.03.2009
    Сообщения:
    543
    Симпатии:
    97
    Баллы:
    31
    Так и делаю. Формулу то прописал вот впихиваю ее в ноду на питонской API .. Тот еще кровопийца, то одно not defined то другое ему не нравиться. ((( Мозги уже кипеть начинают
     
  6. Dark™ vip

    Dark™ Administrator Команда форума

    С нами с:
    28.10.2001
    Сообщения:
    3.110
    Симпатии:
    217
    Баллы:
    1.520
    Вектор к ближайшей точке будет равен P1 + (P3-P1)*(P2-P1)/|(P2-P1)|^2*(P2-P1). Думаю, дальше сами разберетесь.
     
    Последнее редактирование: 19 авг 2016
    Andots нравится это.
  7. Andots

    Andots Знаток

    С нами с:
    12.03.2009
    Сообщения:
    543
    Симпатии:
    97
    Баллы:
    31
    Ооо спасибки большое, я правильно понял |(P2-P1)| это дистаниция? То что у меня om.MVector(v2-v1).length()
     
  8. 4i4ikov

    4i4ikov Знаток

    С нами с:
    07.04.2015
    Сообщения:
    170
    Симпатии:
    50
    Баллы:
    23
    Без векторов решил, не выкидывать же теперь))

    Есть треугольник со сторонами a,b,c
    c - расстояние между P1 и P2, на "с" лежит искомая точка
    (a,b,c находятся стандартно по формуле расстояния между точками в трехм. прос-ве)

    Находим отрезки x и у, которые делят "с" на две части:
    Решаем систему уравнений
    x+y = c
    a*a-x*x=b*b-y*y

    Так как вольфрам альфа сейчас у меня в дауне, решаю на sympy:
    from sympy import *
    x,y = symbols('x,y')
    a,b,c = symbols('a,b,c')
    print solve([a*a-x*x-b*b+y*y, x+y-c],[x, y])

    sympy говорит:
    x = (a**2 - b**2 + c**2)/(2*c)
    y = (-a**2 + b**2 + c**2)/(2*c)

    коэффициент интерполяции между P1 и P2:
    k = x/c
    (у не нужен)

    получаем точку:
    X = (x2*k+x1*(1-k))
    Y = (y2*k+y1*(1-k))
    Z = (z2*k+z1*(1-k))
     
    Последнее редактирование: 19 авг 2016
    Andots нравится это.
  9. Dark™ vip

    Dark™ Administrator Команда форума

    С нами с:
    28.10.2001
    Сообщения:
    3.110
    Симпатии:
    217
    Баллы:
    1.520
    Да
     
  10. Andots

    Andots Знаток

    С нами с:
    12.03.2009
    Сообщения:
    543
    Симпатии:
    97
    Баллы:
    31
    Спасибо вам всем огромное за ответы. Я немного по другому сделал, но правда верность метода пока не проверял (сил уже нет )). Проверю завтра если не работает, возьму ваши способы. Формула
    Dark™ больше всего приглянулась, все так нода будет, а там чем меньше телодвижений тем лучше.

    v1, v2, v3 = Om.MVector(p1), Om.MVector(p2), Om.MVector(p3)



    dist1 = Om.MVector(v2-v1).length()
    dist2 = Om.MVector(v3-v2).length()
    dist3 = Om.MVector(v3-v1).length()

    p=(dist1+dist2+dist3)/2

    he = 2/(dist1 * math.sqrt(p*(p-dist1)*(p-dist2)*(p-dist3)))


    trx = math.sqrt(dist3 - he)

    Clvvect = v1+(trx/dist1*ds)
     
  11. 4i4ikov

    4i4ikov Знаток

    С нами с:
    07.04.2015
    Сообщения:
    170
    Симпатии:
    50
    Баллы:
    23
    Andots, потом, когда у вас заработает, напишите координаты каких нибудь 4-х точек для проверки (три исходные и найденную), я проверю свою писанину.
     
  12. Andots

    Andots Знаток

    С нами с:
    12.03.2009
    Сообщения:
    543
    Симпатии:
    97
    Баллы:
    31
    Да без проблем. Моя формула правда не совсем корректно заработала ,где то ребра перепутал, поэтому я не сильно мучаясь совестью взял формулу Dark .

    Вот с принтов в некий момент времени, (p1 , p2) вектор на котором ищем.
    p1 (5.111 , -2.046, -1.956)

    p2 (-5.419 , -0.070 , -1.225)

    p3 ( -0.246 , 0 , -6.764)

    (искомая)intp = (-0.088 , -1,071, -1.595 )

    Или с видео с атрибутов можно скатать в разных моментах. Как удобней вам

     
    Последнее редактирование: 20 авг 2016
  13. Lemieux

    Lemieux Знаток

    С нами с:
    08.06.2011
    Сообщения:
    810
    Симпатии:
    74
    Баллы:
    32
    А зачем это всё? :)
     
  14. Andots

    Andots Знаток

    С нами с:
    12.03.2009
    Сообщения:
    543
    Симпатии:
    97
    Баллы:
    31
    Ну в данном виде конечно особо незачем. Это всего лишь малая составная часть. Есть просто у меня одна задумка, но для ее реализации мне нужно понимать саму суть подобных операций и уметь это использовать в нодах или в простых скриптах. Делать это все стд средствами майки очень неудобно и тяжко в моем случае.

    Ну а если даже у меня ничего путного не получится в итоге, то как минимум + к шансу не страдать от маразма в старости.
     
    Последнее редактирование: 20 авг 2016
    Бабуинище нравится это.
  15. 4i4ikov

    4i4ikov Знаток

    С нами с:
    07.04.2015
    Сообщения:
    170
    Симпатии:
    50
    Баллы:
    23
    Нормалёк, моя тоже работает:
    Код:
    import maya.OpenMaya as Om
    
    def vectorTest(v1,v2,v3):
         a = Om.MVector(v1-v3).length()
         b = Om.MVector(v2-v3).length()
         c = Om.MVector(v2-v1).length()
         if c:
             x = (a*a - b*b + c*c)/(2*c)
             k = x/c
             v = v2*k+v1*(1-k)
         else:
             v=v1
         return v
    
    v1 = Om.MVector(5.111 , -2.046, -1.956) 
    v2 = Om.MVector(-5.419 , -0.070 , -1.225)
    v3 = Om.MVector( -0.246 , 0 , -6.764)
    v = vectorTest(v1,v2,v3)
    print v.x,v.y,v.z
    
    Код:
    -0.0880312190608 -1.07037932679 -1.59507959913
    
    Померить бы скорости.
     
  16. Andots

    Andots Знаток

    С нами с:
    12.03.2009
    Сообщения:
    543
    Симпатии:
    97
    Баллы:
    31
    Да, в принципе замерить было бы интересно.
    Вот что у меня. Но вектора с апи 2.0

    import maya.api.OpenMaya as Om

    def vectorTest(p1,p2,p3):

    v1, v2, v3 = Om.MVector(p1), Om.MVector(p2), Om.MVector(p3)
    dist1 = Om.MVector(v2-v1).length()
    p4 = v1 + (v3-v1)*(v2-v1)/dist1**2*(v2-v1)
    return p4
     
    Последнее редактирование: 20 авг 2016
  17. 4i4ikov

    4i4ikov Знаток

    С нами с:
    07.04.2015
    Сообщения:
    170
    Симпатии:
    50
    Баллы:
    23
    Вектора почти в два раза быстрее.

    Замерялка:
    Код:
    import maya.api.OpenMaya as Om
    
    def vectorTest_4i4ikov(v1,v2,v3):
        a = Om.MVector(v1-v3).length()
        b = Om.MVector(v2-v3).length()
        c = Om.MVector(v2-v1).length()
        k = (a*a - b*b)/(2*c*c) + 0.5
        return v2*k+v1*(1-k)
    
    def vectorTest_Dark(v1,v2,v3):
        v21 = v2-v1
        d = Om.MVector(v21).length()
        return v1+(v3-v1)*v21*v21/(d*d)
    
    import time
    class new_Bench:
        mera = time.time
        #mera = time.clock
        def __init__(self):
            self.time=self.mera()
        def reset(self):
            self.__init__()
        def get(self):
            self.time = self.mera() - self.time
            return self.time
    
    v1 = Om.MVector(5.111 , -2.046, -1.956)
    v2 = Om.MVector(-5.419 , -0.070 , -1.225)
    v3 = Om.MVector( -0.246 , 0 , -6.764)
    print '\n','-'*20,'check'
    print 'Dark    (vector):',vectorTest_Dark(v1,v2,v3)
    print '4i4ikov (scalar):',vectorTest_4i4ikov(v1,v2,v3)
    
    Bench = new_Bench()
    N = 100000
    print '\n','-'*20,'bench',N
    
    Bench.reset()
    for i in xrange(1,N): vectorTest_Dark(v1/i,v2/i,v3/i)
    print 'Dark    (vector):',Bench.get()
    
    Bench.reset()
    for i in xrange(1,N): vectorTest_4i4ikov(v1/i,v2/i,v3/i)
    print '4i4ikov (scalar):',Bench.get()
    
    Bench.reset()
    for i in xrange(1,N): vectorTest_Dark(v1/i,v2/i,v3/i)
    print 'Dark    (vector):',Bench.get()
    
    Bench.reset()
    for i in xrange(1,N): vectorTest_4i4ikov(v1/i,v2/i,v3/i)
    print '4i4ikov (scalar):',Bench.get()
    
    Код:
    -------------------- check
    Dark    (vector): (-0.0880312, -1.07038, -1.59508)
    4i4ikov (scalar): (-0.0880312, -1.07038, -1.59508)
    
    -------------------- bench 100000
    Dark    (vector): 0.391000032425
    4i4ikov (scalar): 0.766000032425
    Dark    (vector): 0.390000104904
    4i4ikov (scalar): 0.734000205994
    
    Формулы оптимизировал.
    Если v1 и v2 совпадут, то там и там будет ошибка деления на ноль.

    API 2.0 просто няшка!
     
    Последнее редактирование: 21 авг 2016
    Andots нравится это.
  18. Andots

    Andots Знаток

    С нами с:
    12.03.2009
    Сообщения:
    543
    Симпатии:
    97
    Баллы:
    31
    Прикольно, честно говоря не думал что разница будет почти в 2 раза. Интересно было бы сравнить ноду на питонской Апи с абсолютно аналогичной скомпиленой на с++
     
  19. 4i4ikov

    4i4ikov Знаток

    С нами с:
    07.04.2015
    Сообщения:
    170
    Симпатии:
    50
    Баллы:
    23
    Тоже не думал что такая сильная разница будет.

    Мне вот интересно по железу, как на разных машинах будет.
    Вот две машинки, на i7 и c2d.
    До этого был замер на c2d E5700 @ 3750 MHz (maya 2013x32)

    Вот замер на i7 2600k @ 4500 MHz (maya 2014x64):
    Код:
    -------------------- check
    Dark    (vector): (-0.0880312, -1.07038, -1.59508)
    4i4ikov (scalar): (-0.0880312, -1.07038, -1.59508)
    
    -------------------- bench 100000
    Dark    (vector): 0.254999876022
    4i4ikov (scalar): 0.486999988556
    Dark    (vector): 0.24599981308
    4i4ikov (scalar): 0.487999916077
    
    Быстрее ровно в 1.5 раза (между машинами).
    Это одно ядро считает, ну и разрядность разная.
    Но всё равно не сильно быстрее.

    А по рендеру одна быстрее другой в 4.4 раза (все ядра работают).
     
  20. Andots

    Andots Знаток

    С нами с:
    12.03.2009
    Сообщения:
    543
    Симпатии:
    97
    Баллы:
    31
    Не повезло, у меня тоже 2600к. Стоит правда без буста (чтоб ноги просто так не грел :) )

    3.4 гц
    -------------------- bench 100000
    Dark (vector): 0.375
    4i4ikov (scalar): 0.707000017166
    Dark (vector): 0.358999967575
    4i4ikov (scalar): 0.68799996376
     
    4i4ikov нравится это.
Модераторы: Dark™, Skif

Поделиться этой страницей