二维矢量图形对象的拾取在矢量绘图软件中是一个常用的操作,非精准的拾取很容易实现,直接计算Geometry的Bound即可,但是这样做未免有点太粗糙了,显得好没专业水准!要体现出专业的绘图水准,我们必须做到精准的拾取。这里介绍一种采用Geos缓冲分析和gdi区域结合的方法。这里只介绍多边形的精准拾取。
首先定义以下这里精准拾取的含义,所谓精准拾取,也就是只有在鼠标点击图形覆盖到的屏幕像素范围时才算作有效的拾取;如下图
只有点击到红色的区域时,才算拾取到该图形。因此我们考虑到Pen的宽度和样式,特别是JoinStyle和EndCapStyle。
GDI的区域是一个不规则的封闭范围,它提供的有PTInRegion函数来判断某点是否在该区域内,因此只要我们能够计算的到上述图形的区域,也就很容易进行精准拾取。但是只知道图形的坐标数据和画笔信息怎么计算得到一个区域呢?
很容易想到求该图形的点串数据的两条距离为画笔宽的平行线,但是自己去写这个算法有点费劲,还好我们有开源的Geos,我们要求的平行线在几何操作里其实就是缓冲区分析,通过Geos提供BufferOp操作,很轻松求的了我们需要的边界数据,这样我们就可以根据这个边界数据去创建区域,然后去做点击测试了。
这里需要注意的是,Geos考虑了几何图形复杂的拓扑关系,对于不规则的多边形,计算得到的Geometry可能是错的,比如下图情况
该图使用GDI的Polygon绘制出的无填充的多边形,如果直接调用Polygon类型的Geometry去做缓冲,那么的到的可能只有该图形的下半身,这是Geos处理后的结果,但这不是我们想要的,因此我们还不能直接掉用Geos的BufferOp::getResultGeometry。深入分析Geos的缓冲区分析算法,我们找到了一个替代的解决方案OffsetCurveBuilder,它的方法其实就是我们要找的平行线算法,而且考虑了画笔的样式,我们只需要根据我们的Geomerty类型来调用响应的get*Curve()函数即可。
对于上述不规则多边形,我们可能需要调用两次getRingCurve函数,分别求的内环和外环,在构建区域时注意内环和外环的点串顺序是反的才能得到正确的区域。
二维矢量图形对象拾取的一种方法,布布扣,bubuko.com
原文地址:http://www.cnblogs.com/zzugis/p/3825142.html