tree.py 1.54 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
    source: str = '?'
Eric Duminil's avatar
Eric Duminil committed
17
    color: str = 'green'
18
19

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

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

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

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

32

Eric Duminil's avatar
Eric Duminil committed
33
class Forest(UserList):
34
35
36
37
38
39
    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
40
        self.data = existing_trees
41

Eric Duminil's avatar
Eric Duminil committed
42
    def add_tree_if_possible(self, min_distance_2, x, y, **kparams):
Eric Duminil's avatar
Eric Duminil committed
43
44
45
        _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
46
            self.append(Tree(x, y, **kparams))
Eric Duminil's avatar
Eric Duminil committed
47
48

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

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

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