我需要编写和算法用水平等距线填充闭合多义线。
我用矩形和 circle 做了类似的事情,这是后者的代码片段:
// circle parameters: center(point(0).x, point(0).y), radius
int offsetX = point(0).x + radius;
int offsetY = point(0).y + radius;
for(int i = -radius; i < radius; i += spacing){
int ry = i;
int rx = sqrt(double(radius*radius - ry*ry));
// the parameters are pair of coordinates of the horizontal line
fl_line(offsetX - rx, offsetY + i,
offsetX + rx, offsetY + i);
}
在闭合多线的情况下,额外的难度(对我而言)是水平线的坐标不会从单个方程中提取(圆形,矩形的高度,等),而是来自具有相同“y”坐标的线的方程式,这些坐标将不会连续匹配。
答案 0 :(得分:5)
这只是扫描线算法(用于填充多边形)的特例:http://www.tutorialspoint.com/computer_graphics/polygon_filling_algorithm.htm
使用所需的步长(间距)将y从yMin(多边形的顶部)迭代到yMax。
对于每个y,找到与多边形线段的交点,按x坐标排序,用线连接每隔一对
答案 1 :(得分:1)
首先创建一个具有最低端点的所有边的列表。通过增加纵坐标(最低端点)对列表进行排序。
创建一个“活动列表”,其中包含与当前水平相交的所有边。
初始化最低边缘下方的当前水平位置,并确保活动列表为空。
以所需的增量向上移动水平,直到活动列表再次清空。
移动后,从活动列表中丢弃不再与其相交的边。还要添加将开始交叉的边缘(因为边缘已经排序,您将搜索不超过需要的数量。)
请注意,可以完全跳过边缘(它可以进入活动列表并立即离开)。
当活动列表是最新的时,计算所有交叉点并按从左到右的水平段连接它们。
请注意,在成对连接交叉点之前,可以通过在必要时小心插入新边来避免水平排序。鉴于活动列表通常很短,我更喜欢系统地应用插入排序。
假设所有活动列表操作都采用列表大小的线性时间,总时间就像O(Ne.Lg(Ne) + Ny.L)
,其中Ne
是边数,Ny
的数量是L
水平线和O(Ne.Ny)
每个水平线的平均交叉点数(通常在2到4之间)。对于天真的算法,这将与button(-text => 'Row1', -command => \&do_something_with('Row 1'));
ttk::button -text $row -command [list RowOpertaion $row $xyz $abc]
进行比较。