因为各种原因,想顺着我的开发思路写,但是现在感觉这么写太啰嗦了,直接写核心代码吧。
算法依然是之前的小文的算法,通过代码验证算法是可行的,并没有太大的疏漏。根据代码吧算法又进行了归纳,流程图如下:
说明:Box表示盛放七巧板的盒子多边形,part是七巧板部件。上面的算法没有进行优化,例如正方形的部件实际上各边是一样的,不用测试其余边。
代码如下:
public static bool MatchPolygon(TangramPolygon partPlg, out TangramPolygon outPart, Control ctrl = null)
{
//1# get the first vertex of the boxPlg and calculate the angle between xAxis and the first side fo the boxPlg
double boxAngle, partAngle;
// from the first point of the boxPlg
var boxPlg = partPlg.usingBoxPlg;
outPart = boxPlg;
int boxIdx = boxPlg.firstPntIdx;
boxAngle = GetAngleToXaxis(boxPlg.GetVertexPoint(boxIdx), boxPlg.GetNextVertexPoint(boxIdx));
bool bAllInBox = false;
int i;
for (i = partPlg.usingIdx; i < partPlg.Count(); i++)
{
TangramPolygon partPlgCpy = new TangramPolygon(partPlg.m_OrgPointArr);
var pntA = partPlgCpy.GetVertex(i).m_Point;
var pntB = partPlgCpy.GetNextVertex(i).m_Point;
partAngle = GetAngleToXaxis(pntA, pntB);
//partAngle = GetAngleToXaxis(partPlgCpy.GetOrgPoint(i), partPlgCpy.GetNextOrgPoint(i));
double rotA = boxAngle - partAngle;
partPlgCpy = CMyPolygonTool.Rotate(partPlgCpy,boxPlg.GetVertexPoint(boxPlg.firstPntIdx), i, rotA);
//set the first point to i
if (ctrl != null)
{
ctrl.Refresh();
partPlgCpy.DrawPolygon(ctrl, Color.Red);
//MessageBox.Show("Testing ");
}
//
//check if the part is in the main Box
bool bInBox = true;
int segIdx = 0;
for (int j = 0; j < partPlgCpy.Count(); j++)
{
PointF pnt1 = partPlgCpy.GetVertexPoint(segIdx);
PointF pnt2 = partPlgCpy.GetNextVertexPoint(segIdx);
if (ctrl != null)
{
Graphics g = ctrl.CreateGraphics();
SolidBrush brsh = new SolidBrush(Color.Yellow);
Pen pen = new Pen(brsh, 3);
g.DrawLine(pen, pnt1, pnt2);
}
if (!boxPlg.SegInsidePlg(new Segment(pnt1, pnt2), boxPlg))
{
bInBox = false;
break;
}
segIdx = partPlgCpy.GetVertex(segIdx).next_idx;
}
if (bInBox)
{
outPart = partPlgCpy;
bAllInBox = true;
break;
}
}
partPlg.usingIdx = i;
return bAllInBox;
}
里面包含了调试代码。
另外这种匹配方式,不能完全匹配所有的可能性,改匹配方式是匹配各自多边形的左下部分,如图示:
上述方法不能匹配图中红的部分,尽管在匹配的迭代过程中,这过程可能会因为其他形状匹配之后,可以使红色方块出现在上图的位置上,但是算法上并没有保证。
几个子函数的说明:
1、计算指定边到X轴的角度,顺时针为正角度,反正负角度。
GetAngleToXaxis(boxPlg.GetVertexPoint(boxIdx), boxPlg.GetNextVertexPoint(boxIdx));
2、多边形旋转
Rotate(partPlgCpy,boxPlg.GetVertexPoint(boxPlg.firstPntIdx), i, rotA);
3、线段是否在多边形内部(包括边上)
SegInsidePlg(new Segment(pnt1, pnt2), boxPlg))
其余函数是GDI函数。
计算剩余区域的算法和函数,准备在下一文介绍、
MaraSun 2022-05-12 BJFWDQ
南丁格尔节
汶川地震日
中国清零进行中
北京慢慢进入上海状态