clipper库使用的一些心得
来源:互联网 发布:linux shell替换字符串 编辑:程序博客网 时间:2024/05/17 02:53
clipper
sourceforge官网:http://sourceforge.net/projects/polyclipping/
1. 版本差异
之前工程里面使用4.8.6,最近升级到最新版本6.2.1,接口层面有点差别:
老版本使用Polygon概念,最新版本用Path代替了Polygon,对用的Polygons用Paths代替,Clipper::AddPath的时候还需要制定是否封闭。
2. 注意数据类型
一个测试,回字上半部分和下半部分,两半部分进行合并,但是输出结果总是不对:
void transform_array_to_path(int* arr, int size, ClipperLib::Path& path, int scale = 1){for (int i = 0; i < size; i += 2){path.push_back(ClipperLib::IntPoint(arr[i] * scale, arr[i + 1] * scale));}}void ClipperTest::merge_case(){using namespace ClipperLib;Clipper union_worker;Paths solution;Path positive_path;{int points[] = { 1, 1, 1, 0, 2, 0, 2, 2, -2, 2, -2, 0, -1, 0, -1, 1 };transform_array_to_path(points, sizeof(points) / sizeof(points[0]), positive_path, 10);}union_worker.AddPath(positive_path, ClipperLib::ptSubject, true);Path negative_path;{int points[] = { 1, -1, 1, 0, 2, 0, 2, -2, -2, -2, -2, 0, -1, 0, -1, -1 };transform_array_to_path(points, sizeof(points) / sizeof(points[0]), negative_path, 10);}union_worker.AddPath(negative_path, ClipperLib::ptClip, true);union_worker.Execute(ClipperLib::ctUnion, solution, pftEvenOdd, pftEvenOdd);for (int k = 0; k < solution.size(); k++){Path& path = solution[k];printf("[ %dth ] : ", k + 1);for (int t = 0; t < path.size(); t++){printf("%d,%d ", path[t].X, path[t].Y);} printf("\n");}}合并后的结果输出:
// [1th] : -10, -1 - 10, -1 10, 0 10, 0// [2th] : -20, -1 - 20, -1 20, 0 20, 0结果百思不得其解,结果怎么是一个线段了,莫名其妙???正确结果如下图,合并后是一个回字型。
不断地跟clipper自带的demo程序比对,终于发现了问题所在:问题出在Clipper内部的IntPoint,如果没有定义宏use_int32,采用的是long long存储顶点XY值,而上面code中printf是%d,使用%lld或者cout 就没问题了。坑啊。。。
2. 带洞多边形和多边形填充规则
clipper中定义了,EvenOdd,NonZero,Positive,Negative四中填充规则。对应参考OpenGL红皮书上关于多边形填充规则的说明:http://glprogramming.com/red/chapter11.html
多边形填充规则的使用引入了一个环绕数(Winding Numbers)和环绕规则(Winding Rules)的概念。环绕规则一般CCW为正,CW为负。环绕数和填充规则的示例如下图:
为了表示一个带洞的多边形,例如上图中的回字型,需要内外两个路径表示,那么需要注意顶点的存储顺序吗? 这个问题的答案是,取决于多边形的填充规则。如果使用EvenOdd规则,则不用关心顶点的存储顺序。因为:第一圈为+1/-1,一定是奇数,然后加1或者减1,结果都是偶数,然后再加1或减1结果一定是奇数。
有了这个认识,我们写个测试例子,一个回字,跟一个四边形就行融合,Subject是一个Paths,包含两个Path表示,内外圈顺序无关;Clip是一个Path,进行合并的结果包含两个Path。
void ClipperTest::polygon_with_hole_merge_test(){using namespace ClipperLib;Path path1_outer;Path path1_inner;{int outer[] = { -2, -2, 2, -2, 2, 2, -2, 2 };int inner[] = { -1, -1, 1, -1, 1, 1, -1, 1 };transform_array_to_path(outer, sizeof(outer)/sizeof(outer[0]), path1_outer);transform_array_to_path(inner, sizeof(inner)/sizeof(inner[0]), path1_inner);}Path path2;{int outer[] = { 2, 2, 3, 2, 3, -2, 2, -2 };transform_array_to_path(outer, sizeof(outer) / sizeof(outer[0]), path2);}Paths sub_poly;sub_poly.push_back(path1_outer);sub_poly.push_back(path1_inner);Clipper union_worker;union_worker.AddPaths(sub_poly, ptSubject, true);union_worker.AddPath(path2, ptClip, true);Paths solution;union_worker.Execute(ClipperLib::ctUnion, solution, pftEvenOdd, pftEvenOdd);for (int k = 0; k < solution.size(); k++){Path& path = solution[k];printf("[ %dth ] : ", k + 1);for (int t = 0; t < path.size(); t++){// printf("%d,%d ", path[t].X, path[t].Y);cout << path[t].X << "," << path[t].Y << " ";} printf("\n");}}不用care顶点顺序,效果图如下:
0 0
- clipper库使用的一些心得
- 使用 Clipper 库的一些问题记录
- libcurl库的使用的一些心得
- 使用 7230的一些心得
- TreeView使用的一些心得
- 使用JTAG的一些心得
- BerkeleyDB使用的一些心得
- 使用JTAG的一些心得
- Siverlight的一些使用心得
- thickbox的一些使用心得
- eclipse 的一些使用心得
- cocostudio使用的一些心得
- Sqoop的一些使用心得
- hiredis的一些使用心得
- 使用HighChart的一些心得
- Neo4j 的一些使用心得
- 使用pygame的一些心得
- MySql的一些使用心得
- Python print 格式化输出
- Java开发者值得关注的7款新工具
- 有关于图片组合成视频的功能
- FFMPEG 关于对时间戳转换的理解
- 公司促销礼品送什么好
- clipper库使用的一些心得
- 半透明渲染新技术摘录
- python之MySQLdb模块
- Ubuntu下安装Python GUI开发包 wxpython
- android的消息处理机制(图+源码分析)——Looper,Handler,Message
- 使用PullToRefresh实现下拉刷新和上拉加载
- jQuery Mobile 移动网站开发之日期控件Mobiscroll 2.5 使用说明
- Android开发笔记之:Handler Runnable与Thread的区别详解
- 《数据结构》第四章 字符串和多维数组 问题收集站