tree.py 1.52 KB
Newer Older
1
from dataclasses import dataclass
Eric Duminil's avatar
Eric Duminil committed
2
from collections import UserList
3
4
import kdtree

Eric Duminil's avatar
Eric Duminil committed
5

6
7
8
9
@dataclass
class Tree:
    x: float
    y: float
Eric Duminil's avatar
Eric Duminil committed
10
    diameter: float
11
12
    z: float = 0
    height: float = None
Eric Duminil's avatar
Eric Duminil committed
13
    trunk_diameter: float = None
14
    type: str = None
Eric Duminil's avatar
Eric Duminil committed
15
    description: str = '?'
Eric Duminil's avatar
Eric Duminil committed
16
    color: str = 'green'
17
18

    def __len__(self):
Eric Duminil's avatar
Eric Duminil committed
19
        return 2  # x & y
20
21
22
23

    def __getitem__(self, i):
        return [self.x, self.y][i]

Eric Duminil's avatar
Eric Duminil committed
24
25
26
27
    @property
    def radius(self):
        return self.diameter / 2

Eric Duminil's avatar
Eric Duminil committed
28
    def __str__(self):
Eric Duminil's avatar
Eric Duminil committed
29
        return f"{self.type} ({self.description}), {self.radius or '?'} m (X={self.x:.1f}, Y={self.y:.1f})"
Eric Duminil's avatar
Eric Duminil committed
30

31

Eric Duminil's avatar
Eric Duminil committed
32
class Forest(UserList):
33
34
35
36
37
38
    def __init__(self, existing_trees=[]):
        if existing_trees:
            self.kd_tree = kdtree.create(existing_trees, dimensions=2)
        else:
            self.kd_tree = kdtree.create([(0, 0)], dimensions=2)

Eric Duminil's avatar
Eric Duminil committed
39
        self.data = existing_trees
40

Eric Duminil's avatar
Eric Duminil committed
41
    def add_tree_if_possible(self, min_distance_2, x, y, **kparams):
Eric Duminil's avatar
Eric Duminil committed
42
43
44
        _nearest_tree, distance_2 = self.kd_tree.search_nn((x, y))
        if distance_2 > min_distance_2:
            self.kd_tree.add((x, y))
Eric Duminil's avatar
Eric Duminil committed
45
            self.append(Tree(x, y, **kparams))
Eric Duminil's avatar
Eric Duminil committed
46
47

    @property
Eric Duminil's avatar
Eric Duminil committed
48
49
50
    def xs_ys_cs(self):
        xs, ys, colors = [], [], []
        for tree in self:
Eric Duminil's avatar
Eric Duminil committed
51
52
            xs.append(tree.x)
            ys.append(tree.y)
Eric Duminil's avatar
Eric Duminil committed
53
54
            colors.append(tree.color)
        return xs, ys, colors
Eric Duminil's avatar
Eric Duminil committed
55

56
    def __str__(self):
Eric Duminil's avatar
Eric Duminil committed
57
        return f"Forest with {len(self)} trees."
58
59

    def __repr__(self):
Eric Duminil's avatar
Eric Duminil committed
60
        return "\n".join([str(self)] + [str(tree) for tree in self])