[从头学数学] 第280节 [计算几何] 路径合并

剧情提要:
阿伟看到了一本比较有趣的书,是关于《计算几何》的,2008年由北清派出版。很好奇
它里面讲了些什么,就来看看啦。


正剧开始:
星历2016年09月27日 11:58:38, 银河系厄尔斯星球中华帝国江南行省。

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




比如下面两条路径,如果它们合并成一个环形的大路径,新路径是什么呢?





<span style="font-size:18px;">#
class Path():
    def info(self):
        print(self.path);

    
    def __init__(self, path):
        if (path[-1] == path[0]):
            path = path[:-1];
            
        if (type(path[0]) == Point):
            self.path = path;
        else:
            self.path = [];
            for i in range(len(path)):
                self.path.append(Point(path[i]));

    #判断路径相等
    def __eq__(self, other):
        if other == None:
            return False;

        len_1 = len(self.path);
        len_2 = len(other.path);

        if (len_1 != len_2):
            return False;

        if (other[0] in self):
            idx = self.path.index(other[0]);

            for i in range(len_1):
                if other[i] != self.path[(idx+i)%len_1]:
                    return False;

            return True;
        else:
            return False;

    def __len__(self):
        return len(self.path);

    def __iter__(self):
        for i in range(len(self)):
            yield self.path[i];

    def __contains__(self, item):
        return item in self.path;

    def __getitem__(self, index):
        return self.path[index];   

    #路径上的顶点集
    def pointSet(self):
        pSet = set();

        for i in range(len(self.path)):
            pSet.add(self.path[i]);

        return pSet;

    #两个点序号之间的劣弧路径,是以通过点的数量定优劣弧的,不是根据路径长度。
    def minorSubpath(self, idx1, idx2):
        idx1, idx2  = min(idx1, idx2), max(idx1, idx2);

        len_path = len(self.path);

        if (idx2 - idx1) <= len_path//2:
            subPath = self.path[idx1:idx2+1];
        else:
            subPath = self.path[idx2:]+self.path[:idx1+1];

        return subPath;

    #两个点序号之间的优弧路径,是以通过点的数量定优劣弧的,不是根据路径长度。
    def majorSubpath(self, idx1, idx2):
        idx1, idx2  = min(idx1, idx2), max(idx1, idx2);

        len_path = len(self.path);

        if (idx2 - idx1) >= len_path//2:
            subPath = self.path[idx1:idx2+1];
        else:
            subPath = self.path[idx2:]+self.path[:idx1+1];

        return subPath;

    #连接两段子路径,两段路径必须有相同的起点和终点,这样形成一个环路
    def linkPath(self, path1, path2):
        result = [];

        if path1[0] == path2[0] and path1[-1] == path2[-1]:
            path2 == reversed(path2);
            result = path1[:-1]+path2[:-1];
        elif path1[0] == path2[-1] and path1[-1] == path2[0]:
            result = path1[:-1]+path2[:-1];

        return result;

    #找公共点集在路径中的端点
    def findCommonBound(self, interSet):
        array = sorted(list(interSet));
        print(array);

        if (len(array) < 2):
            return [];
        elif (len(array) == 2):
            #一共只有两个交点,它们就是边界
            return [array[0], array[1]];
        elif (len(array) < len(self.path)):
            min_ = max_ = array[0];
            print(array[0]);

            idx1 = idx2 = self.path.index(min_);
            print(idx1);
            len_ = len(self.path);

            idx1 -= 1;
            idx2 += 1;

            print(self.path[idx2%len_]);
            while self.path[idx1%len_] in array:
                min_ = self.path[idx1%len_];
                idx1 -= 1;

            while self.path[idx2%len_] in array:
                max_ = self.path[idx2%len_];
                idx2 += 1;

            return [min_, max_];
        else:
            return [self.path[0], self.path[-1]];
        
    

    #合并两条路径,返回的是值的阵列,不是Path类
    def union(self, other):
        path1 = self.pointSet();
        path2 = other.pointSet();

        u = path1.intersection(path2);
        len_ = len(u);

        indexArray = [];        

        for item in u:
            indexArray.append(self.path.index(item));

        minIndex = min(indexArray);
        maxIndex = max(indexArray);


        for i in range(minIndex, maxIndex):
            u.add(self.path[i]);

        print('---', u);

        #两条路径有多于两个的交点
        if (len_ >= 2 and len_ < len(self)):

            #交点在两条路径中的序号
            a = self.findCommonBound(u);
            print(a);
            min_, max_ = a[0], a[1];


            minIdx_, maxIdx_ = self.path.index(min_), self.path.index(max_);
            minIdx_2, maxIdx_2 = other.path.index(min_), other.path.index(max_);

            subPath1 = self.majorSubpath(minIdx_, maxIdx_);
            subPath2 = other.majorSubpath(minIdx_2, maxIdx_2);

            '''
            print(subPath1);
            print(subPath2);
            print('\n');
            '''

            result = self.linkPath(subPath1, subPath2);            

            return result;
        elif (len_ == len(self)):
            return self.path;
        else:
            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);

    path_0 = path[0];
    path_2 = path[2];

    path_0_2 = path_0[:-1];
    path_0_2 = path_0_2[-3:] + path_0_2[:-3];

    #print(Path(path_0) == Path(path_2));  #False;
    #print(Path(path_0) == Path(path_0_2)); #True;

    a = Path(path_0);
    b = Path(path_2);
    #a.info();
    #b.info();

    uab = a.union(b);

#</span>

这里的合并算法是有问题的,对于两条可能有多段穿插的路径,或许应该把每段的交汇和分离都记录下来,先放着吧。


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值