一个算法充/放气(抵消,缓冲)多边形
-
12-09-2019 - |
题
我怎么会"膨胀"的一面?这就是我想要做的事类似于这样的:
要求是,新的(膨胀)面的边缘点都是在同一定距离的旧(原)面的(在本例中的图片,他们不是,自那时以来,它就会有使用弧膨胀的顶点,但是让我们忘了,现在)).
数学期我在寻找什么是实际上 向内/外侧面抵消.+1到巴林特指出了这一点。替代性命名 多边缓冲.
结果我的搜索:
这里有一些链接:
其他提示
我听起来就像你想要什么是:
- 开始在一个顶点,面对抗沿顺时针的一个相邻的边缘。
- 代替边缘有一个新的、平行的边放置在距离
d
向"留"的旧的。 - 重复为所有的边缘。
- 找到交叉点的新的边缘,获得新的顶点。
- 检测,如果你已经成为一个交叉面,并决定该怎么做的。或许添加一个新的顶点,在过境点和摆脱一些旧的。我不确定是否有一个更好的方法以检测,这不仅仅是比较每一个对非相邻的边缘看到,如果他们的交叉点在于两者之间的对折点。
得到的面在于在所要求的距离从旧的多边形"远远不够"从顶点。附近的一个顶点,该集点的距离 d
从旧面是,正如你所说,不是一个面,因此要求说明不能实现。
我不知道,如果这种算法有一个名字,例码网络,或者一个魔王的优化,但我觉得这描述了你想要什么。
对于这些类型的事我通常会使用 执照的正规会计事务所.为了示范的目的,我创造了这个 jsFiddle 使用 JSTS (JavaScript港口执照的正规会计事务所).你只需要转换的坐标你必须JSTS坐标:
function vectorCoordinates2JTS (polygon) {
var coordinates = [];
for (var i = 0; i < polygon.length; i++) {
coordinates.push(new jsts.geom.Coordinate(polygon[i].x, polygon[i].y));
}
return coordinates;
}
结果是这样的:
额外的信息:我通常使用这种类型的充/放气(一个小小的修改我的目的),用于设置边界半径上面绘制的地图(用小册子或谷歌地图)。你只要转换(纬度、液化天然气)对JSTS坐标和其他的一切都是相同的。例如:
每个线应分的飞机到"内部"和"概述";你可以找到这个了使用通常的内产品的方法。
将所有的线外的一些距离。
考虑到所有对邻线(线、无线段),发现交汇点。这些都是新的顶点。
清理新的顶点,通过删除任何交叉部分。-我们有一些情况下这里
(a)案例1:
0--7 4--3
| | | |
| 6--5 |
| |
1--------2
如果你把这个接一个,你得到了这一点:
0----a----3
| | |
| | |
| b |
| |
| |
1---------2
7和4的重叠..如果你看到这个,你删除这点和所有有点之间。
(b)情况2
0--7 4--3
| | | |
| 6--5 |
| |
1--------2
如果你把它通过两个,你得到这个:
0----47----3
| || |
| || |
| || |
| 56 |
| |
| |
| |
1----------2
要解决这一问题,对于每个分段的路线,你要检查它是否重叠与后一段。
(c)的情况3
4--3
0--X9 | |
| 78 | |
| 6--5 |
| |
1--------2
花费1。这是一个更普遍的情况下对案1中。
(d)的情况4
同case3,但花费的两个。
实际上,如果你能处理的情况下4.所有其他情况下,都是特殊情况,它与一些线或折点重叠。
要做到4的情况下,则保持一堆顶点..你把当你找到线的重叠与后一行,把它当你得到后者线。-就像你做什么在凸船体。
这里是一个替代解决方案中,看到如果你这样更好。
做一个 三角测量, 它不必是德洛内--的任何三角测量会怎么做。
膨胀每个三角形--这应该是微不足道的。如果存储三角形的抗顺时针的顺序,只要移动线路的右手边和做交叉口。
把它们合并使用改进的 Weiler-Atherton幅算法
在地理信息系统世界,一个使用负缓冲这个任务:http://www-users.cs.umn.edu/~npramod/enc_pdf.pdf
的 执照的正规会计事务所图书馆 应该为你做这个。请参阅文件的缓冲器操作: http://tsusiatsoftware.net/jts/javadoc/com/vividsolutions/jts/operation/buffer/package-summary.html
对于一个粗略的概述,另见开发商指南:http://www.vividsolutions.com/jts/bin/JTS%20Developer%20Guide.pdf
大感谢安格斯*约翰逊为他的帆船库。有很好的代码样做的剪切东西的帆船主页 http://www.angusj.com/delphi/clipper.php#code 但是我没有看到一个实例对于面抵消。所以我想这也许是使用对于个人,如果我后我的代码:
public static List<Point> GetOffsetPolygon(List<Point> originalPath, double offset)
{
List<Point> resultOffsetPath = new List<Point>();
List<ClipperLib.IntPoint> polygon = new List<ClipperLib.IntPoint>();
foreach (var point in originalPath)
{
polygon.Add(new ClipperLib.IntPoint(point.X, point.Y));
}
ClipperLib.ClipperOffset co = new ClipperLib.ClipperOffset();
co.AddPath(polygon, ClipperLib.JoinType.jtRound, ClipperLib.EndType.etClosedPolygon);
List<List<ClipperLib.IntPoint>> solution = new List<List<ClipperLib.IntPoint>>();
co.Execute(ref solution, offset);
foreach (var offsetPath in solution)
{
foreach (var offsetPathPoint in offsetPath)
{
resultOffsetPath.Add(new Point(Convert.ToInt32(offsetPathPoint.X), Convert.ToInt32(offsetPathPoint.Y)));
}
}
return resultOffsetPath;
}
另一个选择是使用 提升::多边形 -该文件有所欠缺,但你应该找到方法 resize
和 bloat
, 和也超载 +=
操作员,这实际上实现缓冲。因此,例如尺寸增大的多边(或一组多边形)通过一些值可以作为简单的:
poly += 2; // buffer polygon by 2
根据咨询意见@JoshO布赖恩,它会出现的 rGeos
包在 R
语言实现了这种算法。看看 rGeos::gBuffer
.
有一对夫妇的图书馆一个可以使用(也可用于3D数据集的).
- https://github.com/otherlab/openmesh
- https://github.com/alecjacobson/nested_cages
- http://homepage.tudelft.nl/h05k3/Projects/MeshThickeningProj.htm
其中一个还可以找到相应的出版物,这些图书馆以理解的算法更详细的说明。
最后一个拥有最少的依赖关系,是独立的,并可以阅读。obj文件。
最良好的祝愿, 斯蒂芬
我使用简单几何形状:向量和/或三角
在每一个角落查找中的矢量,以及中期角度。中矢量的算术平均值的两个单位矢量定义的边缘的角落。中期角度是一半的角度定义的边缘。
如果你需要扩大(或协定)多边形数额的d从各个边缘;你应该出去(在)过量d/sin(midAngle)获得新的角点。
重复,这对于所有角落
***以小心你的方向。让逆时针方向测试使用了三个指定的角落;要找出哪方式是出,或在。