您的位置:首页 > 其它

[从头学数学] 第242节 线段求交 专题图叠合

2016-07-22 17:55 337 查看
剧情提要:
阿伟看到了一本比较有趣的书,是关于《计算几何》的,2008年由北清派出版。很好奇
它里面讲了些什么,就来看看啦。

正剧开始:

星历2016年07月22日 17:57:38, 银河系厄尔斯星球中华帝国江南行省。

[工程师阿伟]正在和[机器小伟]一起研究[计算几何]]。





<span style="font-size:18px;">###
# @usage 数据结构汇总,不断增加中
# @author mw
# @date 2016年07月11日 星期一 10:06:56
# @param
# @return
#
###

#栈
class Stack:
def __init__(self, size = 16):
self.stack = []
self.size = size
self.top = -1

def setSize(self, size):
self.size = size

def isEmpty(self):
if self.top == -1:
return True
else:
return False

def isFull(self):
if self.top + 1 == self.size:
return True
else:
return False

def top(self):
if self.isEmpty():
raise Exception("StackIsEmpty")
else:
return self.stack[self.top]

def push(self,obj):
if self.isFull():
raise Exception("StackOverFlow")
#self.setSize(self.size*=2);
else:
self.stack.append(obj)
self.top +=1

def pop(self):
if self.isEmpty():
raise Exception("StackIsEmpty")
else:
self.top -= 1
return self.stack.pop()

def show(self):
print(self.stack)

def test(self):
s = Stack(5)
s.push(1)
s.push(2)
s.push(3)
s.push(4)
s.push(5)
s.show()
s.pop()
s.show()
s.push(6)
s.show()

#队列
class Queue:
def __init__(self,size = 16):
self.queue = []
self.size = size
self.front = 0
self.rear = 0

def setSize(self, size):
self.size = size

def isEmpty(self):
return self.rear == 0

def isFull(self):
if (self.front - self.rear +1) == self.size:
return True
else:
return False

def first(self):
if self.isEmpty():
raise Exception("QueueIsEmpty")
else:
return self.queue[self.front]

def last(self):
if self.isEmpty():
raise Exception("QueueIsEmpty")
else:
return self.queue[self.rear]

def add(self,obj):
if self.isFull():
raise Exception("QueueOverFlow")
else:
self.queue.append(obj)
self.rear += 1

def delete(self):
if self.isEmpty():
raise Exception("QueueIsEmpty")
else:
self.rear -=1
return self.queue.pop(0)

def show(self):
print(self.queue)

def test(self):
q = Queue(3)
q.add(1)
q.add(2)
q.show()
q.delete()
q.show()

#二叉树,要用到Queue()
class BinaryTreeNode:
def __init__(self,data,left,right):
self.left = left
self.data = data
self.right = right

class BinaryTree:
def __init__(self):
self.root = None

def makeTree(self,data,left,right):
self.root = BinaryTreeNode(data,left,right) #left.root = right.root = None

def isEmpty(self):
if self.root is None:
return True
else:
return False

def preOrder(self,r):
if r.root is not None:
print(r.root.data)
if r.root.left is not None:
self.preOrder(r.root.left)
if r.root.right is not None:
self.preOrder(r.root.right)

def inOrder(self,r):
if r.root is not None:
if r.root.left is not None:
self.inOrder(r.root.left)
print(r.root.data)
if r.root.right is not None:
self.inOrder(r.root.right)

def postOrder(self,r):
if r.root is not None:
if r.root.left is not None:
self.preOrder(r.root.left)
if r.root.right is not None:
self.preOrder(r.root.right)
print(r.root.data)

#这里用到Queue()
def levelOrder(self,a):
q = Queue()
r = a
while r is not None:
print(r.root.data)
if r.root.left is not None:
q.add(r.root.left)
if r.root.right is not None:
q.add(r.root.right)

if q.isEmpty():
print("empty")
r = None
else:
r = q.delete()

def test(self):
r = BinaryTree()
ra = BinaryTree()
ra.makeTree(2,None,None)
rb = BinaryTree()
rb.makeTree(3,None,None)
r.makeTree(1,ra,rb)
print("前序遍历")
r.preOrder(r)
print("中序遍历")
r.inOrder(r)
print("后序遍历")
r.postOrder(r)
print("层级遍历")
r.levelOrder(r)

#从前序,中序,生成后序
def findTree(self, preList,inList,postList):
if len(preList)==0:
return
if len(preList)==1:
postList.append(preList[0])
return
root=preList[0]
n = inList.index(root)
self.findTree(preList[1:n+1],inList[:n],postList)
self.findTree(preList[n+1:],inList[n+1:],postList)
postList.append(root)

#已知前序遍历结果和中序遍历结果,求后序遍历
def test2(self):
preList=list('DBACEGF')
midList=list('ABCDEFG')
afterList=[]

self.findTree(preList,midList,afterList)
print(afterList)

#有序数组转为平衡二叉树的递归算法
def sortedArrayToBST(self, array, start = 0, end = 0):
if (start > end):
return None;
else:
mid = math.floor((start + end)/2);
root = BinaryTree();
root.makeTree(array[mid],
self.sortedArrayToBST(array, start, mid-1),
self.sortedArrayToBST(array,mid+1, end));
return root;

def test3(self):
a = list(range(1, 10));
len_ = len(a);
r = self.sortedArrayToBST(a, 0, len_-1);
print("层级遍历")
r.levelOrder(r)

#递归的查找遍历
def search(self, root, data):
if (root == None):
return None;

if (root.data == data):
return root.data;
elif (self.less(data, root.data)):
return self.search(root.left, data);
else:
return self.search(root.right, data);

#定义一种小于的规则
def less(self, data1, data2):
#某个应用例程data是[x, y]点对,先按y, 再按x的顺序由小到大排序
if (data1[1] < data2[1]) or (data1[1] == data2[1] and data1[0] < data2[0]):
return True;
else:
return False;

#左旋
def leftRotate(self, root):
tmp = root.right;
root.right = root.left;
root.left = root.data;
root.data = tmp;

#右旋
def rightRotate(self, root):
tmp = root.left;
root.left = root.right;
root.right = root.data;
root.data = tmp;

#
#线段的交点集求解
#
class LineSegIntersection():
#点集模式[P1, P2, ...]
#边集模式[E1, E2, ...]

#列表的二分查找
def binSearch(self, lis, ele, mode = 'P'):
low, high = 0, len(lis)-1;

while (low <= high):
mid = math.floor((low + high)/2);
midval = lis[mid];

if (mode == 'P'):
if (self.less(midval, ele)):
low = mid + 1;
elif (self.less(ele, midval)):
high = mid - 1;
else:
return mid;
elif (mode == 'E'):
if (self.less(midval, ele, 'E')):
low = mid + 1;
elif (self.less(ele, midval, 'E')):
high = mid - 1;
else:
return mid;
return -1;

#列表的二分插入
def binInsert(self, lis, ele, mode = 'P'):
low, high = 0, len(lis)-1;

pos = 0;
while (low <= high):
mid = math.floor((low + high)/2);
midval = lis[mid];

if (mode == 'P'):
if (self.less(midval, ele)):
low = mid + 1;
elif (self.less(ele, midval)):
high = mid - 1;
else:
return lis;
elif (mode == 'E'):
if (self.less(midval, ele, 'E')):
low = mid + 1;
elif (self.less(ele, midval, 'E')):
high = mid - 1;
else:
return lis;

mid = math.floor((low + high)/2);
pos = min(low, mid, high);
lis = lis[0:pos+1]+[ele]+lis[pos+1:];
return lis;

#按先y,后x由小到大的序列排列点坐标阵列
def sortPoint(self, vertex):
return sorted(vertex, key = lambda P:(P[1], P[0]));

#输入的是边集合[edge1, edge2, ...]
#edge为[P1, P2]
def sortEdge(self, edge):
for i in range(len(edge)):
edge[i] = self.sortPoint(edge[i]);

return sorted(edge, key = lambda E:(E[0][1], E[0][0]));

#根据不同的小于(<)规则编写
def less(self, data1, data2, mode = 'P'):
if (mode == 'P'): #点
#判断两个点[x,y],先y后x
if data1[1] == data2[1]:
return data1[0] < data2[0];
else:
return data1[1] < data2[1];
elif (mode == 'E'): #边
if data1[0][1] == data2[0][1]:
return data1[0][0] < data2[0][0];
else:
return data1[0][1] < data2[0][1];

#点P在有向线段Vec的左侧还是右侧
def side_P_Vec(self, Point, Vec):
Q, R = Vec[0], Vec[1];
P_x, P_y = Point[0], Point[1];
deter = np.array([[1, Q[0], Q[1]],
[1, R[0], R[1]],
[1, P_x, P_y]]);

det = np.linalg.det(deter);

#det < 0 右侧
#det = 0 点在直线上
#det > 0 左侧

return det;

#去除重复点
def removeDup(self, vertices):
v_new = [];
len_1 = len(vertices);
len_2 = 0;

for i in range(len_1):
len_2 = len(v_new);
if (len_2 < 1):
v_new.append(vertices[i]);
else:
for j in range(len_2):
if v_new[j] == vertices[i]:
break;
if (j >= len_2-1):
v_new.append(vertices[i]);

return v_new;

#两条线段求交点
def cross_2Seg(self, seg1, seg2):
cp = geo.crossPointOfTwoLine(seg1, seg2);
if (geo.pointInSeg(cp, seg1) and geo.pointInSeg(cp, seg2)):
return cp;
else:
return [];

#点是线段的上端点
def U_p_set(self, Point, segSet):
set_ = [];
for i in range(len(segSet)):
if segSet[i][0] == Point:
set_.append(segSet[i]);

return set_;

#点是线段的下端点
def L_p_set(self, Point, segSet):
set_ = [];
for i in range(len(segSet)):
if segSet[i][1] == Point:
set_.append(segSet[i]);

return set_;

#点在y轴的投影是处于线段在y轴投影上的
def C_p_set(self, Point, segSet):
set_ = [];
for i in range(len(segSet)):
P1, P2 = segSet[i][0], segSet[i][1];
if P1[1] < Point[1] and Point[1] < P2[1]:
set_.append(segSet[i]);

return set_;

#用二重循环法求交点
def findInterPoint(self, edges):
len_ = len(edges);
interP = [];

for i in range(len_):
for j in range(i+1, len_):
#传入的edges是用扫描线法排过序的,即先y后x顺序由小到大排列,
#可以减少一些判断
P1, P2 = edges[i][0], edges[i][1];
P3, P4 = edges[j][0], edges[j][1];

if (P1 == P3) and (P2 == P4):
interP.append(P1);
interP.append(P2);
elif (P1[1] > P4[1]) or (P3[1] > P2[1]):
continue;
else:
a = self.cross_2Seg(edges[i], edges[j]);
if (a != []):
interP.append(a);
return interP;

def tmp():
calc = Convex();
shape = geo.Shape();
line = LineSegIntersection();

#计时开始
startTime = time.clock();

verts = shape.nStar(0, 0, 100, 7);
verts = calc.roundVector(verts);

verts = line.sortPoint(verts);
print(verts);

edges = [[[13.363, -27.748], [0.0, -100.0]], [[-13.363, -27.748], [-78.183, -62.349]],
[[-30.026, -6.853], [-97.493, 22.252]], [[-24.079, 19.202], [-43.388, 90.097]],
[[-0.0, 30.798], [43.388, 90.097]], [[97.493, 22.252], [30.026, -6.853]],
[[78.183, -62.349], [24.079, 19.202]]]

edges = line.sortEdge(edges);
print(edges);

interP = line.findInterPoint(edges);
interP = calc.roundVector(interP);

print(interP);
</span>



其实它那个扫描线算法并没有实现出来,里面很多东西还没理清楚。

本节到此结束,欲知后事如何,请看下回分解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: