[从头学数学] 第282节 [计算几何] 相邻边和相邻点

来源:互联网 发布:每次人口普查的数据 编辑:程序博客网 时间:2024/05/18 14:26
剧情提要:
阿伟看到了一本比较有趣的书,是关于《计算几何》的,2008年由北清派出版。很好奇
它里面讲了些什么,就来看看啦。


正剧开始:
星历2016年09月28日 15:47:30, 银河系厄尔斯星球中华帝国江南行省。

[工程师阿伟]正在和[机器小伟]一起研究[计算几何]]。






# 点和边的位置关系


<span style="font-size:18px;">#>>> 点在线段[[2.4, 5.4], [6, 9]]的Nevermind边扫描线与线段交点: []点在线段[[0.8, 3.8], [2.4, 5.4]]的Right边扫描线与线段交点: [1.47, 4.47]点在线段[[1.33, 3], [0.8, 3.8]]的Nevermind边扫描线与线段交点: []点在线段[[1.33, 3], [2, 3]]的Nevermind边扫描线与线段交点: []点在线段[[2, 3], [6, 3]]的Nevermind边扫描线与线段交点: []点在线段[[6, 3], [6, 3.86]]的Nevermind边扫描线与线段交点: []点在线段[[6, 3.86], [3.33, 5]]的Left边扫描线与线段交点: [4.57, 4.47]点在线段[[3.33, 5], [6, 9]]的Nevermind边扫描线与线段交点: []>>> 点在线段[[2.4, 5.4], [6, 9]]的Left边扫描线与线段交点: [2.49, 5.49]点在线段[[2.4, 5.4], [-6, 9]]的Left边扫描线与线段交点: [2.19, 5.49]点在线段[[-0.37, 2.56], [-6, 9]]的Right边扫描线与线段交点: [-2.93, 5.49]点在线段[[-0.37, 2.56], [0, 3]]的Nevermind边扫描线与线段交点: []点在线段[[0, 3], [1.33, 3]]的Nevermind边扫描线与线段交点: []点在线段[[1.33, 3], [2, 3]]的Nevermind边扫描线与线段交点: []点在线段[[2, 3], [3.33, 5]]的Nevermind边扫描线与线段交点: []点在线段[[3.33, 5], [6, 9]]的Left边扫描线与线段交点: [3.66, 5.49]#三个点的叉积def crossProduct(P1, P2, P3):    x1, y1, x2, y2, x3, y3 = P1[0], P1[1], P2[0], P2[1], P3[0], P3[1];    #    # 1   1   1    # x_1 x_2 x_3    # y_1 y_2 y_3    #    #逆时针结果为正,顺时针为负    return round((x1*y2-x2*y1)-(x1*y3-x3*y1)+(x2*y3-x3*y2), 3);#判断点在边的左边还是右边def judgePointAgainstEdgePosition(seg, point):    #传入SegLine类型和Point类型,这样方便比较    #SegLine是以y优先x其次由小大大排序的,终端点按排序规则大于起始端点    pValue = point.value();    sValue = seg.value();    x0, y0, x1, y1, x2, y2 = pValue[0], pValue[1], sValue[0][0], sValue[0][1],\                             sValue[1][0], sValue[1][1];    #点的y值要在线段两个端点的y值中间,可以等于    if (y0 >= y1 and y0 <= y2):        cross = crossProduct(pValue, sValue[0], sValue[1]);        if (cross > 0):            #点在线段的左边            if (y1 < y0):                return 'Left';        elif (cross < 0):            #点在线段的右边            if (y2 > y0):                return 'Right';    return 'Nevermind';#获取扫描线与线段的交点#y方向的扫描线为平行于x轴且y值为某一定值的直线def calcScanLineCrosspoint(seg, point):    #传入SegLine类型和Point类型,这样方便比较    #SegLine是以y优先x其次由小大大排序的,终端点按排序规则大于起始端点    pValue = point.value();    sValue = seg.value();    x0, y0, x1, y1, x2, y2 = pValue[0], pValue[1], sValue[0][0], sValue[0][1],\                             sValue[1][0], sValue[1][1];    #点的y值要在线段两个端点的y值中间,可以等于    if (y0 >= y1 and y0 <= y2):        if y0 == y1:            return sValue[0];        elif y0 == y2:            return sValue[1];        else:            x = x1 + (y0 - y1)/(y2 - y1)*(x2-x1);            return [round(x, 2), y0];    return [];def tmp5():    path = [[[6, 9], [2.4, 5.4], [0.8, 3.8], [1.33, 3], [2, 3], [6, 3], [6, 3.86], [3.33, 5], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [1.33, 3], [2, 3], [3.33, 5], [6, 3.86], [8, 3], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.5, 1.5], [1.78, 2.33], [2, 3], [3.33, 5], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.33, 3], [1.78, 2.33], [2, 3], [3.33, 5], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.33, 3], [2, 3], [6, 3], [6, 3.86], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.33, 3], [2, 3], [3.33, 5], [6, 3.86], [6, 9]], [[6, 9], [2.4, 5.4], [3.33, 5], [2, 3], [6, 3], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [2.4, 5.4], [3.33, 5], [6, 3.86], [6, 3], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [2.4, 5.4], [-6, 9], [-0.37, 2.56], [0, 3], [1.33, 3], [2, 3], [3.33, 5], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [1.78, 2.33], [3.67, -0.5], [4.29, 0.43], [6, 3], [6, 3.86], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [6, 3], [6, -3], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [6, 3], [6, -3], [8, -7], [8, 3], [6, 3.86], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [6, 3], [4.5, 0], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [3.33, 5], [6, 3.86], [6, 3], [6, -3], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [3.33, 5], [6, 3.86], [6, 3], [4.5, 0], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [4.29, 0.43], [4.5, 0], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [6, -3], [5.56, -3.33], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [6, -3], [5.67, -3.5], [5.35, -3.97], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [4.5, 0], [6, -3], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [4.5, 0], [4, -1], [6, -3], [8, -7], [8, 3], [6, 9]]]    len_path = len(path);    center = [[3.45, 4.47], [4.86, 5.51], [2.36, 4.5], [2.63, 4.92], [4.0, 5.0], [3.97, 5.51], [6.01, 2.42], [6.33, 2.21], [-0.28, 5.49], [4.29, 3.73], [6.17, 1.92], [6.07, 1.58], [6.08, 1.89], [6.53, 1.61], [6.39, 1.6], [6.68, 0.49], [6.95, 0.31], [6.92, 0.09], [6.71, 0.27], [6.62, 0.38]];    #第几条线段作为测试        n = 8;        len_path_0 = len(path[n]);    pCenter_0 = center[n];    for i in range(len_path_0-1):        seg = SegLine(path[n][i], path[n][i+1]);        p = Point(pCenter_0)        print('点在线段{0}的{1}边'.format(str(seg), judgePointAgainstEdgePosition(seg, p)));        print('扫描线与线段交点:', calcScanLineCrosspoint(seg, p));#</span>


#找某点的左、右邻居边


<span style="font-size:18px;">#>>> [SegLine([-0.37, 2.56], [-6, 9]), [-2.93, 5.49]][SegLine([2.4, 5.4], [-6, 9]), [2.19, 5.49]]    #找某点的左邻居边,也就是路径中处于给定点的左边,并且在y扫描线上最接近的那条边    def findLeftNearestEdge(self, point):        edge = None;        scanPoint = None;        len_ = len(self.path);        for i in range(len_):            seg = SegLine(self.path[i].value(), self.path[(i+1)%len_].value());            #点在边的右侧            if (judgePointAgainstEdgePosition(seg, point) == 'Right'):                if (edge == None):                    edge = seg;                    scanPoint = calcScanLineCrosspoint(seg, point);                else:                    a = calcScanLineCrosspoint(seg, point);                    #取扫描线的交点的x值                    if a[0] > scanPoint[0]:                        edge = seg;                        scanPoint = a;        return [edge, scanPoint];    #找某点的右邻居边,也就是路径中处于给定点的右边,并且在y扫描线上最接近的那条边    def findRightNearestEdge(self, point):        edge = None;        scanPoint = None;        len_ = len(self.path);        for i in range(len_):            seg = SegLine(self.path[i].value(), self.path[(i+1)%len_].value());            #点在边的左侧            if (judgePointAgainstEdgePosition(seg, point) == 'Left'):                if (edge == None):                    edge = seg;                    scanPoint = calcScanLineCrosspoint(seg, point);                else:                    a = calcScanLineCrosspoint(seg, point);                    #取扫描线的交点的x值                    if a[0] < scanPoint[0]:                        edge = seg;                        scanPoint = a;        return [edge, scanPoint];def tmp5():    path = [[[6, 9], [2.4, 5.4], [0.8, 3.8], [1.33, 3], [2, 3], [6, 3], [6, 3.86], [3.33, 5], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [1.33, 3], [2, 3], [3.33, 5], [6, 3.86], [8, 3], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.5, 1.5], [1.78, 2.33], [2, 3], [3.33, 5], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.33, 3], [1.78, 2.33], [2, 3], [3.33, 5], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.33, 3], [2, 3], [6, 3], [6, 3.86], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.33, 3], [2, 3], [3.33, 5], [6, 3.86], [6, 9]], [[6, 9], [2.4, 5.4], [3.33, 5], [2, 3], [6, 3], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [2.4, 5.4], [3.33, 5], [6, 3.86], [6, 3], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [2.4, 5.4], [-6, 9], [-0.37, 2.56], [0, 3], [1.33, 3], [2, 3], [3.33, 5], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [1.78, 2.33], [3.67, -0.5], [4.29, 0.43], [6, 3], [6, 3.86], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [6, 3], [6, -3], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [6, 3], [6, -3], [8, -7], [8, 3], [6, 3.86], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [6, 3], [4.5, 0], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [3.33, 5], [6, 3.86], [6, 3], [6, -3], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [3.33, 5], [6, 3.86], [6, 3], [4.5, 0], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [4.29, 0.43], [4.5, 0], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [6, -3], [5.56, -3.33], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [6, -3], [5.67, -3.5], [5.35, -3.97], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [4.5, 0], [6, -3], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [4.5, 0], [4, -1], [6, -3], [8, -7], [8, 3], [6, 9]]]    len_path = len(path);    center = [[3.45, 4.47], [4.86, 5.51], [2.36, 4.5], [2.63, 4.92], [4.0, 5.0], [3.97, 5.51], [6.01, 2.42], [6.33, 2.21], [-0.28, 5.49], [4.29, 3.73], [6.17, 1.92], [6.07, 1.58], [6.08, 1.89], [6.53, 1.61], [6.39, 1.6], [6.68, 0.49], [6.95, 0.31], [6.92, 0.09], [6.71, 0.27], [6.62, 0.38]];    #第几条线段作为测试        n = 8;        len_path_0 = len(path[n]);    pCenter_0 = Point(center[n]);    a = Path(path[n]);    print(a.findLeftNearestEdge(pCenter_0));    print(a.findRightNearestEdge(pCenter_0));#</span>

#找某点的上、下相邻点

<span style="font-size:18px;">#>>> [SegLine([-0.37, 2.56], [-6, 9]), [-2.93, 5.49]][SegLine([2.4, 5.4], [-6, 9]), [2.19, 5.49]][-6, 9][2.4, 5.4]>>>     #找某点的上兄弟点,这个点的y坐标大于给定点,    #并且处于该点的左、右邻居边之间。    #如果没有这种点,返回左、右邻居边的上顶点中y值比较小的那一个点。        def findUpBrother(self, point): #point是Point类型        rEdge = self.findRightNearestEdge(point);        lEdge = self.findLeftNearestEdge(point);        rSeg, lSeg = rEdge[0], lEdge[0];        upBrother = None;                if (rSeg != None and lSeg != None):            len_ = len(self.path);            for i in range(len_):                a = self.path[i].value();                b = point.value();                if (a[1] > b[1]):                    if (judgePointAgainstEdgePosition(rSeg, self.path[i]) == 'Left' and\                        judgePointAgainstEdgePosition(lSeg, self.path[i]) == 'Right'):                        if upBrother == None:                            upBrother = self.path[i];                        else:                            if (upBrother < self.path[i]):                                upBrother = self.path[i];            if upBrother == None:                upBrother = min(Point(lSeg.value()[1]), Point(rSeg.value()[1]));        return upBrother;    #找某点的下兄弟点,这个点的y坐标小于给定点,    #并且处于该点的左、右邻居边之间。    #如果没有这种点,返回左、右邻居边的下顶点中y值比较大的那一个点。        def findDownBrother(self, point): #point是Point类型        rEdge = self.findRightNearestEdge(point);        lEdge = self.findLeftNearestEdge(point);        rSeg, lSeg = rEdge[0], lEdge[0];        downBrother = None;                if (rSeg != None and lSeg != None):            len_ = len(self.path);            for i in range(len_):                a = self.path[i].value();                b = point.value();                if (a[1] < b[1]):                    if (judgePointAgainstEdgePosition(rSeg, self.path[i]) == 'Left' and\                        judgePointAgainstEdgePosition(lSeg, self.path[i]) == 'Right'):                        if downBrother == None:                            downBrother = self.path[i];                        else:                            if (downBrother < self.path[i]):                                downBrother = self.path[i];            if downBrother == None:                downBrother = max(Point(lSeg.value()[0]), Point(rSeg.value()[0]));        return downBrother;                        def tmp5():    path = [[[6, 9], [2.4, 5.4], [0.8, 3.8], [1.33, 3], [2, 3], [6, 3], [6, 3.86], [3.33, 5], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [1.33, 3], [2, 3], [3.33, 5], [6, 3.86], [8, 3], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.5, 1.5], [1.78, 2.33], [2, 3], [3.33, 5], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.33, 3], [1.78, 2.33], [2, 3], [3.33, 5], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.33, 3], [2, 3], [6, 3], [6, 3.86], [6, 9]], [[6, 9], [2.4, 5.4], [0.8, 3.8], [0, 3], [1.33, 3], [2, 3], [3.33, 5], [6, 3.86], [6, 9]], [[6, 9], [2.4, 5.4], [3.33, 5], [2, 3], [6, 3], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [2.4, 5.4], [3.33, 5], [6, 3.86], [6, 3], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [2.4, 5.4], [-6, 9], [-0.37, 2.56], [0, 3], [1.33, 3], [2, 3], [3.33, 5], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [1.78, 2.33], [3.67, -0.5], [4.29, 0.43], [6, 3], [6, 3.86], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [6, 3], [6, -3], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [6, 3], [6, -3], [8, -7], [8, 3], [6, 3.86], [6, 9]], [[6, 9], [3.33, 5], [2, 3], [6, 3], [4.5, 0], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [3.33, 5], [6, 3.86], [6, 3], [6, -3], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [3.33, 5], [6, 3.86], [6, 3], [4.5, 0], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [4.29, 0.43], [4.5, 0], [6, -3], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [6, -3], [5.56, -3.33], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [6, -3], [5.67, -3.5], [5.35, -3.97], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [4.5, 0], [6, -3], [5.67, -3.5], [8, -7], [8, 3], [6, 9]], [[6, 9], [6, 3.86], [6, 3], [4.5, 0], [4, -1], [6, -3], [8, -7], [8, 3], [6, 9]]]    len_path = len(path);    center = [[3.45, 4.47], [4.86, 5.51], [2.36, 4.5], [2.63, 4.92], [4.0, 5.0], [3.97, 5.51], [6.01, 2.42], [6.33, 2.21], [-0.28, 5.49], [4.29, 3.73], [6.17, 1.92], [6.07, 1.58], [6.08, 1.89], [6.53, 1.61], [6.39, 1.6], [6.68, 0.49], [6.95, 0.31], [6.92, 0.09], [6.71, 0.27], [6.62, 0.38]];    #第几条线段作为测试        n = 8;        len_path_0 = len(path[n]);    pCenter_0 = Point(center[n]);    a = Path(path[n]);    print(a.findLeftNearestEdge(pCenter_0));    print(a.findRightNearestEdge(pCenter_0));    print(a.findUpBrother(pCenter_0));    print(a.findDownBrother(pCenter_0));#</span>

本节到此结束,欲知后事如何,请看下回分解。


0 0
原创粉丝点击