在该书中的4.3基本图形的绘制的例程中,关于P102中的DrawPolygon()函数的写法代码中,遇到了几个问题,这里进行自我总结:
首先贴出书上的源码:
//-------------------【DrawPolygon( )函数】--------------------------
//描述:自定义的绘制函数,实现了凹多边形的绘制
//-----------------------------------------------------------------
void DrawPolygon( Mat img )
{
int lineType = 8;
//创建一些点
Point rookPoints[1][20];
rookPoints[0][0] = Point( WINDOW_WIDTH/4, 7*WINDOW_WIDTH/8 );
rookPoints[0][1] = Point( 3*WINDOW_WIDTH/4, 7*WINDOW_WIDTH/8 );
rookPoints[0][2] = Point( 3*WINDOW_WIDTH/4, 13*WINDOW_WIDTH/16 );
rookPoints[0][3] = Point( 11*WINDOW_WIDTH/16, 13*WINDOW_WIDTH/16 );
rookPoints[0][4] = Point( 19*WINDOW_WIDTH/32, 3*WINDOW_WIDTH/8 );
rookPoints[0][5] = Point( 3*WINDOW_WIDTH/4, 3*WINDOW_WIDTH/8 );
rookPoints[0][6] = Point( 3*WINDOW_WIDTH/4, WINDOW_WIDTH/8 );
rookPoints[0][7] = Point( 26*WINDOW_WIDTH/40, WINDOW_WIDTH/8 );
rookPoints[0][8] = Point( 26*WINDOW_WIDTH/40, WINDOW_WIDTH/4 );
rookPoints[0][9] = Point( 22*WINDOW_WIDTH/40, WINDOW_WIDTH/4 );
rookPoints[0][10] = Point( 22*WINDOW_WIDTH/40, WINDOW_WIDTH/8 );
rookPoints[0][11] = Point( 18*WINDOW_WIDTH/40, WINDOW_WIDTH/8 );
rookPoints[0][12] = Point( 18*WINDOW_WIDTH/40, WINDOW_WIDTH/4 );
rookPoints[0][13] = Point( 14*WINDOW_WIDTH/40, WINDOW_WIDTH/4 );
rookPoints[0][14] = Point( 14*WINDOW_WIDTH/40, WINDOW_WIDTH/8 );
rookPoints[0][15] = Point( WINDOW_WIDTH/4, WINDOW_WIDTH/8 );
rookPoints[0][16] = Point( WINDOW_WIDTH/4, 3*WINDOW_WIDTH/8 );
rookPoints[0][17] = Point( 13*WINDOW_WIDTH/32, 3*WINDOW_WIDTH/8 );
rookPoints[0][18] = Point( 5*WINDOW_WIDTH/16, 13*WINDOW_WIDTH/16 );
rookPoints[0][19] = Point( WINDOW_WIDTH/4, 13*WINDOW_WIDTH/16 );
const Point* ppt[1] = { rookPoints[0] };
int npt[] = { 20 };
fillPoly( img,
ppt,
npt,
1,
Scalar( 255, 255, 255 ),
lineType );
}
遇到的问题:
①为什么创建一些点的时候,要定义二维数组Point rookPoints[1][20];这和直接定义一维数组Point rookPoint[20];不是一样的吗?
②在定义了点的二维数组Point rookPoints[1][20];之后,为何又要定义一个中间变量const Point* ppt[1] = { rookPoints[0] };呢?
③在书中关于fillPoly()函数中,说明了npt是绘制的多边形顶点数目,为什么要定义成int npt[] = { 20 };而不是直接定义成 int npt=20;呢?
首先去找了下关于fillPoly()函数的说明:
void fillPoly(cvArr* img, cvPoint** pts,int* npts, int contours, cvScalar color, int line_type=8, int shift=0;);
参数说明:
img:图像
pts:指向多边形的数组指针
npts:多边形的顶点个数的数组
contours:要绘制多边形的数量
color:多边形的颜色
line_type:组成多边形的线条的类型
shift:顶点坐标的小数点位数
这就可以解释问题①中为什么要定义二维数组了,因为fillPoly函数中第二个参数就是这么要求的cvPoint**类型
问题③也能解决了,因为要求的是多边形的顶点个数的数组。
关于问题②,在网上也问了一些人,查了些资料,大概意思是
因为fillPoly函数中要求的是cvPoint**类型,直接传rookPoints的话 有些编译器会报warning 甚至还会报error 的错误。若想避免这个才会加个中间变量。
看到这里时,我还是一脸懵逼,fillPoly函数中要求的是二级常指针,而作为中间变量的const Point* ppt[1]他还是一个一级常指针啊,为什么编译就通过了呢?
网上还给出了一个测试程序:
#include <iostream>
using namespace std;
typedef int Point;
void fillPoly(const Point** pts)
{
}
int main()
{
Point rookPoints[1][20];
const Point* ppt[1] = { rookPoints[0] };
Point* ppt1[1] = { rookPoints[0] };
fillPoly(ppt);
fillPoly(ppt1);
fillPoly(rookPoints);
fillPoly((const Point **)rookPoints);
return 0;
}
大概意思就是定义了一个fillPoly函数、一个rookPoints数组和两个中间变量ppt和ppt1。我去VS编译器试了下,进行编译的时候,fillPoly(ppt1);和fillPoly(rookPoints);报错了,而fillPoly(ppt);和fillPoly((const Point **)rookPoints);没有报错。
这里的fillPoly(ppt);就和书上的做法一样,但明明ppt是一级常指针,却没有报错,还是不明白。
关于一级和二级常指针,自己也补充了点知识:如果函数给它传递的是int*参数,编译是可以通过的,不需要强制转换;但如果是传递的int**参数,编译不能通过,需要进行强制转换,就如上面的fillPoly((const Point **)rookPoints);。
仍然没有解决问题②,若有大佬看到,麻烦能解惑,不胜感激!