[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[文本处理] 批处理用怎么实现快速判断点与多边形关系呢

多边形顶点数据如下:
A
96.802,87.23
89.094,78.623
92.268,64.808
115.391,61.863
124.913,77.265
115.845,90.174
102.696,92.439
96.802,87.23
待判断的点

如果点在多边形外就保存下来>>c.txt
如果点在多边形内或者多边形边上就剔除它>>d.txt
基本思路是用射线法,计算以待判断点(yt,xt)为起点,
平行向右或者向上发射射线,依次与每条多边形的边发射,判断有没有交点,有偶数个交点包括0,就说明在多边形内,那么这一行数据>>d.txt。奇数个就>>c.txt
当某条边的两个顶点x坐标 x(1),x(2)满足如下条件时
If xt >= x1 And xt < x2 or xt <= x1 And xt > x2 then  ::就是说要依次找到相交的可能性,再去判断下面的
set yt=yi+(y2-y1)(xt-x1)/(x2-x1)
if yt > y0 Then Ncross = Ncross + 1    ::如果有交点,交点数Ncross就+1
每个点遍历每条边,if Ncross%2=0,>>d.txt
else if Ncross%2=1,>>c.txt
因为需要判断的点数据量非常大(有几百万个),用vb还可以做出来,但是速度太慢了,最近感受到了gawk的速度,想用gawk或者sed去解决,但是又涉及到二维数组,头大,哪位大神能帮帮忙

TOP

回复 44# 523066680
  谢谢啦,我慢慢研究一下

TOP

本帖最后由 523066680 于 2014-8-20 23:10 编辑

Crlf确定加的是技术分吗……
这几段码出来我就可以作为原创内容发到各个文档网站赚点积分方便以后用吧,大概这么想的。

TOP

判断是否为逆时针的VBS实例贴出来啦,我也算图文都弄上来了,其他的楼主自己折腾。
──────────────────────────┐
                                                    │
msgbox triangleIsCCW(1.0, 0.0, 10.0, 3.0, 0.0, 0.0) │
                                                    │
msgbox triangleIsCCW(10.0, 3.0, 1.0, 0.0, 0.0, 0.0) │
                                                    │
function Cross(x0,y0, x1,y1)                        │
        Cross = (x0 * y1) - (y0 * x1)               │
end function                                        │
                                                    │
function triangleIsCCW(x0, y0, x1, y1, x2, y2)      │
        result = Cross(x1-x0, y1-y0, x2-x0, y2-y0)  │
        if (result > 0) then                        │
                triangleIsCCW=True                  │
        else                                        │
                triangleIsCCW=False                 │
        end if                                      │
end function                                        │
──────────────────────────┘
1

评分人数

    • CrLf: 你真的好闲...技术 + 1

TOP

点与凸多边形之间的测试

回复 40# tommytangtang

一下内容是原文照抄(有小小修改;我终于也沦为搬运工了啊……)

点与凸多边形之间的测试
  假设n边凸多边形顶点V0, V1, …,Vn-1 呈逆时针排列。通过测试顶点P与方向直线V0、Vk(k=n/2)
的位置关系,可将多边形的测试范围缩至一半。该过程重复执行并相应地调整K值,直至发现顶点P位于多
边形的外部或位于有向直线V0Vk
~ V0Vk+1之间。对于后者,若顶点P位于有向直线VkVk+1的左侧(呈
逆时针排列),则其位于多边形内部。
  以一个8条边的凸多边形作为例。首先,顶点P针对直线V0V4进行测试,并将多边形顶点范围降至一半。
由于顶点P位于A的左侧,所以丢弃多边形的右半部分,并继续对左半部分执行相同处。下一步,在顶点P与
直线B之间执行测试,最后对直线C进行测试,此时,顶点P位于邻接顶点构成的两条直线之间。最后,顶点
P与该邻接顶点构成的直线进行测试。
  测试结果为:顶点P位于多边形内部。




          [attach]7612[/attach]

  图为:凸多边形顶点的二分搜索使得点P的包含测试的时间复杂度为O(log n)(这里测试了4条边:A~D


  另外,预计算函数TriangleIsCCW()将计算三角形顶点是否为逆时针方向排列。该测试的高效实现

方法如下列代码所示:


──────────────────────────────────────────┐
    // Test if point p lies inside ccw-specified convex n-gon given by vertices v[]
    int PointInConvexPolygon(Point p, int n, Point v[])                             │
    {                                                                               │
        // Do binary search over polygon vertices to find the fan triangle          │
        // (v[0], v[low], v[high]) the point p lies within the near sides of        │
        int low = 0, high = n;                                                      │
        do {                                                                        │
            int mid = (low + high) / 2;                                             │
            if (TriangleIsCCW(v[0], v[mid], p))                                     │
                low = mid;                                                          │
            else                                                                    │
                high = mid;                                                         │
        } while (low + 1 < high);                                                   │
                                                                                    │
        // If point outside last (or first) edge, then it is not inside the n-gon   │
        if (low == 0 || high == n) return 0;                                        │
                                                                                    │
        // p is inside the polygon if it is left of                                 │
        // the directed edge from v[low] to v[high]                                 │
        return TriangleIsCCW(v[low], v[high], p);                                   │
    }                                                                               │
──────────────────────────────────────────┘




  该点包含测试方法类似[Preparata85]中所描述的相关算法结构,其中n边多边形内部也存在一个与

此处的顶点V0对应。


---------以下内容可能造成不适,请[跳过]或者[对上面内容进行消化]后再访问--------


   该算法通过多边形的一个原点和其他顶点,对多边形进行划分(二分),通过TriangleIsCCW()函数

逐渐找到最靠近点P的两个边界,在示例中最后找到为:V0->V5 和 V0->V6 。这个过程手工演算一

次就知道原理了。

  最后一步 return TriangleIsCCW(v[low], v[high], p); 即为判断:如果V5->V6->P 呈逆时针顺序,

则点P在多边形内部。

TriangleIsCCW() 函数判断传入的三个顶点数据是否呈逆时针排列,书中没有给出,但是在网上找到:
─────────────────────────────┐
    template<class T>                                     │
    T Cross(T x0, T y0, T x1, T y1) {                     │
        //|x0 y0| = |a b|                                 │
        //|x1 y1|   |c d|                                 │
                                                          │
        //ad * bc                                         │
        //x0 * y1 - x1 * y0                               │
                                                          │
        return (x0 * y1) - (y0 * x1);                     │
    }                                                     │
                                                          │
    template<class T>                                     │
    bool triangleIsCCW(                                   │
        T x0, T y0,                                       │
        T x1, T y1,                                       │
        T x2, T y2) {                                     │
        auto cross = (Cross<T>(x1-x0,y1-y0,x2-x0,y2-y0)); │
        return cross > 0;                                 │
    }                                                     │
─────────────────────────────┘

  原理就是对传入的三个顶点坐标进行向量运算(以P为原点,计算出另外两个点

的相对坐标,视为向量a、b,计算这两个向量的向量积(cross product))

(高等数学第一章有介绍这个计算和性质,或者在网上搜索:叉积……)

计算向量积得到的是垂直于a和b所在平面的向量V,遵循右手法则:右手握住V

向量(垂直于a和b),手指从a向b环绕,大拇指的方向和向量方向一致。

也就是如果a-> b->原点p 是逆时针方向则V>0 ,是反方向则V<0,如果ab平

行或者其中一方为0,则V=0


                [attach]7613[/attach]

TOP

回复 41# 523066680

真的没看懂,要翻译好难,求助版版

TOP

本帖最后由 523066680 于 2014-8-20 01:03 编辑

回复 40# tommytangtang

现在凸多边形和凹多边形的解决方案都有了, 你会VB的话就把函数照抄,转化为VB就可以了。
(话说就单单从文本读取数据,VB比gawk慢是真的吗?)

今天略忙,忘了分析算法了。太晚了,闪!

TOP

C不懂啊,这个算是解决了吗?

TOP

回复 30# 523066680


突然发现我也是两个太阳...话说这里为什么没有列出版主用户:http://bbs.bathome.net/memcp.php?action=usergroups

你看看在线时间下面那一排太阳吧

TOP

卧槽,你们这群技术宅...Holy high

TOP

回复 31# tommytangtang

我测试了一个C代码
2

评分人数

TOP

回复 35# CrLf


    仔细想了想,这两种情况可能要先用算法计算后区分,要单独去判断,感觉越来越复杂了。。。

TOP

回复 31# tommytangtang


    这可以通过判断交叉点 x 是否在 [x1,x2) 内来区分,但仔细想了一下,射线法还有两个问题比较郁闷:
  1. 1、出现与射线平行的边线时,在线上的点应视为不在区域内才能避免被多次计算
  2. 2、有两个角点重合时,会计算两次而导致误判
复制代码
我原来的代码确实有问题,想太简单了。为了不误导人,那帖还是删了为好

TOP

回复 32# 523066680
    原本是感觉到了gawk在处理文本的速度上的优势才发这个贴的,c完全没有自己编过,汗…算了,多学点吧。

TOP

返回列表