使用 Sutherland-Hodgman 算法时多边形裁剪不起作用
Posted
技术标签:
【中文标题】使用 Sutherland-Hodgman 算法时多边形裁剪不起作用【英文标题】:Polygon Clipping not working when using Sutherland-Hodgman Algorithm 【发布时间】:2015-04-23 12:17:29 【问题描述】:我正在编写一个程序来创建一个形状像鱼的多边形并用绿色填充它。有一些按钮可以在窗口内移动这条鱼。我只想让窗口内的鱼的部分可见,所以我试图实现 Sutherland-Hodgman 算法来做到这一点。
我不肯定我哪里出错了。我所知道的是,当我接触到窗户的边缘时,我最终会看到线条到不应该出现的地方。
例如:
第一张图片是在它撞到边缘之前,第二张是当鱼撞到窗口的顶部边缘时:
这是我为实现多边形裁剪的 Sutherland-Hodgman 算法而编写的代码:
int left_most_edge, right_most_edge, scan = 0;
double wxl = 50, wxh = 362, wyl = 246, wyh = 62;
double[][] table = new double[4][200]; //2d array containing:
//[0][-] -> ymax, [1][-] -> ymin, [2][-] -> dx, [3][-] -> x
double[] px = 100, 150, 200, 210, 215, 205, 215, 210, 200, 150; //contains all x coord.
double[] py = 125, 100, 120, 110, 115, 125, 135, 140, 130, 150; //contains all y coord.
double[] xout = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
double[] yout = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
int outnum;
double[] lastl = new double[2];
double[] lastr = new double[2];
double[] lastt = new double[2];
double[] lastb = new double[2];
boolean drawAgain = false;
public void clipPolygon(Graphics g, int number_entered_edges)
//clips the polygon so only parts that are in the viewing window get filled
lastl[0] = px[number_entered_edges - 1];
lastl[1] = py[number_entered_edges - 1];
lastr[0] = wxl;
lastb[0] = wxl;
lastt[0] = wxl;
lastr[1] = wyl;
lastb[1] = wyl;
lastt[1] = wyl;
outnum = 0;
for (int i = 0; i < number_entered_edges; i++)
clipL(px[i], py[i]);
//end for
outnum = 0;
for (int i = 0; i < number_entered_edges; i++)
clipL(px[i], py[i]);
//end for
//end clipPolygon
public void clipL(double x, double y)
//clips from the left
if ((lastl[0] < wxl && wxl <= x) || (x <= wxl && wxl < lastl[0]))
System.out.println("Passed into clipR -> (" + wxl + ", " + ((((y - lastl[1]) * (wxl - x)) / x - lastl[0]) + y) + ")");
System.out.println(y + " - " + lastl[1] + " * " + "(" + wxl + " - " + x + ") / " + x + " - " + lastl[0] + " + " + y + ")");
clipR(wxl, ((((y - lastl[1]) * (wxl - x)) / x - lastl[0]) + y));
drawAgain = true;
//end if
lastl[0] = x;
lastl[1] = y;
if (wxl < x)
clipR(x, y);
//end clipL
public void clipR(double x, double y)
//clips from the right
System.out.println("herro: " + x + ", " + y);
if ((x <= wxh && wxh < lastr[0]) || (lastr[0] < wxh && wxh <= x))
clipB(wxh, ((((y - lastr[1]) * (wxh - x)) / x - lastr[0]) + y));
drawAgain = true;
//end if
lastr[0] = x;
lastr[1] = y;
if (x < wxh)
clipB(x, y);
//end clipR
public void clipB(double x, double y)
//clips from the bottom
if ((lastb[1] < wyl && wyl <= y) || (y <= wyl && wyl < lastb[1]))
clipT(((((x - lastb[0]) * (wyl - y)) / y - lastb[1]) + x), wyl);
drawAgain = true;
//end if
lastb[0] = x;
lastb[1] = y;
if (wyl > y)
clipT(x, y);
//end clipB
public void clipT(double x, double y)
//clips from the top
if ((lastt[1] > wyh && wyh >= y) || y >= wyh && wyh > lastt[1])
store(((((x - lastt[0]) * (wyh - y)) / y - lastt[1]) + x), wyh);
drawAgain = true;
//end if
lastt[0] = x;
lastt[1] = y;
if (wyh < y)
store(x, y);
//end clipT
public void store(double x, double y)
//stores the final coordinates after clipping
xout[outnum] = x;
yout[outnum] = y;
outnum++;
//end store
public void drawMyPolygon(Graphics g)
//draws the polygon
g.setColor(Color.RED);
g.drawLine((int) px[0], (int) py[0], (int) px[1], (int) py[1]);
g.drawLine((int) px[1], (int) py[1], (int) px[2], (int) py[2]);
g.drawLine((int) px[2], (int) py[2], (int) px[3], (int) py[3]);
g.drawLine((int) px[3], (int) py[3], (int) px[4], (int) py[4]);
g.drawLine((int) px[4], (int) py[4], (int) px[5], (int) py[5]);
g.drawLine((int) px[5], (int) py[5], (int) px[6], (int) py[6]);
g.drawLine((int) px[6], (int) py[6], (int) px[7], (int) py[7]);
g.drawLine((int) px[7], (int) py[7], (int) px[8], (int) py[8]);
g.drawLine((int) px[8], (int) py[8], (int) px[9], (int) py[9]);
g.drawLine((int) px[9], (int) py[9], (int) px[0], (int) py[0]);
//end drawMyPolygon
public void drawNewPolygon(Graphics g)
//draw a new polygon with the coordinates of the clipped polygon
g.setColor(Color.RED);
g.drawLine((int) xout[0], (int) yout[0], (int) xout[1], (int) yout[1]);
g.drawLine((int) xout[1], (int) yout[1], (int) xout[2], (int) yout[2]);
g.drawLine((int) xout[2], (int) yout[2], (int) xout[3], (int) yout[3]);
g.drawLine((int) xout[3], (int) yout[3], (int) xout[4], (int) yout[4]);
g.drawLine((int) xout[4], (int) yout[4], (int) xout[5], (int) yout[5]);
g.drawLine((int) xout[5], (int) yout[5], (int) xout[6], (int) yout[6]);
g.drawLine((int) xout[6], (int) yout[6], (int) xout[7], (int) yout[7]);
g.drawLine((int) xout[7], (int) yout[7], (int) xout[8], (int) yout[8]);
g.drawLine((int) xout[8], (int) yout[8], (int) xout[9], (int) yout[9]);
g.drawLine((int) xout[9], (int) yout[9], (int) xout[0], (int) yout[0]);
drawAgain = false;
//end drawNewPolygon
public void drawMyHorizontalLine(Graphics g, int x1, int y, int x2)
//draws the line for filling
g.setColor(Color.GREEN);
g.drawLine(x1, y, x2, y);
//end drawMyHorizontalLine
public void drawWindow(Graphics g)
//draws the viewing window
g.setColor(Color.BLACK);
g.drawLine((int)wxl, (int)wyh, (int)wxl, (int)wyl);
g.drawLine((int)wxl, (int)wyh, (int)wxh, (int)wyh);
g.drawLine((int)wxl, (int)wyl, (int)wxh, (int)wyl);
g.drawLine((int)wxh, (int)wyh, (int)wxh, (int)wyl);
//end drawWindow
@Override
public void paint(Graphics g)
super.paint(g);
//draw viewing window
drawWindow(g);
//initialize the edge table to all zeroes
initializeTable();
//clip the polygon
clipPolygon(g, 10);
System.out.println("Coordinates:");
System.out.println("(" + px[0] + ", " + py[0] + ")");
System.out.println("(" + px[1] + ", " + py[1] + ")");
System.out.println("(" + px[2] + ", " + py[2] + ")");
System.out.println("(" + px[3] + ", " + py[3] + ")");
System.out.println("(" + px[4] + ", " + py[4] + ")");
System.out.println("(" + px[5] + ", " + py[5] + ")");
System.out.println("(" + px[6] + ", " + py[6] + ")");
System.out.println("(" + px[7] + ", " + py[7] + ")");
System.out.println("(" + px[8] + ", " + py[8] + ")");
System.out.println("(" + px[9] + ", " + py[9] + ")");
System.out.println("\nStored:");
System.out.println("(" + xout[0] + ", " + yout[0] + ")");
System.out.println("(" + xout[1] + ", " + yout[1] + ")");
System.out.println("(" + xout[2] + ", " + yout[2] + ")");
System.out.println("(" + xout[3] + ", " + yout[3] + ")");
System.out.println("(" + xout[4] + ", " + yout[4] + ")");
System.out.println("(" + xout[5] + ", " + yout[5] + ")");
System.out.println("(" + xout[6] + ", " + yout[6] + ")");
System.out.println("(" + xout[7] + ", " + yout[7] + ")");
System.out.println("(" + xout[8] + ", " + yout[8] + ")");
System.out.println("(" + xout[9] + ", " + yout[9] + ")");
for (int i = 0; i < xout.length; i++)
System.out.println("outnum -> " + outnum);
//draw polygon with red outline
if (drawAgain)
fillMyPolygon(g, 10, 10);
drawNewPolygon(g);
//end if
else
fillMyPolygon(g, 10, 10);
drawMyPolygon(g);
//end else
//set buttons to visible
buttons();
//end paint
如果您有任何想法或可能需要更多信息,请告诉我。谢谢。
【问题讨论】:
我强烈建议您使用调试器逐步完成此操作。 在这里查看算法:youtube.com/watch?v=Euuw72Ymu0M 【参考方案1】:算法的问题很简单,就是缺少括号来分隔公式的不同部分,这些部分决定了剪裁线的新坐标。解决后,它运行良好。
【讨论】:
以上是关于使用 Sutherland-Hodgman 算法时多边形裁剪不起作用的主要内容,如果未能解决你的问题,请参考以下文章
使用 createML 创建文本分类器模型时使用啥机器学习算法?
在 python 中使用 in 运算符搜索列表时使用啥算法?