bor*_*ero 9 algorithm polygon swift
我正在尝试确定一个点是否位于多边形内部.我从这个网站使用以下(用于Swift修改)算法:
func contains(polygon: [Point], test: Point) -> Bool {
let count = polygon.count
var i: Int, j: Int
var contains = false
for (i = 0, j = count - 1; i < count; j = i++) {
if ( ((polygon[i].y >= test.y) != (polygon[j].y >= test.y)) &&
(test.x <= (polygon[j].x - polygon[i].x) * (test.y - polygon[i].y) /
(polygon[j].y - polygon[i].y) + polygon[i].x) ) {
contains = !contains;
}
}
return contains;
}
Run Code Online (Sandbox Code Playgroud)
然而,具有以下坐标一个简单的多边形时:(x: 0, y: 40), (x: 0, y: 0), (x: 20, y: 0), (x: 20, y: 20), (x: 40, y: 20), (x: 40, y: 40),并检查点(x: 30, y: 20)作为IF语句计算结果是真实的true时候i和j5个和4个((x: 40, y: 40)和(x: 40, y: 20)),尽管点仅位于的边界多边形.该函数应该实际上只评估true,如果该点确实位于中的多边形.感谢您对算法的任何帮助或改进/调整!
Duy*_*Hoa 11
如果这是针对iOS应用程序,请将您的多边形转换为UIBezierPath,然后使用函数containtsPoint()验证您的点是否位于bezierpath
示例(iOS):
func contains(polygon: [CGPoint], test: CGPoint) -> Bool {
if polygon.count <= 1 {
return false //or if first point = test -> return true
}
var p = UIBezierPath()
let firstPoint = polygon[0] as CGPoint
p.moveToPoint(firstPoint)
for index in 1...polygon.count-1 {
p.addLineToPoint(polygon[index] as CGPoint)
}
p.closePath()
return p.containsPoint(test)
}
Run Code Online (Sandbox Code Playgroud)
也适合我,所以我不知道问题出在哪里
我还做了一个修改后的修改版本来使用swift迭代器:
func contains(polygon: [Point], test: Point) -> Bool {
var pJ=polygon.last!
var contains = false
for pI in polygon {
if ( ((pI.y >= test.y) != (pJ.y >= test.y)) &&
(test.x <= (pJ.x - pI.x) * (test.y - pI.y) / (pJ.y - pI.y) + pI.x) ){
contains = !contains
}
pJ=pI
}
return contains
}
Run Code Online (Sandbox Code Playgroud)
以下是您在游乐场中使用数组示例的结果:
contains(poly,Point(x:40,y:40)) -> true
contains(poly,Point(x:30,y:20)) -> false
contains(poly,Point(x:40,y:20)) -> true
contains(poly,Point(x:1,y:1)) -> true
Run Code Online (Sandbox Code Playgroud)
小智 6
extension MKPolygon {
func contain(coor: CLLocationCoordinate2D) -> Bool {
let polygonRenderer = MKPolygonRenderer(polygon: self)
let currentMapPoint: MKMapPoint = MKMapPointForCoordinate(coor)
let polygonViewPoint: CGPoint = polygonRenderer.point(for: currentMapPoint)
return polygonRenderer.path.contains(polygonViewPoint)
}
}
Run Code Online (Sandbox Code Playgroud)
这是 PNPoly 算法的改进实现。我用过它,效果很好。
func isPointInsidePolygon(polygon: [CGPoint], test:CGPoint) -> Bool {
var i:Int, j:Int = polygon.count - 1
var contains = false
for (i = 0; i < polygon.count; i++) {
if (((polygon[i].y < test.y && polygon[j].y >= test.y) || (polygon[j].y < test.y && polygon[i].y >= test.y))
&& (polygon[i].x <= test.x || polygon[j].x <= test.x)) {
contains ^= (polygon[i].x + (test.y - polygon[i].y) / (polygon[j].y - polygon[i].y) * (polygon[j].x - polygon[i].x) < test.x)
}
j = i
}
return contains
}
Run Code Online (Sandbox Code Playgroud)
进一步查询检查:http : //alienryderflex.com/polygon/
这是javascript代码(很容易理解,你可以在swift上重写)。它对我来说非常有效,几乎 100%,即非常精确。
您的解决方案精度较差。
function pointIsInPoly(v, polygon) {
var edge_error = 1.192092896e-07; // epsilon i.e ~0.000000192
var x = 0;
var y = 1;
var i, j;
var r = false;
for (i = 0, j = polygon.length - 1; i < polygon.length; j = i++)
{
var pi = polygon[i];
var pj = polygon[j];
if (Math.abs(pi[y] - pj[y]) <= edge_error && Math.abs(pj[y] - v[y]) <= edge_error && (pi[x] >= v[x]) != (pj[x] >= v[x]))
{
return true;
}
if ((pi[y] > v[y]) != (pj[y] > v[y]))
{
var c = (pj[x] - pi[x]) * (v[y] - pi[y]) / (pj[y] - pi[y]) + pi[x];
if (Math.abs(v[x] - c) <= edge_error)
{
return true;
}
if (v[x] < c)
{
r = !r;
}
}
}
return r;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5177 次 |
| 最近记录: |