Как сравнить два вектора в vPython

Я пытаюсь смоделировать кубик Рубика. Чтобы определить, действительно ли пользователь решил куб, я хотел бы запомнить все векторы начального положения, а затем просто сравнить их.

Однако, когда вы запускаете мою программу и портите куб, а затем нажимаете «k», чтобы решить его, вы можете видеть в консоли, что значения на самом деле одинаковы, однако они имеют разную точность. Например, z-значение равно -0,99999 вместо -1. Результатом этой ошибки является то, что даже если значения совпадают, программа все равно не будет считать куб решенным. Я предполагаю, что при вращении, когда вычисления выполняются над вектором, точность меняется, и в результате в конце значения разные. Как я могу решить эту проблему? Чтобы распечатать векторы начального положения и текущие векторы, нажмите клавишу «a» в любое время :)

from visual import *
import string
import random

class Cube:
    def __init__(self):
        self.surfaces = { 'r': (color.red, (1, 0, 0)), 
                              'o': (color.orange, (-1, 0, 0)),
                              'y': (color.yellow, (0, 1, 0)), 
                              'b': (color.blue, (0, -1, 0)),
                              'w': (color.white, (0, 0, 1)), 
                              'g': (color.green, (0, 0, -1))} 
        self.fps = 30
        self.wholeSurfaces = []
        self.initialPosition = []
        self.commandsList = []

    def createCube(self):
         for colour, axis in self.surfaces.itervalues():
            for x in (-1, 0, 1):
                for y in (-1, 0, 1):

                    # Start with all powierzchniaBoczna on the top face, then rotate them "down"
                    # to the appropriate face.
                    powBoczna = box(color=colour, pos=(x, y, 1.5),
                                  length=0.98, height=0.98, width=0.05)

                    cos_kat = dot((0, 0, 1), axis)

                    if cos_kat == 0: #alfa = 90 + kPI
                        obliczonaOsObrotu = cross((0, 0, 1), axis) #iloczyn wektorowy
                    else: 
                        obliczonaOsObrotu=(1, 0, 0)

                    powBoczna.rotate(angle=acos(cos_kat), axis=obliczonaOsObrotu, origin=(0, 0, 0))
                    self.wholeSurfaces.append(powBoczna)

                    #remember initial position
                    v = (float(powBoczna.pos.x), float(powBoczna.pos.y), float(powBoczna.pos.z))
                    self.initialPosition.append(v)

    def solveCube(self):
        print self.commandsList

        self.commandsList.reverse()

        print self.commandsList
        for i in self.commandsList:
            self.rotateCube(self.reverseCommand(i), 10000)
        self.commandsList = []

    def reverseCommand(self, key):
        if (key.islower()): return key.upper()
        else: return key.lower()

    def rotateCube(self, key, refreshRate):
                colour, axis = self.surfaces[key.lower()]

                if (key.isupper()): kat = (pi / 2.0) 
                else: kat = -pi/2.0


                for r in arange(0, kat, kat / self.fps):
                    rate(refreshRate) 

                    for surface in self.wholeSurfaces:
                        if dot(surface.pos, axis) > 0.5: 
                            surface.rotate(angle=kat / self.fps, axis=axis, origin=(0, 0, 0))

    def beginLoop(self):       
        while True:
            key = scene.kb.getkey() 
            if (key.lower() in self.surfaces):
                self.commandsList.append(key)
                self.rotateCube(key, self.fps)
            elif key == "k":
                self.solveCube()
            elif key == "a":
                i = 0
                print "================="
                for surface in self.wholeSurfaces:
                        print "%s\n(%s,%s,%s)" % (self.initialPosition[i], surface.pos.x, surface.pos.y, surface.pos.z)
                        if self.initialPosition[i][0] == float(surface.pos.x) and self.initialPosition[i][1] == float(surface.pos.y) and self.initialPosition[i][2] == float(surface.pos.z): print "equal"
                        else: print "not equal"
                        print ""
                        i+=1

if __name__ == "__main__":
    myCube = Cube()
    myCube.createCube()
    myCube.beginLoop()

person Zwierzak    schedule 30.05.2015    source источник
comment
Взгляните на numpy.allclose.   -  person Ami Tavory    schedule 30.05.2015
comment
Спасибо! Проблема решена :) Я даже не знал о таком методе :)   -  person Zwierzak    schedule 30.05.2015


Ответы (1)


Решение простое, вам нужно использовать numpy.allclose метод с заданной точностью.

for surface in self.wholeSurfaces:
    print "%s\n%s" % (self.initialPosition[i], powierzchnia.pos)
    if np.allclose(self.initialPosition[i], surface.pos.astuple(), 1e-5, 1e-5): print "are equal"
    else: print "arent equal"
    i+=1
person Zwierzak    schedule 30.05.2015