跨平台二维绘图程序(四)——多边形绘制
2017-08-02 16:09
316 查看
前三篇内容的基础上,可以绘制出如下的图形:
![](https://img-blog.csdn.net/20170802142812931?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2F5cmlnaHQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
这一篇介绍如何绘制多边形。
(1)GDI通过API函数Polygon或者PolyPolygon就能够绘制不规则的多边形,包括自交带内洞,而GLES只能绘制三角形;
(2)多边形三角化有个开源的triangle.h,这里推荐下:http://compgeom.com/~piyush/scripts/triangle/triangle_8h-source.html
(3)三角化的时候要注意几个问题。多边形点中不可以有重复坐标点,否则会出错;多边形坐标点数不可过少,否则出错。
以下是多边形三角化的一个类:
struct Triangle
{
std::vector<Coor> cos;
void set(const std::vector<Coor>& polygon)
{
cos.clear();
cos.insert(cos.end(), polygon.begin(), polygon.end());
}
void set(const Coor& A, const Coor& B, const Coor& C)
{
cos.clear();
cos.push_back(A);
cos.push_back(B);
cos.push_back(C);
}
};
class WithInnerTriangulation
{// 2D Coor
public:
Coor getCenter(const std::vector<Coor>& cos)
{
Coor center;
if (cos.size() == 3)
{
for (size_t j = 0; j < 3; ++j)
{
center.x += cos[j].x;
center.y += cos[j].y;
}
}
else
{
struct triangulateio in, out;
triangulateioinit(&in);
triangulateioinit(&out);
int numPoints = cos.size();
int numSeg = cos.size();
in.numberofpoints = numPoints;
in.numberofpointattributes = 0;
in.pointlist = (REAL*)malloc(sizeof(REAL) * in.numberofpoints * 2);
for (size_t i = 0; i < cos.size(); i++)
{
in.pointlist[i * 2 + 0] = cos[i].x;
in.pointlist[i * 2 + 1] = cos[i].y;
}
in.numberofsegments = numSeg;
in.segmentlist = (int*)malloc(sizeof(int) * in.numberofsegments * 2);
size_t i = 0;
for (i = 0; i < cos.size() - 1; i++)
{
in.segmentlist[i * 2 + 0] = i;
in.segmentlist[i * 2 + 1] = i + 1;
}
in.segmentlist[i * 2 + 0] = i;
in.segmentlist[i * 2 + 1] = 0;
triangulate("pzFQ", &in, &out, NULL);
int count = out.numberoftriangles * 3;
if (count > 3)
count = 3;
for (int i = 0; i < count; i++)
{
int coor_index = out.trianglelist[i];
center.x += out.pointlist[coor_index * 2];
center.y += out.pointlist[coor_index * 2 + 1];
}
triangulateiofree(&out, 0);
triangulateiofree(&in, 1);
}
center.x /= 3;
center.y /= 3;
return center;
}
bool transform(const std::vector< std::vector<Coor> >& polys2,
std::vector<Triangle>& triangles)
{
struct triangulateio in, out;
triangulateioinit(&in);
triangulateioinit(&out);
std::vector< std::vector<Coor> > polys;
for (size_t i = 0; i < polys2.size(); ++i)
{
std::vector<Coor> temp;
GeoAlgorithm::kick_overlay_dot(polys2[i],
temp,
false);
if (temp.size() >= 3)
{
// 点数过少会导致后面的triangulate函数崩溃
polys.push_back(temp);
}
}
if (polys.size() == 0)
{
return false;
}
int numPoints = 0;
int numSeg = 0;
std::vector<Coor> centers;
for (size_t i = 0; i < polys.size(); i++)
{
numSeg += polys[i].size();
Coor center = getCenter(polys[i]);
centers.push_back(center);
}
numPoints = numSeg;
in.numberofpoints = numPoints;
in.numberofpointattributes = 0;
in.pointlist = (REAL*)malloc(sizeof(REAL) * in.numberofpoints * 2);
int pointc = 0;
for (size_t i = 0; i < polys.size(); i++)
{
for (size_t j = 0; j < polys[i].size(); j++, pointc++)
{
in.pointlist[pointc * 2 + 0] = polys[i][j].x;
in.pointlist[pointc * 2 + 1] = polys[i][j].y;
}
}
in.numberofsegments = numSeg;
in.segmentlist = (int*)malloc(sizeof(int) * in.numberofsegments * 2);
pointc = 0;
for (size_t i = 0; i < polys.size(); i++, pointc++)
{
int first = pointc;
for (size_t j = 0; j < polys[i].size() - 1; j++, pointc++)
{
in.segmentlist[pointc * 2 + 0] = pointc;
in.segmentlist[pointc * 2 + 1] = pointc + 1;
}
in.segmentlist[pointc * 2 + 0] = pointc;
in.segmentlist[pointc * 2 + 1] = first;
}
in.numberofregions = 0;
in.numberofholes = centers.size() - 1;
in.holelist = (REAL*)malloc(sizeof(REAL) * in.numberofholes * 2);
for (size_t i = 1; i < centers.size(); i++)
{
in.holelist[(i - 1) * 2 + 0] = centers[i].x;
in.holelist[(i - 1) * 2 + 1] = centers[i].y;
}
triangulate("pzFQ", &in, &out, NULL);
// verify the mesh a bit
if (out.numberofpoints - out.numberofedges + out.numberoftriangles !=
2 - centers.size())
{
cout << endl << "epc wrong" << endl;
}
std::vector<Coor> cos;
int numberofvertex, coor_index;
numberofvertex = out.numberoftriangles * 3;
for (int i = 0; i < numberofvertex; i++)
{
coor_index = out.trianglelist[i];
Coor co;
co.x = out.pointlist[coor_index * 2];
co.y = out.pointlist[coor_index * 2 + 1];
cos.push_back(co);
}
for (int i = 0; i < out.numberoftriangles; ++i)
{
Triangle tri;
tri.set(cos[3 * i], cos[3 * i + 1], cos[3 * i + 2]);
triangles.push_back(tri);
}
triangulateiofree(&out, 0);
triangulateiofree(&in, 1);
return true;
}
};
有了这样的三角化类,就可以将不规则多边形(如凹多边形,带内洞多边形)转换为三角形,然后将三角形传递到VBO中。
std::vector< std::vector<Coor> > polys;
int32_t idx = 0;
for (int32_t i = 0; i < pc; ++i)
{
std::vector<Coor> pts;
for (int32_t j = 0; j < ptsc[i]; ++j)
{
Coor cc;
cc.x = pco[idx].x - m_vo.s_left;
cc.y = pco[idx].y - m_vo.s_bottom;
cc.z = 0.f;
pts.push_back(cc);
idx++;
}
polys.push_back(pts);
}
{
WithInnerTriangulation wit;
std::vector<Triangle> triangles;
wit.transform(polys, triangles);
size_t tc = triangles.size();
if (tc)
{
auto tri = triangles.begin();
while (tri != triangles.end())
{
PointF cc;
cc.z = m_vo.s_zIndex;
cc.x = tri->cos[0].x; cc.y = tri->cos[0].y;
m_vo.polyBuffer.cos.push_back(cc);
cc.x = tri->cos[1].x; cc.y = tri->cos[1].y;
m_vo.polyBuffer.cos.push_back(cc);
cc.x = tri->cos[2].x; cc.y = tri->cos[2].y;
m_vo.polyBuffer.cos.push_back(cc);
m_vo.polyBuffer.cols.push_back(colF);
m_vo.polyBuffer.cols.push_back(colF);
m_vo.polyBuffer.cols.push_back(colF);
++tri;
}
}
}
这样多边形就能够渲染出来了!
这一篇介绍如何绘制多边形。
(1)GDI通过API函数Polygon或者PolyPolygon就能够绘制不规则的多边形,包括自交带内洞,而GLES只能绘制三角形;
(2)多边形三角化有个开源的triangle.h,这里推荐下:http://compgeom.com/~piyush/scripts/triangle/triangle_8h-source.html
(3)三角化的时候要注意几个问题。多边形点中不可以有重复坐标点,否则会出错;多边形坐标点数不可过少,否则出错。
以下是多边形三角化的一个类:
struct Triangle
{
std::vector<Coor> cos;
void set(const std::vector<Coor>& polygon)
{
cos.clear();
cos.insert(cos.end(), polygon.begin(), polygon.end());
}
void set(const Coor& A, const Coor& B, const Coor& C)
{
cos.clear();
cos.push_back(A);
cos.push_back(B);
cos.push_back(C);
}
};
class WithInnerTriangulation
{// 2D Coor
public:
Coor getCenter(const std::vector<Coor>& cos)
{
Coor center;
if (cos.size() == 3)
{
for (size_t j = 0; j < 3; ++j)
{
center.x += cos[j].x;
center.y += cos[j].y;
}
}
else
{
struct triangulateio in, out;
triangulateioinit(&in);
triangulateioinit(&out);
int numPoints = cos.size();
int numSeg = cos.size();
in.numberofpoints = numPoints;
in.numberofpointattributes = 0;
in.pointlist = (REAL*)malloc(sizeof(REAL) * in.numberofpoints * 2);
for (size_t i = 0; i < cos.size(); i++)
{
in.pointlist[i * 2 + 0] = cos[i].x;
in.pointlist[i * 2 + 1] = cos[i].y;
}
in.numberofsegments = numSeg;
in.segmentlist = (int*)malloc(sizeof(int) * in.numberofsegments * 2);
size_t i = 0;
for (i = 0; i < cos.size() - 1; i++)
{
in.segmentlist[i * 2 + 0] = i;
in.segmentlist[i * 2 + 1] = i + 1;
}
in.segmentlist[i * 2 + 0] = i;
in.segmentlist[i * 2 + 1] = 0;
triangulate("pzFQ", &in, &out, NULL);
int count = out.numberoftriangles * 3;
if (count > 3)
count = 3;
for (int i = 0; i < count; i++)
{
int coor_index = out.trianglelist[i];
center.x += out.pointlist[coor_index * 2];
center.y += out.pointlist[coor_index * 2 + 1];
}
triangulateiofree(&out, 0);
triangulateiofree(&in, 1);
}
center.x /= 3;
center.y /= 3;
return center;
}
bool transform(const std::vector< std::vector<Coor> >& polys2,
std::vector<Triangle>& triangles)
{
struct triangulateio in, out;
triangulateioinit(&in);
triangulateioinit(&out);
std::vector< std::vector<Coor> > polys;
for (size_t i = 0; i < polys2.size(); ++i)
{
std::vector<Coor> temp;
GeoAlgorithm::kick_overlay_dot(polys2[i],
temp,
false);
if (temp.size() >= 3)
{
// 点数过少会导致后面的triangulate函数崩溃
polys.push_back(temp);
}
}
if (polys.size() == 0)
{
return false;
}
int numPoints = 0;
int numSeg = 0;
std::vector<Coor> centers;
for (size_t i = 0; i < polys.size(); i++)
{
numSeg += polys[i].size();
Coor center = getCenter(polys[i]);
centers.push_back(center);
}
numPoints = numSeg;
in.numberofpoints = numPoints;
in.numberofpointattributes = 0;
in.pointlist = (REAL*)malloc(sizeof(REAL) * in.numberofpoints * 2);
int pointc = 0;
for (size_t i = 0; i < polys.size(); i++)
{
for (size_t j = 0; j < polys[i].size(); j++, pointc++)
{
in.pointlist[pointc * 2 + 0] = polys[i][j].x;
in.pointlist[pointc * 2 + 1] = polys[i][j].y;
}
}
in.numberofsegments = numSeg;
in.segmentlist = (int*)malloc(sizeof(int) * in.numberofsegments * 2);
pointc = 0;
for (size_t i = 0; i < polys.size(); i++, pointc++)
{
int first = pointc;
for (size_t j = 0; j < polys[i].size() - 1; j++, pointc++)
{
in.segmentlist[pointc * 2 + 0] = pointc;
in.segmentlist[pointc * 2 + 1] = pointc + 1;
}
in.segmentlist[pointc * 2 + 0] = pointc;
in.segmentlist[pointc * 2 + 1] = first;
}
in.numberofregions = 0;
in.numberofholes = centers.size() - 1;
in.holelist = (REAL*)malloc(sizeof(REAL) * in.numberofholes * 2);
for (size_t i = 1; i < centers.size(); i++)
{
in.holelist[(i - 1) * 2 + 0] = centers[i].x;
in.holelist[(i - 1) * 2 + 1] = centers[i].y;
}
triangulate("pzFQ", &in, &out, NULL);
// verify the mesh a bit
if (out.numberofpoints - out.numberofedges + out.numberoftriangles !=
2 - centers.size())
{
cout << endl << "epc wrong" << endl;
}
std::vector<Coor> cos;
int numberofvertex, coor_index;
numberofvertex = out.numberoftriangles * 3;
for (int i = 0; i < numberofvertex; i++)
{
coor_index = out.trianglelist[i];
Coor co;
co.x = out.pointlist[coor_index * 2];
co.y = out.pointlist[coor_index * 2 + 1];
cos.push_back(co);
}
for (int i = 0; i < out.numberoftriangles; ++i)
{
Triangle tri;
tri.set(cos[3 * i], cos[3 * i + 1], cos[3 * i + 2]);
triangles.push_back(tri);
}
triangulateiofree(&out, 0);
triangulateiofree(&in, 1);
return true;
}
};
有了这样的三角化类,就可以将不规则多边形(如凹多边形,带内洞多边形)转换为三角形,然后将三角形传递到VBO中。
std::vector< std::vector<Coor> > polys;
int32_t idx = 0;
for (int32_t i = 0; i < pc; ++i)
{
std::vector<Coor> pts;
for (int32_t j = 0; j < ptsc[i]; ++j)
{
Coor cc;
cc.x = pco[idx].x - m_vo.s_left;
cc.y = pco[idx].y - m_vo.s_bottom;
cc.z = 0.f;
pts.push_back(cc);
idx++;
}
polys.push_back(pts);
}
{
WithInnerTriangulation wit;
std::vector<Triangle> triangles;
wit.transform(polys, triangles);
size_t tc = triangles.size();
if (tc)
{
auto tri = triangles.begin();
while (tri != triangles.end())
{
PointF cc;
cc.z = m_vo.s_zIndex;
cc.x = tri->cos[0].x; cc.y = tri->cos[0].y;
m_vo.polyBuffer.cos.push_back(cc);
cc.x = tri->cos[1].x; cc.y = tri->cos[1].y;
m_vo.polyBuffer.cos.push_back(cc);
cc.x = tri->cos[2].x; cc.y = tri->cos[2].y;
m_vo.polyBuffer.cos.push_back(cc);
m_vo.polyBuffer.cols.push_back(colF);
m_vo.polyBuffer.cols.push_back(colF);
m_vo.polyBuffer.cols.push_back(colF);
++tri;
}
}
}
这样多边形就能够渲染出来了!
相关文章推荐
- 跨平台二维绘图程序(三)——VAO&VBO
- 跨平台二维绘图程序(二)——着色器shader
- 跨平台二维绘图程序(一)——前奏
- 利用OFFICE 2003 OWC 绘图控件在.NET平台下实现数据图表的绘制
- QT二维图形的绘制(类的介绍与绘图实例)
- OpenCv学习笔记(七)---OpenCv中的基本绘图函数,圆,椭圆,线段,矩形,多边形的绘制(1)
- 黄聪:C#窗体程序OpenGL绘制立方体多边形旋转示例教程(VS2008,Winform)
- 黄聪:C#窗体程序OpenGL绘制立方体多边形旋转示例教程(VS2008,Winform)
- 简单的QT绘图程序(把全部的点都记录下来,然后在paintEvent里使用drawLine函数进行绘制,貌似效率很低。。。)
- OpenCv学习笔记(七)---OpenCv中的基本绘图函数,圆,椭圆,线段,矩形,多边形的绘制(2)--提高篇
- Cocos2d-x常用功能-绘图API:绘制点、线条、圆形、矩形、多边形
- 温度场有限容积法程序入门之六:后处理.isoline的绘制.基于Flash.Display.Graphics绘图API
- 二维绘图引擎:圆、半圆、弧线绘制
- html5 canvas绘图-多边形的绘制
- 二维光子晶体带隙绘制程序_平面波展开法(最终版)
- 简单的QT绘图程序(把全部的点都记录下来,然后在paintEvent里使用drawLine函数进行绘制,貌似效率很低。。。)
- 基于MFC串口编程和曲线图绘制(visual studio2008,Teechart绘图控件)的程序总结
- Python中Turtle绘图函数-绘制时钟程序
- OpenGL(一)二维图形的绘制:图元、多边形、颜色插值、文本、查询与错误、状态的保存
- 黄聪:C#窗体程序OpenGL绘制立方体多边形旋转示例教程(VS2008,Winform)