[从头学数学] 第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>
其实它那个扫描线算法并没有实现出来,里面很多东西还没理清楚。
本节到此结束,欲知后事如何,请看下回分解。
阿伟看到了一本比较有趣的书,是关于《计算几何》的,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>
其实它那个扫描线算法并没有实现出来,里面很多东西还没理清楚。
本节到此结束,欲知后事如何,请看下回分解。
相关文章推荐
- iOS 约束警告
- Spring事务配置
- hdu 5573 Binary Tree【思维+递推】
- linux(二)-command(vi)
- 提示ORA-03113:通信通道的文件结尾解决
- 省市区数据库以及后台工程(Java)前端三级联动 后台数据查询
- 【POJ】1142 - Smith Numbers(容斥原理)
- 283. Move Zeroes
- 真机调试出现错误提示:The certificate used to sign "项目名称" has either expired or has been revoked. An u
- connection pool. SQL State = HY000
- 神箭手-云爬虫开发平台
- 【转】C# winform 安装程序打包(自定义操作)
- 正则表达式 替换 <img > 标签
- 勉励自己
- [转] 产品知识分享:外部链接分享到微信的逻辑
- SQL数据类型解释
- 《大大李带你玩转XenServer 7 系列》 三、挂载ISO Library(ISO库)
- WebMagic 如何设置 cookie, 以及发送 post 请求
- Phoenix:Phoenix无法插值和读取Hbase
- Unity不同路径下的文件拷贝