1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
from guid import Guid
from partialdate import PartialDate
import const
# Constants
const._union_color = (0, 0, 0)
# Union class
class Union:
"Class to process union between two persons"
def __init__(self, dad, mum):
"Constructor, init dad, mum and childs"
self.id = Guid().newid()
self.dad = dad
dad.append_union(self)
self.mum = mum
mum.append_union(self)
self.uniondate = PartialDate()
self.childs = []
def append_child(self, child):
"Append a child born from the union"
self.childs.append(child)
child.parents = self
def tostring(self, level=1):
"Translate to a formatted string, tree is horizontal"
str = 'U{0}\n'.format(self.id)
for c in self.childs:
str += c.tostring(level+1) + '\n'
return str
def size_to_draw(self):
"Compute size to draw the union an its subtree"
totlen = 0
if self.childs == []:
return 3
for c in self.childs:
totlen = totlen + c.size_to_draw()
return max(3,totlen)
def compute_draw(self, x, y):
"Compute union subtree position"
# Compute childs size
size = 0
for c in self.childs:
size = size + c.size_to_draw()
# Compute origin
wmargin = const._person_width/const._person_wmargin_ratio
if len(self.childs) == 1:
x = x - (const._person_width)/2
else:
x = x - (size*const._person_width+(size-1)*wmargin)/2
# Draw each child
for c in self.childs:
# Draw the child
c.compute_draw(x, y)
size = c.size_to_draw()
x = x + (size*const._person_width+size*wmargin)
def draw(self, gc, pc, unionnumber):
"Draw person and its subtree in the graphical context"
# Draw link between parents
if self.dad.x0 < self.mum.x0:
(left, right) = (self.dad, self.mum)
if (unionnumber != 0):
left = left.unions[unionnumber-1].mum
else:
(left, right) = (self.mum, self.dad)
if (unionnumber != 0):
left = left.unions[unionnumber-1].dad
width = left.x1 - left.x0
height = left.y1 - left.y0
wmargin = width / const._person_wmargin_ratio
hmargin = height / const._person_hmargin_ratio
gc.move_to(left.x0+width, left.y0+(height/2))
gc.line_to(right.x0, right.y0+(height/2))
gc.set_source_rgb(*const._union_color)
gc.stroke()
# Draw each child
size = len(self.childs)
for c in self.childs:
# Draw the child
c.draw(gc, pc)
# Draw link to child
gc.move_to(right.x0-(wmargin/2), right.y0+(height/2))
gc.line_to(right.x0-(wmargin/2), right.y0+height+(hmargin/2))
if size == 1:
gc.line_to(right.x0-(wmargin/2), c.y0)
else:
gc.line_to(c.x0+(width/2), right.y0+height+(hmargin/2))
gc.line_to(c.x0+(width/2), c.y0)
gc.set_source_rgb(*const._union_color)
gc.stroke()
|