代码之家  ›  专栏  ›  技术社区  ›  Comrade Che

哪里可以找到Chaikin切角算法的Python实现?

  •  8
  • Comrade Che  · 技术社区  · 7 年前

    我在寻找柴金的切角算法( link1 link2 )在Python 2.7中实现。但是找不到它。

    也许有人拥有它并且可以共享代码?

    2 回复  |  直到 5 年前
        1
  •  13
  •   Liran Funaro    4 年前

    下面的实现可以工作,但这里有一个更简短的版本,它更高效、更优雅。

    import numpy as np
    
    def chaikins_corner_cutting(coords, refinements=5):
        coords = np.array(coords)
    
        for _ in range(refinements):
            L = coords.repeat(2, axis=0)
            R = np.empty_like(L)
            R[0] = L[0]
            R[2::2] = L[1:-1:2]
            R[1:-1:2] = L[2::2]
            R[-1] = L[-1]
            coords = L * 0.75 + R * 0.25
    
        return coords
    

    它是如何工作的?

    对于每两个点,我们需要使用1:3的比例取它们之间的线的下半部分和上半部分:

    LOWER-POINT = P1 * 0.25 + P2 * 0.75
    UPPER-POINT = P1 * 0.75 + P2 * 0.25
    

    并将它们都添加到新的点列表中。

    我们以某种方式构建两个数组L和R,如果我们将它们按如下方式相乘,则将生成新的点列表。

    NEW-POINTS = L * 0.75 + R * 0.25
    

    例如,如果我们有4个点的数组:

    P = 0 1 2 3
    

    L和R阵列如下:

    L = 0 0 1 1 2 2 3 3
    R = 0 1 0 2 1 3 2 3
    

        2
  •  10
  •   Comrade Che    7 年前

    好的,这并不难,下面是代码: enter image description here

    import math
    
    # visualisation
    import matplotlib.pyplot as plt
    import matplotlib.lines as lines
    # visualisation
    
    def Sum_points(P1, P2):
        x1, y1 = P1
        x2, y2 = P2
        return x1+x2, y1+y2
    
    def Multiply_point(multiplier, P):
        x, y = P
        return float(x)*float(multiplier), float(y)*float(multiplier)
    
    def Check_if_object_is_polygon(Cartesian_coords_list):
        if Cartesian_coords_list[0] == Cartesian_coords_list[len(Cartesian_coords_list)-1]:
            return True
        else:
            return False
    
    class Object():
    
        def __init__(self, Cartesian_coords_list):
            self.Cartesian_coords_list = Cartesian_coords_list
    
        def Find_Q_point_position(self, P1, P2):
            Summand1 = Multiply_point(float(3)/float(4), P1)
            Summand2 = Multiply_point(float(1)/float(4), P2)
            Q = Sum_points(Summand1, Summand2) 
            return Q
    
        def Find_R_point_position(self, P1, P2):
            Summand1 = Multiply_point(float(1)/float(4), P1)
            Summand2 = Multiply_point(float(3)/float(4), P2)        
            R = Sum_points(Summand1, Summand2)
            return R
    
        def Smooth_by_Chaikin(self, number_of_refinements):
            refinement = 1
            copy_first_coord = Check_if_object_is_polygon(self.Cartesian_coords_list)
            while refinement <= number_of_refinements:
                self.New_cartesian_coords_list = []
    
                for num, tuple in enumerate(self.Cartesian_coords_list):
                    if num+1 == len(self.Cartesian_coords_list):
                        pass
                    else:
                        P1, P2 = (tuple, self.Cartesian_coords_list[num+1])
                        Q = obj.Find_Q_point_position(P1, P2)
                        R = obj.Find_R_point_position(P1, P2)
                        self.New_cartesian_coords_list.append(Q)
                        self.New_cartesian_coords_list.append(R)
    
                if copy_first_coord:
                    self.New_cartesian_coords_list.append(self.New_cartesian_coords_list[0])
    
                self.Cartesian_coords_list = self.New_cartesian_coords_list
                refinement += 1
            return self.Cartesian_coords_list
    
    if __name__ == "__main__":
        Cartesian_coords_list = [(1,1),
                                 (1,3),
                                 (4,5),
                                 (5,1),
                                 (2,0.5),
                                 (1,1),
                                 ]
    
        obj = Object(Cartesian_coords_list)    
        Smoothed_obj = obj.Smooth_by_Chaikin(number_of_refinements = 5)
    
        # visualisation
        x1 = [i for i,j in Smoothed_obj]
        y1 = [j for i,j in Smoothed_obj]
        x2 = [i for i,j in Cartesian_coords_list]
        y2 = [j for i,j in Cartesian_coords_list]    
        plt.plot(range(7),range(7),'w', alpha=0.7)
        myline = lines.Line2D(x1,y1,color='r')
        mynewline = lines.Line2D(x2,y2,color='b')
        plt.gca().add_artist(myline)
        plt.gca().add_artist(mynewline)
        plt.show()