首页 技术 正文
技术 2022年11月21日
0 收藏 806 点赞 3,512 浏览 2809 个字

clipper

sourceforge官网:http://sourceforge.net/projects/polyclipping/

1. 版本号差异

之前project里面使用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顶点顺序,效果图例如以下:

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,999
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,511
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,357
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,140
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,770
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,848