Реализация карте


Я просто пытался сделать какой-то код для карты. На картах концепции можно найти здесь. В качестве упражнения я пытаюсь найти решение без прочтения статьи.

Затем, я наткнулся на этот код. Главная проблема заключается в том, что я пропустил алгоритм, мой код не так простой, элегантный, короткий и чистый. И я использовал ООП, потому что я не знаю, как это сделать без него (в университете я узнал, нет С, отсутствие функционального программирования, только ООП).

Другой вопрос, что я хотел сделать список прямоугольников вне зависимости от движка рендеринга (без библиотек matplotlib, может быть, я пишу что-то для OpenGL и pyqt), поэтому мне нужен прямоугольник с координатами нормированный от 0 до 1.

Это мой код, который я не горжусь: это слишком многословный, избыточный и не поцелуй, а может быть, это может быть немного более читаемым:

class Rectangle(object):

    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height

    def __repr__(self):
        return "Rect - x:{0}, y:{1}, width:{2}, height:{3}".format(self.x, self.y, self.width, self.height)

class Node(object):
    iter_method = iter
    size_method = int

    def __init__(self, content, depth=0):
        self.depth = depth
        self.childs = []
        try:
            self.value = Node.size_method(content)
        except TypeError:
            self.childs = [Node(x, depth+1) for x in Node.iter_method(content)]
            self.value = sum(child.value for child in self.childs)

    @property
    def leaf(self):
        return len(self.childs)>0

    def __repr__(self):
        s = "{0}Node:{1}".format('\t'*self.depth, self.value)
        if self.leaf:
            s += '\n'+'\n'.join(str(child) for child in self.childs)
        return s


class TreeMap(object):

    def __init__(self, root):
        self.root = root

        self.rects = []
        self.build(self.root, Rectangle(0,0,1,1))

    def build(self, node, rect, horizzontal=True):
        node.rect = rect
        self.rects.append( rect )

        sizes = [child.value for child in node.childs]
        total_size = node.value

        if horizzontal:
            x = 0.0
            for child in node.childs:
                y = rect.y
                w = (child.value*rect.width) / float(total_size)
                h = rect.height
                self.build(child, Rectangle(x,y,w,h), not horizzontal)
                x += w
        else:
            y = 0.0
            for child in node.childs:
                x = rect.x
                h = (child.value*rect.height) / float(total_size)
                w = rect.width
                self.build(child, Rectangle(x,y,w,h), not horizzontal)
                x += w

import unittest     

class Test_TreeMap(unittest.TestCase):

    def test_build_depth0(self):
        nodes = (2,1,(2,2))

        known = (1,     1), (2.0/7, 1), (1.0/7, 1), (4.0/7, 1), (4.0/7, 0.5), (4.0/7, 0.5)

        Node.iter_method = iter
        Node.size_method = int
        root = Node(nodes)

        t = TreeMap(root)
        widths = tuple((rect.width, rect.height) for rect in t.rects)
        self.assertEqual(known, widths)
unittest.main()


5599
5
задан 4 апреля 2011 в 06:04 Источник Поделиться
Комментарии
1 ответ

предст не должны использоваться в качестве общего довольно метод печати. Он должен дать краткое описание объекта, предпочтительно тот, который выглядит как код.

Его лучше использовать правильный английский в именах переменных, т. е. дети не дети.

А затем, объединив много строк, использовать StringIO

На Картах.способ сборки в основном связана с узлом. Оно должно быть действительно на класс Node. Только взаимодействие его с TreeMap-это прямоугольники. Но поскольку вы в любом случае хранить эти на объект, мы обеспечим отдельной итерации для тех, кто.

После того, как мы переехали строить в узле дерева не делал, поэтому мы с ним боремся.

Не похоже, чтобы быть действительно веская причина для узла, чтобы беспокоиться о собственной глубины.

Мне не нравится узел конструктор. Я не думаю, что конструктора должны быть связаны с преобразованием отдельных формат такой. Формат преобразования следует делать в другой функции. Поскольку iter_method и size_method только для этого преобразования, они должны быть аргументы есть

Сложность заключается в том узле.построить функцию. У вас есть две петли, которые выглядят почти так же. Мы можем объединить их, потянув биты логики, уникальные для каждого направления из.

Мои результаты:

from StringIO import StringIO

class Rectangle(object):

def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height

def __repr__(self):
return "Rectangle({0},{1},{2},{3})".format(
self.x, self.y, self.width, self.height)

def slice(self, horizontal, start, length):
if horizontal:
return Rectangle(self.x + start, self.y, length, self.height)
else:
return Rectangle(self.x, self.y + start, self.width, length)

class Node(object):

def __init__(self, children, value):
self.children = children
self.value = value

@classmethod
def from_nested_tuple(class_, data):
return class_.from_data(data, iter, int)

@classmethod
def from_data(class_, data, iter_method, size_method):
try:
iterable = iter_method(data)
except TypeError:
value = size_method(data)
return class_([], value)
else:
children = [ class_.from_data(item, iter_method, size_method)
for item in iterable]
return Node(children, sum(child.value for child in children))

def __repr__(self):
return "Node< {}, {} children>".format( self.value, len(self.children))

def _pretty_print(self, output, depth):
output.write('\t' * depth)
output.write('Node: {}'.format(self.value))
output.write('\n')
for child in self.children:
child.pretty_print(output, depth + 1)

def pretty_print(self):
output = StringIO()
self._pretty_print(output, 0)
return output.get_value()

def build(self, rect, horizontal=True):
self.rect = rect

sizes = [child.value for child in self.children]
total_size = self.value

if horizontal:
space = rect.width
else:
space = rect.height

position = 0.0
for child in self.children:
length = child.value * space
child.build( rect.slice(horizontal, position, length),
not horizontal)
position += length

def rectangles(self):
yield self.rect
for child in self.children:
for rect in child.rectangles():
yield rect

import unittest

class Test_TreeMap(unittest.TestCase):

def test_build_depth0(self):
nodes = (2,1,(2,2))

known = (1, 1), (2.0/7, 1), (1.0/7, 1), (4.0/7, 1), (4.0/7, 0.5), (4.0/7, 0.5)

Node.iter_method = iter
Node.size_method = int
root = Node.from_nested_tuple(nodes)
root.build( Rectangle(0,0,1,1) )

widths = tuple((rect.width, rect.height) for rect in root.rectangles())
self.assertEqual(known, widths)
unittest.main()

8
ответ дан 4 апреля 2011 в 08:04 Источник Поделиться