NameError в python и matpotlib 3D-модели - PullRequest
0 голосов
/ 31 марта 2020

Вот вопрос для этой кодировки: мы смоделируем здание, в котором будет перемещаться Вонкаватор. Здание будет представлено трехмерной сеткой, где каждая координата в сетке представляет комнату. Вонкаватор может перемещаться из комнаты в комнату, перемещаясь максимум на 1 единицу в любом направлении. Например, он может перемещаться из точки (2, 3, 4) в точку (2, 4, 5), совершая движение (0, 1, 1). Однако нельзя делать переход от (1, 1, 1) к (3, 1, 1), так как мы можем двигаться максимум 1, а не 2, в любом направлении. Перемещение (0, 0, 0) (то есть оставаясь на месте) также недопустимо. Кроме того, недопустимо выходить за пределы сетки (то есть выходить из здания). Если Wonkavator находится в точке с координатами (5, 5, 4), а сетка имеет размер 6x6x6, то движение в направлении (1, 0, 0) недопустимо, так как это приведет к удалению Wonkavator из сетки. В предоставленном вам коде определены три класса: Person, Factory и Wonkavator: • Класс Person определяет человека внутри здания. В начале симуляции каждый человек будет находиться в одной конкретной координате (x, y, z) в сетке и захочет перейти к некоторой другой координате (x, y, z). Класс Person содержит четыре атрибута: имя человека, его текущую позицию в сетке (представленную как объект Point3D), его позицию назначения в сетке (представленную как объект Point3D) и, наконец, логическую переменную, указывающую, имеют ли они прибыл в пункт назначения еще. • Класс Wonkavator содержит методы для перемещения Wonkavator и ведения списка людей, находящихся в данный момент внутри. Вонкаватор должен перемещаться по координатам каждого человека (x, y, z), перемещаясь не более чем на 1 в любом измерении за раз (как описано выше). После подбора человека он должен доставить его по месту назначения (x, y, z) координат. (Примечание: Wonkavator не обязан доставлять человека сразу после его получения; он может забрать несколько человек, прежде чем доставить их всех по назначению.) Как только человек достигнет своего пункта назначения, он остается там до конца симуляция. Класс Wonkavator содержит три атрибута: его текущее положение в сетке (представленное как объект Point3D), размер фабрики (представленный как объект Point3D) и список людей, в настоящее время находящихся в Wonkavator. • Класс Factory содержит методы для запуска симуляции и отображения ее на экране. Он также содержит четыре атрибута: размер фабрики (объект Point3D), список людей в симуляции (т.е. список объектов Person), один объект типа Wonkavator для фактического лифта и, наконец, атрибут, относящийся к к визуализации Matplotlib.

Моя проблема - каждый раз, когда я запускаю программу, она всегда указывает на то, что в строке 159 есть NameError, что get_direction_vector не определено, однако я установил определение в строке 43. Кто-нибудь может взглянуть. Также, если есть какие-либо проблемы, пожалуйста, скажите мне.

import math
from random import randint
from mpl_toolkits import mplot3d
import matplotlib.pyplot as plt

plt.ion() # enable interactive mode (continue graphing without having to close the window)
plt.show() # show the plot

def sign(x):
    # Return the sign of x (0 if x is 0).
    if x > 0: # x positive
        return 1
    elif x < 0: # x negative
        return -1
    else: # x zero
        return 0

class Point3D():
    def __init__(self, x, y, z): # class constructor
        self.x = int(x)
        self.y = int(y)
        self.z = int(z)

    def __eq__(self, other): # comparison
        return self.x == other.x and self.y == other.y and self.z == other.z

    def __str__(self): # string representation
        return '<{}, {}, {}>'.format(self.x, self.y, self.z)

    def add(self, other): # add two points together
        return Point3D(self.x+other.x, self.y+other.y, self.z+other.z)

    def distance(self, other): # get distance between two points
        return math.sqrt((self.x - other.x) ** 2 + (self.y - other.y) ** 2 + (self.z - other.z) ** 2)

    def get_direction_vector(self, other):
        # Return a vecotr of 1, 0 or -1 in each dimension corresponding to
        # the direction you would have to move from the self point to get to the other point.
        return Point3D(sign(other.x-self.x), sign(other.y-self.y), sign(other.z-self.z))

    def aslist(self): # Return the Point2D object as a list of three numbers.
        return [self.x, self.y, self.z]

def get_random_point(x0, x1, y0, y1, z0, z1):
    # return a Point3D object with random coordinates within the given x,y,z intervals.
    return Point3D(randint(x0, x1), randint(y0, y1), randint(z0, z1))

class Person:
    def __init__(self, name, cur_pos, dst_pos):
        #comment the code
        self.name=name
        self.cur_pos=cur_pos
        self.dst_pos=dst_pos
        self.arrived=False

    def arrive_at_destination(self):
        self.cur_pos = self.dst_pos
        self.arrived = True

    def __str__(self): # string representation
        return "Name:" + self.name + "; cur: " + str(self.cur_pos) + "; dst:" + str(self.dst_pos)

class Factory:
    def __init__(self, factory_size, people, elevator): # class constructor
        self.factory_size = factory_size
        self.people = people
        self.elevator = elevator

        self.axes = plt.axes(projection='3d')

    def run(self):
        #comment for the coding
        for person in self.people:
            if not person.arrived and person.cur_pos == elevator.cur_pos and person not in self.elevator.people_in_elevator:
                self.elevator.people_enters(person)
            elif person.dst_pos == elevator.cur_pos and person in self.elevator.people_in_elevator:
                self.elevator.people_leaves(person)

        if not self.is_finished():
            self.elevator.move(self.people)

    def show(self): # display the grid
        self.axes.clear() # clear the previous window contents

        # set the axis bounds
        self.axes.set_xlim(0, factory_size.x)
        self.axes.set_ylim(0, factory_size.y)
        self.axes.set_zlim(0, factory_size.z)
        self.axes.set_xticks(list(range(factory_size.x+1)))
        self.axes.set_yticks(list(range(factory_size.y+1)))
        self.axes.set_zticks(list(range(factory_size.z+1)))

        # show a blue dot for each person not yet in the elevator / not yet arrived at their destination
        xs, ys, zs = [], [], []
        for person in self.people:
            if not person.arrived and person not in self.elevator.people_in_elevator:
                xs.append(person.cur_pos.x)
                ys.append(person.cur_pos.y)
                zs.append(person.cur_pos.z)
        self.axes.scatter3D(xs, ys, zs, color='blue')

        # show a red dot for the destinations of the people currently in the elevator
        edxs, edys, edzs = [], [], []
        for person in self.people:
            if person in self.elevator.people_in_elevator:
                edxs.append(person.dst_pos.x)
                edys.append(person.dst_pos.y)
                edzs.append(person.dst_pos.z)
        self.axes.scatter3D(edxs, edys, edzs, color='red')

        # show a green dot for the elevator itself
        self.axes.scatter3D([self.elevator.cur_pos.x], [self.elevator.cur_pos.y], [self.elevator.cur_pos.z], color='green')

        plt.draw()
        plt.pause(0.5)

    def is_finished(self):
        return all(person.arrived for person in self.people)

class Wonkavator:
    def __init__(self, factory_size): # class constructor
        self.cur_pos = Point3D(0, 0, 0)
        self.factory_size = factory_size
        self.people_in_elevator = [] # the list of people currently in the elevator

    def move(self, people): # move the elevator
        # get the direction in which to move      
        direction = self.choose_direction(people)

        # check if the direction is correct
        if any(not isinstance(d, int) for d in direction.aslist()):
            raise ValueError("Direction values must be integers.")
        if any(abs(d) > 1 for d in direction.aslist()):
            raise ValueError("Directions can only be 0 or 1 in any dimension.")
        if sum(direction.aslist()) == 0:
            raise ValueError("The elevator cannot stay still (direction is 0 in all dimensions).")
        if any(d < 0 or d > s for d, s in zip(self.cur_pos.add(direction).aslist(), self.factory_size.aslist())):
            raise ValueError("The elevator cannot move outside the bounds of the grid.")

        # move the elevator in the correct direction
        self.cur_pos = self.cur_pos.add(direction)

    def get_direction_vector(self, other):
        # Return a vecotr of 1, 0 or -1 in each dimension corresponding to
        # the direction you would have to move from the self point to get to the other point.
        return Point3D(sign(other.x-self.x), sign(other.y-self.y), sign(other.z-self.z))

    def choose_direction(self, people):
        #comment the code for the assignment
        for person in people:
            if not person.arrived and not person.cur_pos == elevator.cur_pos:
                return get_direction_vector(self.elevator.cur_pos,person.cur_pos)
            elif not person.arrived and not person.dst_pos == elevator.cur_pos:
                return get_direction_vector(self.elevator.cur_pos,person.dst_pos)
            else:
                continue
        return self.cur_pos

    def person_enters(self, person): # person arrives in elevator
        if person.arrived:
            raise Exception("A person can only enter the elevator if they have not yet reached their destination.")

        self.people_in_elevator.append(person) # add them to the list

    def person_leaves(self, person): # person departs elevator
        if person.dst_pos != elevator.cur_pos:
            raise Exception("A person can only leave the elevator if the elevator has reached their destination point.")

        person.arrive_at_destination() # let the person know they have arrived
        self.people_in_elevator.remove(person) # remove them from the list

if __name__ == '__main__':    
    factory_size = Point3D(5, 5, 5)

    # create the people objects
    people = []
    for name in ["Candice", "Arnav", "Belle", "Cecily", "Faizah", "Nabila", "Tariq", "Benn"]:
        cur = get_random_point(0, factory_size.x-1, 0, factory_size.y-1, 0, factory_size.z-1)
        dst = get_random_point(0, factory_size.x-1, 0, factory_size.y-1, 0, factory_size.z-1)
        people.append(Person(name, cur, dst))

    # create the elevator
    elevator = Wonkavator(factory_size)

    # create the factory
    factory = Factory(factory_size, people, elevator)

    while True:
        factory.run()
        factory.show()

        # check if everyone has arrived at their destinations
        if all(person.arrived for person in people):
            break

    print("Everyone has arrived.")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...