- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在实现 Voronoi 分割,然后进行平滑处理。为了平滑,我打算做 Lloyd 松弛,但我遇到了一个问题。
我正在使用以下模块计算 Voronoi 面:
https://bitbucket.org/mozman/geoalg/src/5bbd46fa2270/geoalg/voronoi.py
为了进行平滑处理,我需要知道每个多边形的边,以便计算中心,不幸的是,这段代码没有提供。
我有权访问的信息包括:
谁能找到一种相对简单的计算方法?
最佳答案
要找到质心,您可以使用 the formula described on wikipedia :
import math
def area_for_polygon(polygon):
result = 0
imax = len(polygon) - 1
for i in range(0,imax):
result += (polygon[i]['x'] * polygon[i+1]['y']) - (polygon[i+1]['x'] * polygon[i]['y'])
result += (polygon[imax]['x'] * polygon[0]['y']) - (polygon[0]['x'] * polygon[imax]['y'])
return result / 2.
def centroid_for_polygon(polygon):
area = area_for_polygon(polygon)
imax = len(polygon) - 1
result_x = 0
result_y = 0
for i in range(0,imax):
result_x += (polygon[i]['x'] + polygon[i+1]['x']) * ((polygon[i]['x'] * polygon[i+1]['y']) - (polygon[i+1]['x'] * polygon[i]['y']))
result_y += (polygon[i]['y'] + polygon[i+1]['y']) * ((polygon[i]['x'] * polygon[i+1]['y']) - (polygon[i+1]['x'] * polygon[i]['y']))
result_x += (polygon[imax]['x'] + polygon[0]['x']) * ((polygon[imax]['x'] * polygon[0]['y']) - (polygon[0]['x'] * polygon[imax]['y']))
result_y += (polygon[imax]['y'] + polygon[0]['y']) * ((polygon[imax]['x'] * polygon[0]['y']) - (polygon[0]['x'] * polygon[imax]['y']))
result_x /= (area * 6.0)
result_y /= (area * 6.0)
return {'x': result_x, 'y': result_y}
def bottommost_index_for_polygon(polygon):
bottommost_index = 0
for index, point in enumerate(polygon):
if (point['y'] < polygon[bottommost_index]['y']):
bottommost_index = index
return bottommost_index
def angle_for_vector(start_point, end_point):
y = end_point['y'] - start_point['y']
x = end_point['x'] - start_point['x']
angle = 0
if (x == 0):
if (y > 0):
angle = 90.0
else:
angle = 270.0
elif (y == 0):
if (x > 0):
angle = 0.0
else:
angle = 180.0
else:
angle = math.degrees(math.atan((y+0.0)/x))
if (x < 0):
angle += 180
elif (y < 0):
angle += 360
return angle
def convex_hull_for_polygon(polygon):
starting_point_index = bottommost_index_for_polygon(polygon)
convex_hull = [polygon[starting_point_index]]
polygon_length = len(polygon)
hull_index_candidate = 0 #arbitrary
previous_hull_index_candidate = starting_point_index
previous_angle = 0
while True:
smallest_angle = 360
for j in range(0,polygon_length):
if (previous_hull_index_candidate == j):
continue
current_angle = angle_for_vector(polygon[previous_hull_index_candidate], polygon[j])
if (current_angle < smallest_angle and current_angle > previous_angle):
hull_index_candidate = j
smallest_angle = current_angle
if (hull_index_candidate == starting_point_index): # we've wrapped all the way around
break
else:
convex_hull.append(polygon[hull_index_candidate])
previous_angle = smallest_angle
previous_hull_index_candidate = hull_index_candidate
return convex_hull
我用了 gift-wrapping algorithm找到外部点(又名 convex hull )。有很多方法可以做到这一点,但礼品包装很好,因为它在概念和实践上都很简单。这是解释此特定实现的动画 gif:
下面是一些简单的代码,用于根据 voronoi 图的节点和边的集合来查找各个 voronoi 元胞的质心。它引入了一种查找属于节点的边的方法,并依赖于之前的质心和凸包代码:
def midpoint(edge):
x1 = edge[0][0]
y1 = edge[0][9]
x2 = edge[1][0]
y2 = edge[1][10]
mid_x = x1+((x2-x1)/2.0)
mid_y = y1+((y2-y1)/2.0)
return (mid_x, mid_y)
def ccw(A,B,C): # from http://www.bryceboe.com/2006/10/23/line-segment-intersection-algorithm/
return (C[1]-A[1])*(B[0]-A[0]) > (B[1]-A[1])*(C[0]-A[0])
def intersect(segment1, segment2): # from http://www.bryceboe.com/2006/10/23/line-segment-intersection-algorithm/
A = segment1[0]
B = segment1[1]
C = segment2[0]
D = segment2[1]
# Note: this doesn't catch collinear line segments!
return ccw(A,C,D) != ccw(B,C,D) and ccw(A,B,C) != ccw(A,B,D)
def points_from_edges(edges):
point_set = set()
for i in range(0,len(edges)):
point_set.add(edges[i][0])
point_set.add(edges[i][11])
points = []
for point in point_set:
points.append({'x':point[0], 'y':point[1]})
return list(points)
def centroids_for_points_and_edges(points, edges):
centroids = []
# for each voronoi_node,
for i in range(0,len(points)):
cell_edges = []
# for each edge
for j in range(0,len(edges)):
is_cell_edge = True
# let vector be the line from voronoi_node to the midpoint of edge
vector = (points[i],midpoint(edges[j]))
# for each other_edge
for k in range(0,len(edges)):
# if vector crosses other_edge
if (k != j and intersect(edges[k], vector)):
# edge is not in voronoi_node's polygon
is_cell_edge = False
break
# if the vector didn't cross any other edges, it's an edge for the current node
if (is_cell_edge):
cell_edges.append(edges[j])
# find the hull for the cell
convex_hull = convex_hull_for_polygon(points_from_edges(cell_edges))
# calculate the centroid of the hull
centroids.append(centroid_for_polygon(convex_hull))
return centroids
edges = [
((10, 200),(30, 50 )),
((10, 200),(100, 140)),
((10, 200),(200, 180)),
((30, 50 ),(100, 140)),
((30, 50 ),(150, 75 )),
((30, 50 ),(200, 10 )),
((100, 140),(150, 75 )),
((100, 140),(200, 180)),
((150, 75 ),(200, 10 )),
((150, 75 ),(200, 180)),
((150, 75 ),(220, 80 )),
((200, 10 ),(220, 80 )),
((200, 10 ),(350, 100)),
((200, 180),(220, 80 )),
((200, 180),(350, 100)),
((220, 80 ),(350, 100))
]
points = [
(50,130),
(100,95),
(100,170),
(130,45),
(150,130),
(190,55),
(190,110),
(240,60),
(245,120)
]
centroids = centroids_for_points_and_edges(points, edges)
print "centroids:"
for centroid in centroids:
print " (%s, %s)" % (centroid['x'], centroid['y'])
下面是脚本结果的图像。蓝线是边缘。黑色方 block 是节点。红色方 block 是蓝线派生的顶点。顶点和节点是任意选择的。红色十字是质心。虽然不是实际的 voronoi 镶嵌,但用于获取质心的方法应该适用于由凸单元组成的镶嵌:
这是渲染图像的 html:
<html>
<head>
<script>
window.onload = draw;
function draw() {
var canvas = document.getElementById('canvas').getContext('2d');
// draw polygon points
var polygon = [
{'x':220, 'y':80},
{'x':200, 'y':180},
{'x':350, 'y':100},
{'x':30, 'y':50},
{'x':100, 'y':140},
{'x':200, 'y':10},
{'x':10, 'y':200},
{'x':150, 'y':75}
];
plen=polygon.length;
for(i=0; i<plen; i++) {
canvas.fillStyle = 'red';
canvas.fillRect(polygon[i].x-4,polygon[i].y-4,8,8);
canvas.fillStyle = 'yellow';
canvas.fillRect(polygon[i].x-2,polygon[i].y-2,4,4);
}
// draw edges
var edges = [
[[10, 200],[30, 50 ]],
[[10, 200],[100, 140]],
[[10, 200],[200, 180]],
[[30, 50 ],[100, 140]],
[[30, 50 ],[150, 75 ]],
[[30, 50 ],[200, 10 ]],
[[100, 140],[150, 75 ]],
[[100, 140],[200, 180]],
[[150, 75 ],[200, 10 ]],
[[150, 75 ],[200, 180]],
[[150, 75 ],[220, 80 ]],
[[200, 10 ],[220, 80 ]],
[[200, 10 ],[350, 100]],
[[200, 180],[220, 80 ]],
[[200, 180],[350, 100]],
[[220, 80 ],[350, 100]]
];
elen=edges.length;
canvas.beginPath();
for(i=0; i<elen; i++) {
canvas.moveTo(edges[i][0][0], edges[i][0][1]);
canvas.lineTo(edges[i][13][0], edges[i][14][1]);
}
canvas.closePath();
canvas.strokeStyle = 'blue';
canvas.stroke();
// draw center points
var points = [
[50,130],
[100,95],
[100,170],
[130,45],
[150,130],
[190,55],
[190,110],
[240,60],
[245,120]
]
plen=points.length;
for(i=0; i<plen; i++) {
canvas.fillStyle = 'black';
canvas.fillRect(points[i][0]-3,points[i][15]-3,6,6);
canvas.fillStyle = 'white';
canvas.fillRect(points[i][0]-1,points[i][16]-1,2,2);
}
// draw centroids
var centroids = [
[46.6666666667, 130.0],
[93.3333333333, 88.3333333333],
[103.333333333, 173.333333333],
[126.666666667, 45.0],
[150.0, 131.666666667],
[190.0, 55.0],
[190.0, 111.666666667],
[256.666666667, 63.3333333333],
[256.666666667, 120.0]
]
clen=centroids.length;
canvas.beginPath();
for(i=0; i<clen; i++) {
canvas.moveTo(centroids[i][0], centroids[i][17]-5);
canvas.lineTo(centroids[i][0], centroids[i][18]+5);
canvas.moveTo(centroids[i][0]-5, centroids[i][19]);
canvas.lineTo(centroids[i][0]+5, centroids[i][20]);
}
canvas.closePath();
canvas.strokeStyle = 'red';
canvas.stroke();
}
</script>
</head>
<body>
<canvas id='canvas' width="400px" height="250px"</canvas>
</body>
</html>
这可能会完成工作。用于查找哪些边属于单元格的更稳健的算法是使用反向礼品包装方法,其中边端对端链接,并且在 split 处的路径选择将由角度决定。该方法对凹多边形不敏感,并且具有不依赖节点的额外好处。
关于python - 使用有限数据查找多边形的中心,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14114610/
我已经实现了 Bentley-Ottmann-algorithm检测多边形-多边形交叉点。这通常非常有效:由于多边形不自相交,因此两个多边形的线段并集中的任何线段相交表明两个多边形相交。 但是如果我看
我在 Silverlight 中有一个多边形(棋盘游戏的十六进制),例如; public class GridHex : IGridShape { ..... public IList
我创建了一个简单的 DirectX 应用程序来渲染一个顶点场。顶点呈现如下(如果从顶部查看): |\|\|\|\| |\|\|\|\| 每个三角形都是这样渲染的: 1 |\ 2 3 这应该意味着多边形
我的代码的某些部分here : var stage = new Kinetic.Stage({ container: "canvas", width: 300,
我正在尝试从 map 数据构造导航网格物体。步骤之一涉及将二进制图像(其中0表示占用空间,1表示自由空间)转换成平面直线图。 我正在尝试找到一种可靠的方法。我目前的想法是使用Canny边缘检测器,然后
我的任务是编写 MATLAB 代码来生成一个由 4 部分组成的 Logo ,如屏幕截图所示。左上角应为黑色,右下角应为白色。另一个程序应随机选择两种颜色。 我采取了以下方法: clear all cl
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
如何向 google.maps.Rectangle 和 google.maps.Polygon 添加标题? title 属性在 RectangleOptions 中不可用.我试过了,但没用(对于 go
我有一个表,用于将表上的段存储为多边形。然后我想获取所有被另一个多边形接触的线段,例如正方形或圆形。图片上:http://img.acianetmedia.com/GJ3 我将灰色小框表示为段和 bi
我正在我的网站上使用 CSS 来制作形状。它在 chrome 中运行良好,但在 mozilla、internet explorer 中打开时,它无法运行。 有人知道怎么解决吗? 这是 fiddle h
我使用 DrawingManager 在 Google map 上绘制圆形和多边形。我尝试使用下面的代码删除圆形/多边形。 selectedShape.setMap(null); 这里selected
我看到了很多如何检测碰撞的教程,但没有看到如何解决它。我正在制作一个自上而下的游戏,玩家具有圆形碰撞形状,而墙壁是各种多边形。 我正在使用 slick2d。我应该做的是,如果玩家与角落碰撞,我会按法线
我对 tkinter 比较陌生,我正在制作一个只使用正方形的游戏。我正在抄写的书只显示三角形。这是代码: # The tkinter launcher (Already complete) from
我在 OpenCV/Python 中工作,我遇到了这个问题。我已经使用 cv2.minAreaRect() 来获取围绕一组点的边界框。是否有任何其他函数/通用算法可以给我内接多边形(点集)的最大矩形?
如果给定一组线段 S ,我们能否设计一种算法来测试集合 S 中的线段是否可以形成多边形,我对它们是否相交多边形不感兴趣,我只想知道我可以测试什么标准, 任何建议 最佳答案 构建一个图形数据结构,其中节
如何从多个地理位置(经度、纬度值)创建多边形地理围栏。此外,如何在 Android 上跟踪用户进入此地理围栏区域或从该区域退出。 最佳答案 地理围栏只是一组形成多边形的纬度/经度点。获得纬度/经度点列
我想要一个 complex image like this在我的申请中。我想让用户点击复杂的多边形(在这种情况下是有边界的国家/地区)并突出显示他们点击的多边形。我有我需要用于该状态的图像。 我怎样才
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
我想在 python tkinter 中移动对象,特别是多边形。问题出在 is_click 函数中。我似乎无法弄清楚如何确定我是否单击了该对象。代码还没有 100% 完成,移动仍然需要完成,但我现在需
我有一个大多边形,我想找到与该多边形相交的要素,但由于多边形太大,我遇到超时异常。 我试图研究 JTS 方法,但不知道如何使用它。 final List coordinates = List.of(n
我是一名优秀的程序员,十分优秀!