用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字
云代码 - python代码库

所有新手適合練手的代碼

2018-05-26 作者:云代码会员举报

[python]代码库

# -*- coding: utf-8 -*-

import tkinter
import sys, random, math

class Point(object):
	def __init__(self, x, y):
		self.x = x
		self.y = y

	def __str__(self):
		return "<Point>: (%f, %f)" % (self.x, self.y)

class Branch(object):
	def __init__(self, bottom, top, branches, level = 0):
		self.bottom = bottom
		self.top = top
		self.level = level
		self.branches = branches
		self.children = []

	def __str__(self):
		s = "Top: %s, Bottom: %s, Children Count: %d" % \
			(self.top, self.bottom, len(self.children))
		return s

	def nextGen(self, n = -1, rnd = 1):
		if n <= 0: n = self.branches
		if rnd == 1:
			n = random.randint(n / 2, n * 2)
			if n <= 0: n = 1
		dx = self.top.x - self.bottom.x
		dy = self.top.y - self.bottom.y
		r = 0.20 + random.random() * 0.2
		if self.top.x == self.bottom.x:
			# 如果是一条竖线
			x = self.top.x
			y = dy * r + self.bottom.y
		elif self.top.y == self.bottom.y:
			# 如果是一条横线
			x = dx * r + self.bottom.x
			y = self.top.y
		else:
			x = dx * r
			y = x * dy / dx
			x += self.bottom.x
			y += self.bottom.y
		oldTop = self.top
		self.top = Point(x, y)
		a = math.pi / (2 * n)
		for i in range(n):
			a2 = -a * (n - 1) / 2 + a * i - math.pi
			a2 *= 0.9 + random.random() * 0.2
			self.children.append(self.mkNewBranch(self.top, oldTop, a2))

	def mkNewBranch(self, bottom, top, a):
		dx1 = top.x - bottom.x
		dy1 = top.y - bottom.y
		r = 0.9 + random.random() * 0.2
		c = math.sqrt(dx1 ** 2 + dy1 ** 2) * r
		if dx1 == 0:
			a2 = math.pi / 2
		else:
			a2 = math.atan(dy1 / dx1)
			if (a2 < 0 and bottom.y > top.y) \
				or (a2 > 0 and bottom.y < top.y) \
				:
				a2 += math.pi
		b = a2 - a
		dx2 = c * math.cos(b)
		dy2 = c * math.sin(b)
		newTop = Point(dx2 + bottom.x, dy2 + bottom.y)
		return Branch(bottom, newTop, self.branches, self.level + 1)

class Tree(object):
	def __init__(self, root, canvas, bottom, top, branches = 3, depth = 3):
		self.root = root
		self.canvas = canvas
		self.bottom = bottom
		self.top = top
		self.branches = branches
		self.depth = depth
		self.new()

	def gen(self, n = 1):
		for i in range(n):
			self.getLeaves()
			for node in self.leaves:
				node.nextGen()
		self.show()

	def new(self):
		self.leavesCount = 0
		self.branch = Branch(self.bottom, self.top, self.branches)
		self.gen(self.depth)
		print ("leaves count: %d" % self.leavesCount)

	def chgDepth(self, d):
		self.depth += d
		if self.depth < 0: self.depth = 0
		if self.depth > 10: self.depth = 10
		self.new()

	def chgBranch(self, d):
		self.branches += d
		if self.branches < 1: self.branches = 1
		if self.branches > 10: self.branches = 10
		self.new()

	def getLeaves(self):
		self.leaves = []
		self.map(self.findLeaf)

	def findLeaf(self, node):
		if len(node.children) == 0:
			self.leaves.append(node)

	def show(self):
		for i in self.canvas.find_all():
			self.canvas.delete(i)
		self.map(self.drawNode)
		self.canvas.tag_raise("leaf")

	def exit(self, evt):
		sys.exit(0)

	def map(self, func = lambda node: node):
		# 遍历树
		children = [self.branch]
		while len(children) != 0:
			newChildren = []
			for node in children:
				func(node)
				newChildren.extend(node.children)
			children = newChildren

	def drawNode(self, node):
		self.line2(
#		self.canvas.create_line(
				node.bottom.x,
				node.bottom.y,
				node.top.x,
				node.top.y,
				fill = "#100",
				width = 1.5 ** (self.depth - node.level),
				tags = "branch level_%d" % node.level,
			)

		if len(node.children) == 0:
			# 画叶子
			self.leavesCount += 1
			self.canvas.create_oval(
					node.top.x - 3,
					node.top.y - 3,
					node.top.x + 3,
					node.top.y + 3,
					fill = "#090",
					tag = "leaf",
				)

		self.canvas.update()

	def line2(self, x0, y0, x1, y1, width = 1, fill = "#000", minDist = 10, tags = ""):
		dots = midDots(x0, y0, x1, y1, minDist)
		dots2 = []
		for i in range(len(dots) - 1):
			dots2.extend([dots[i].x,
				dots[i].y,
				dots[i + 1].x,
				dots[i + 1].y])
		self.canvas.create_line(
				dots2,
				fill = fill,
				width = width,
				smooth = True,
				tags = tags,
			)

def midDots(x0, y0, x1, y1, d):
	dots = []
	dx, dy, r = x1 - x0, y1 - y0, 0
	if dx != 0:
		r = float(dy) / dx
	c = math.sqrt(dx ** 2 + dy ** 2)
	n = int(c / d) + 1
	for i in range(n):
		if dx != 0:
			x = dx * i / n
			y = x * r
		else:
			x = dx
			y = dy * i / n
		if i > 0:
			x += d * (0.5 - random.random()) * 0.25
			y += d * (0.5 - random.random()) * 0.25
		x += x0
		y += y0
		dots.append(Point(x, y))
	dots.append(Point(x1, y1))
	return dots

if __name__ == "__main__":
	root = tkinter.Tk()
	root.title("Tree")
	gw, gh = 800, 600
	canvas = tkinter.Canvas(root,
			width = gw,
			height = gh,
		)
	canvas.pack()
	tree = Tree(root, canvas, Point(gw / 2, gh - 20), Point(gw / 2, gh * 0.2), \
		branches = 2, depth = 8)
	root.bind("n", lambda evt: tree.new())
	root.bind("=", lambda evt: tree.chgDepth(1))
	root.bind("+", lambda evt: tree.chgDepth(1))
	root.bind("-", lambda evt: tree.chgDepth(-1))
	root.bind("b", lambda evt: tree.chgBranch(1))
	root.bind("c", lambda evt: tree.chgBranch(-1))
	root.bind("q", tree.exit)
	root.mainloop()

[源代码打包下载]




分享到:
更多

网友评论    (发表评论)

共13 条评论 1/1页

发表评论:

评论须知:

  • 1、评论每次加2分,每天上限为30;
  • 2、请文明用语,共同创建干净的技术交流环境;
  • 3、若被发现提交非法信息,评论将会被删除,并且给予扣分处理,严重者给予封号处理;
  • 4、请勿发布广告信息或其他无关评论,否则将会删除评论并扣分,严重者给予封号处理。