Exemplo n.º 1
0
            def clip():
                lower = range_points[0]
                upper = range_points[1]
                lines = []
                dis = []
                t = 0
                mid = []
                for i in range(lower,upper):
                    for j in range(i+1,upper+1):
                        lines.append(Line.biSector(self.points[i],self.points[j]))
                        self.points[i].related.append(pair(lines[-1],self.points[j]))
                        self.points[j].related.append(pair(lines[-1],self.points[i]))
                        lines[-1]._p1 = self.points[i]
                        lines[-1]._p2 = self.points[j]
                        mid.append(((self.points[i]+self.points[j])/2,t))
                        dis.append((t,(self.points[i].x-self.points[j].x)**2+(self.points[i].y-self.points[j].y)**2,Line(self.points[i],self.points[j])))
                        t = t+1

                circumcenter = Line.intersect(lines[0],lines[1])
                if circumcenter is not None:
                    tmp_lines = None
                    dis.sort(key = lambda x : x[1])
                    triangle = 'acute'
                    if dis[0][1]+dis[1][1] == dis[2][1]:
                        triangle = 'right'
                        tmp_lines = dis[0:2]
                    elif dis[0][1]+dis[1][1]<dis[2][1]:
                        triangle = 'obtuse'

                    #print triangle
                    s = dis[2][0]
                    t = 0

                    for i in range(lower,upper):
                        for j in range(i+1,upper+1):
                            ab = (Line(self.points[i],self.points[j]))
                            hl = Line(lines[t].p1,circumcenter)
                            result = Line.intersect(hl,ab)

                            #do not determine the longest side of right triangle in the same way
                            if not (triangle == 'right' and t == s):
                                if result  is  None:
                                    #reverse policy for longest side of obtuse
                                    if not (triangle == 'obtuse' and t == s):
                                        lines[t].p1 = circumcenter
                                    else:
                                        lines[t].p2 = circumcenter
                                else:
                                    if not (triangle == 'obtuse' and t == s):
                                        lines[t].p2 = circumcenter
                                    else:
                                        lines[t].p1 = circumcenter
                            t = t+1
                    #now determine the longest side of right triangle
                    if triangle == 'right':
                        t = dis[2][0]
                        if Line.intersect(Line(lines[t].p1,circumcenter),tmp_lines[0][2])  != None or Line.intersect(Line(lines[t].p1,circumcenter),tmp_lines[1][2]) != None:
                            lines[t].p1,lines[t].p2 = circumcenter,lines[t].p2
                        else:
                            lines[t].p1,lines[t].p2 = circumcenter,lines[t].p1

                    #create circumcenter related points
                    circumcenter.iscircumcenter = True
                    lines[0].connected.append(lines[1])
                    lines[0].connected.append(lines[2])
                    lines[1].connected.append(lines[0])
                    lines[1].connected.append(lines[2])
                    lines[2].connected.append(lines[0])
                    lines[2].connected.append(lines[1])


                else:
                    mid.sort(key = lambda s: attrgetter('x','y')(s[0]))
                    t = mid[1][1]
                    del_line = lines[t]
                    for i in range(lower,upper+1):
                        u = self.points[i].related
                        for j in range(0,len(u)):
                            if u[j].line is del_line:
                                del u[j]
                                break
                    del lines[t]
                    #Line.intersect_with_edge(lines,Canvas.edge_painter,'colinear')

                return lines
Exemplo n.º 2
0
    def Voronoi(self,range_points):

        if (range_points[1]-range_points[0]+1) == 2:
            #print 'len = 2'
            lower = range_points[0]
            upper = range_points[1]
            line = [Line.biSector(self.points[lower],self.points[upper])]
            line[0]._p1 = self.points[lower]
            line[0]._p2 = self.points[upper]
            #hash table for point mapping to related biSector
            self.points[lower].related.append(pair(line[0],self.points[upper]))
            self.points[upper].related.append(pair(line[0],self.points[lower]))
            #Line.intersect_with_edge(line,Canvas.edge_painter,'colinear')
            vd = VD(line,range_points,self)
            return vd

        elif (range_points[1]-range_points[0]+1) == 3:
            #print 'len = 3'
            def clip():
                lower = range_points[0]
                upper = range_points[1]
                lines = []
                dis = []
                t = 0
                mid = []
                for i in range(lower,upper):
                    for j in range(i+1,upper+1):
                        lines.append(Line.biSector(self.points[i],self.points[j]))
                        self.points[i].related.append(pair(lines[-1],self.points[j]))
                        self.points[j].related.append(pair(lines[-1],self.points[i]))
                        lines[-1]._p1 = self.points[i]
                        lines[-1]._p2 = self.points[j]
                        mid.append(((self.points[i]+self.points[j])/2,t))
                        dis.append((t,(self.points[i].x-self.points[j].x)**2+(self.points[i].y-self.points[j].y)**2,Line(self.points[i],self.points[j])))
                        t = t+1

                circumcenter = Line.intersect(lines[0],lines[1])
                if circumcenter is not None:
                    tmp_lines = None
                    dis.sort(key = lambda x : x[1])
                    triangle = 'acute'
                    if dis[0][1]+dis[1][1] == dis[2][1]:
                        triangle = 'right'
                        tmp_lines = dis[0:2]
                    elif dis[0][1]+dis[1][1]<dis[2][1]:
                        triangle = 'obtuse'

                    #print triangle
                    s = dis[2][0]
                    t = 0

                    for i in range(lower,upper):
                        for j in range(i+1,upper+1):
                            ab = (Line(self.points[i],self.points[j]))
                            hl = Line(lines[t].p1,circumcenter)
                            result = Line.intersect(hl,ab)

                            #do not determine the longest side of right triangle in the same way
                            if not (triangle == 'right' and t == s):
                                if result  is  None:
                                    #reverse policy for longest side of obtuse
                                    if not (triangle == 'obtuse' and t == s):
                                        lines[t].p1 = circumcenter
                                    else:
                                        lines[t].p2 = circumcenter
                                else:
                                    if not (triangle == 'obtuse' and t == s):
                                        lines[t].p2 = circumcenter
                                    else:
                                        lines[t].p1 = circumcenter
                            t = t+1
                    #now determine the longest side of right triangle
                    if triangle == 'right':
                        t = dis[2][0]
                        if Line.intersect(Line(lines[t].p1,circumcenter),tmp_lines[0][2])  != None or Line.intersect(Line(lines[t].p1,circumcenter),tmp_lines[1][2]) != None:
                            lines[t].p1,lines[t].p2 = circumcenter,lines[t].p2
                        else:
                            lines[t].p1,lines[t].p2 = circumcenter,lines[t].p1

                    #create circumcenter related points
                    circumcenter.iscircumcenter = True
                    lines[0].connected.append(lines[1])
                    lines[0].connected.append(lines[2])
                    lines[1].connected.append(lines[0])
                    lines[1].connected.append(lines[2])
                    lines[2].connected.append(lines[0])
                    lines[2].connected.append(lines[1])


                else:
                    mid.sort(key = lambda s: attrgetter('x','y')(s[0]))
                    t = mid[1][1]
                    del_line = lines[t]
                    for i in range(lower,upper+1):
                        u = self.points[i].related
                        for j in range(0,len(u)):
                            if u[j].line is del_line:
                                del u[j]
                                break
                    del lines[t]
                    #Line.intersect_with_edge(lines,Canvas.edge_painter,'colinear')

                return lines

            lines = []+clip()
            return VD(lines,range_points,self)

        elif (range_points[1]-range_points[0]+1) == 1:
            return VD([],range_points,self)
        else:
            mid = int((range_points[1]+range_points[0])/2)
            VDL = self.Voronoi((range_points[0],mid))

            if self.isstep_by_step == True:
                #vdl = VD(copy.deepcopy(VDL.lines),copy.deepcopy(VDL.range_points),self)
                vdl = savevd(VDL.lines,VDL.range_points,self,VDL.convex)
                vdl.pos = 'left'
                vdl.color = QtCore.Qt.blue
                self.vd[0].append(vdl)

            VDR = self.Voronoi((mid+1,range_points[1]))

            if self.isstep_by_step == True:
                #vdr = VD(copy.deepcopy(VDR.lines),copy.deepcopy(VDR.range_points),self)
                vdr = savevd(VDR.lines,VDR.range_points,self,VDR.convex)
                vdr.pos = 'right'
                vdr.color = QtCore.Qt.red
                vdr.other = vdl
                vdl.other = vdr
                self.vd[0].append(vdr)

            merge_vd = VD.merge(VDL,VDR,self.tangent)
            self.debug_message[0].append(self.msg)
            self.msg = ""
            return merge_vd
Exemplo n.º 3
0
    def merge(VDL, VDR, tangent):

        clip_lines = []
        #used to record ray which intersect with dividing chain
        #using hash table
        ray_list = set()

        def discard_edges(ray, circumcenter, side, SG_bisector):
            def recursive_discard_edge(ray, other_point, base_point, side):
                #want to delete left remaining line
                for candidate in ray.connected:
                    if candidate.avail == True and candidate not in ray_list:
                        next_base_point = None
                        next_other_point = None
                        #catch base point
                        if (candidate.p1 is base_point
                                or candidate.p2 is base_point):
                            if candidate.p1 is base_point:
                                next_base_point = candidate.p2
                                next_other_point = candidate.p1
                            else:
                                next_base_point = candidate.p1
                                next_other_point = candidate.p2

                            if side == 'right':
                                if ConvexHull.cross(base_point,
                                                    next_base_point,
                                                    other_point) > 0:
                                    candidate.avail = False
                                    recursive_discard_edge(
                                        candidate, next_other_point,
                                        next_base_point, 'right')
                            elif side == 'left':
                                if ConvexHull.cross(base_point,
                                                    next_base_point,
                                                    other_point) < 0:
                                    candidate.avail = False
                                    recursive_discard_edge(
                                        candidate, next_other_point,
                                        next_base_point, 'left')

            if side == 'right':
                #clear the edges extend to the left of HP
                #Line(hole,ray.p1) or Line(hole,ray.p2) must cw to Line(hole,bisector.p1)
                if ConvexHull.cross(circumcenter, ray.p1, SG_bisector.p1) > 0:
                    #this means p1 is left to circumcenter,so replace p1 with circumcenter
                    if ray.p1.iscircumcenter == True:
                        recursive_discard_edge(ray, circumcenter, ray.p1,
                                               'right')
                    ray.p1 = circumcenter
                else:
                    if ray.p2.iscircumcenter == True:
                        recursive_discard_edge(ray, circumcenter, ray.p2,
                                               'right')
                    ray.p2 = circumcenter
            elif side == "left":
                #clear the edges extend to the right of HP
                #Line(hole,ray.p1) or Line(hole,ray.p2) must ccw to Line(hole,bisector.p1)
                if ConvexHull.cross(circumcenter, ray.p1, SG_bisector.p1) < 0:
                    #this means p1 is right to circumcenter,so replace p1 with circumcenter
                    if ray.p1.iscircumcenter == True:
                        recursive_discard_edge(ray, circumcenter, ray.p1,
                                               'left')
                    ray.p1 = circumcenter
                else:

                    if ray.p2.iscircumcenter == True:
                        recursive_discard_edge(ray, circumcenter, ray.p2,
                                               'left')
                    ray.p2 = circumcenter
            else:
                #clear both side
                #clear the edges extend to the right of HP
                #Line(hole,ray.p1) or Line(hole,ray.p2) must ccw to Line(hole,bisector.p1)
                if ConvexHull.cross(circumcenter, ray[0].p1,
                                    SG_bisector.p1) < 0:
                    #this means p1 is right to circumcenter,so replace p1 with circumcenter
                    if ray[0].p1.iscircumcenter == True:
                        recursive_discard_edge(ray[0], circumcenter, ray[0].p1,
                                               'left')
                    ray[0].p1 = circumcenter
                else:
                    if ray[0].p2.iscircumcenter == True:
                        recursive_discard_edge(ray[0], circumcenter, ray[0].p2,
                                               'left')
                    ray[0].p2 = circumcenter

                #clear the edges extend to the left of HP
                if ConvexHull.cross(circumcenter, ray[1].p1,
                                    SG_bisector.p1) > 0:
                    #this means p1 is left to circumcenter,so replace p1 with circumcenter
                    if ray[1].p1.iscircumcenter == True:
                        recursive_discard_edge(ray[1], circumcenter, ray[1].p1,
                                               'right')
                    ray[1].p1 = circumcenter
                else:
                    if ray[1].p2.iscircumcenter == True:
                        recursive_discard_edge(ray[1], circumcenter, ray[1].p2,
                                               'right')
                    ray[1].p2 = circumcenter

        def nextPoint(pool, SG_bisector):
            ans = None
            first = True
            for candidate in pool:
                if candidate.line.avail == True and SG_bisector.p1 is not candidate.line.hole:
                    result = Line.intersect(candidate.line, SG_bisector)
                    if result is not None:
                        t = (result, candidate.point, candidate.line)
                        if first == True:
                            ans = t
                            first = False
                        else:
                            if t[0].y <= ans[0].y:
                                ans = t
            return ans

        upper_tangent, lower_tangent = VD.find_tangent(VDL, VDR)
        ul = (upper_tangent, lower_tangent)
        tangent[0].append(ul)

        HP = []
        SG = upper_tangent
        px = SG.p1
        py = SG.p2
        #p1 of upper_tangent belongs to VDL, and p2 belongs to VDR
        SG_bisector = Line.biSector(SG.p1, SG.p2)
        SG_bisector._p1 = SG.p1
        SG_bisector._p2 = SG.p2

        HP.append(SG_bisector)
        circumcenter = None

        firsttime = True
        newpl = defaultdict(list)

        while not (SG == lower_tangent):
            #step4 as textBook

            #p1 of SG_bisector is fixed to upper position than p2
            if SG_bisector.p1.y > SG_bisector.p2.y:
                SG_bisector.p1, SG_bisector.p2 = SG_bisector.p2, SG_bisector.p1
            elif abs((SG_bisector.p1.y) - (SG_bisector.p2.y)) <= 0.00005:
                if SG_bisector.p1.x < SG_bisector.p2.x:
                    SG_bisector.p1, SG_bisector.p2 = SG_bisector.p2, SG_bisector.p1

            newpl[SG.p1].append(pair(SG_bisector, SG.p2))
            newpl[SG.p2].append(pair(SG_bisector, SG.p1))

            #orginally p1 is very far from painter,so we need to fix p1 to previous circumcenter
            if firsttime == False and circumcenter is not None:
                SG_bisector.p1 = circumcenter

            pll = px.related
            prl = py.related

            result_l = nextPoint(pll, SG_bisector)
            result_r = nextPoint(prl, SG_bisector)

            side = None
            ray = None
            #with biSector of pyz2 first,that is,VDR first
            if result_l is not None and result_r is not None:
                if abs(result_l[0].x - result_r[0].x) <= 0.05 and abs(
                        result_l[0].y - result_r[0].y) <= 0.05:
                    #VDL.parent.msg = VDL.parent.msg+'both cd'+'\n'
                    SG = Line(result_l[1], result_r[1])
                    circumcenter = result_l[0]
                    ray = (result_l[2], result_r[2])
                    side = 'both'
                elif result_l[0].y > result_r[0].y:
                    #VDL.parent.msg = VDL.parent.msg+'cd VDR'+'\n'
                    SG = Line(px, result_r[1])
                    circumcenter = result_r[0]
                    ray = result_r[2]
                    side = 'right'
                elif result_l[0].y < result_r[0].y:
                    #VDL.parent.msg = VDL.parent.msg+'cd VDL'+'\n'
                    SG = Line(result_l[1], py)
                    circumcenter = result_l[0]
                    ray = result_l[2]
                    side = 'left'
                else:
                    print('confused...')
                    #print result_l,result_r
            else:
                if result_l is not None and result_r is None:
                    #VDL.parent.msg = VDL.parent.msg+'VDR is None,cd VDL'+'\n'
                    SG = Line(result_l[1], py)
                    circumcenter = result_l[0]
                    ray = result_l[2]
                    side = 'left'
                elif result_r is not None and result_l is None:
                    #VDL.parent.msg = VDL.parent.msg+'VDL is None,cd VDR'+'\n'
                    SG = Line(px, result_r[1])
                    circumcenter = result_r[0]
                    #print 'circumcenter',(circumcenter.x,circumcenter.y)
                    ray = result_r[2]
                    side = 'right'
                else:
                    #VDL.parent.msg = VDL.parent.msg+'both are None'+'\n'
                    #let SG be lower_tangent
                    SG = lower_tangent
                    SG_bisector = Line.biSector(SG.p1, SG.p2)
                    SG_bisector._p1 = SG.p1
                    SG_bisector._p2 = SG.p2
                    HP.append(SG_bisector)
                    continue

            if ray is not None:
                if not isinstance(ray, tuple):
                    ray.hole = circumcenter
                    t = (ray, SG_bisector, side, circumcenter)
                    if ray not in ray_list:
                        ray_list.add(ray)
                    clip_lines.append(t)
                else:
                    for r in ray:
                        r.hole = circumcenter
                        ray_list.add(r)
                    t = (ray, SG_bisector, side, circumcenter)
                    clip_lines.append(t)

            if circumcenter is not None:
                circumcenter.iscircumcenter = True
                #lower point is replaced by circumcenter
                SG_bisector.p2 = circumcenter

            #new SG
            px = SG.p1
            py = SG.p2
            SG_bisector = Line.biSector(SG.p1, SG.p2)
            SG_bisector._p1 = SG.p1
            SG_bisector._p2 = SG.p2

            HP.append(SG_bisector)
            firsttime = False
            #the end of while loop for HP

        if SG_bisector.p1.y > SG_bisector.p2.y:
            SG_bisector.p1, SG_bisector.p2 = SG_bisector.p2, SG_bisector.p1
        elif abs((SG_bisector.p1.y) - (SG_bisector.p2.y)) <= 0.00005:
            if SG_bisector.p1.x < SG_bisector.p2.x:
                SG_bisector.p1, SG_bisector.p2 = SG_bisector.p2, SG_bisector.p1

        newpl[SG.p1].append(pair(SG_bisector, SG.p2))
        newpl[SG.p2].append(pair(SG_bisector, SG.p1))

        for p in newpl.keys():
            for t in newpl[p]:
                p.related.append(t)

        if circumcenter is not None:
            SG_bisector.p1 = circumcenter

        #clip the unwanted lines
        VDL.parent.msg = VDL.parent.msg + 'clip lines' + '\n'
        for t in clip_lines:
            ray = t[0]
            circumcenter = t[3]
            SG_bisector = t[1]
            side = t[2]
            discard_edges(ray, circumcenter, side, SG_bisector)

        #add new connected line
        s = 0
        for t in range(0, len(HP) - 1):
            #need to add the intersected dividing chain
            HP[t].connected.append(HP[t + 1])
            HP[t + 1].connected.append(HP[t])
            #need to add the intersected ray
            if s != len(clip_lines):
                if not isinstance(clip_lines[s][0], tuple):
                    HP[t].connected.append(clip_lines[s][0])
                    clip_lines[s][0].connected.append(HP[t])
                    HP[t + 1].connected.append(clip_lines[s][0])
                    clip_lines[s][0].connected.append(HP[t + 1])
                else:
                    r = clip_lines[s][0]
                    HP[t].connected.append(r[0])
                    r[0].connected.append(HP[t])
                    HP[t + 1].connected.append(r[0])
                    r[0].connected.append(HP[t + 1])

                    HP[t].connected.append(r[1])
                    r[1].connected.append(HP[t])
                    HP[t + 1].connected.append(r[1])
                    r[1].connected.append(HP[t + 1])

                    r[1].connected.append(r[0])
                    r[0].connected.append(r[1])
            s = s + 1

        lines = []
        #lines = VDR.lines+VDL.lines+HP
        lines.append(VDR.lines)
        lines.append(VDL.lines)
        lines.append(HP)
        if VDL.parent.isstep_by_step == True:
            hp = []
            for h in HP:
                hp.append(Line(Point(h.p1.x, h.p1.y), Point(h.p2.x, h.p2.y)))
            VDR.parent.hp[0].append(hp)
        #VDR.parent.hp[0].append(copy.deepcopy(HP))
        range_points = (VDL.range_points[0], VDR.range_points[1])
        return VD(lines, range_points, VDR.parent)
Exemplo n.º 4
0
            def clip():
                lower = range_points[0]
                upper = range_points[1]
                lines = []
                dis = []
                t = 0
                mid = []
                for i in range(lower,upper):
                    for j in range(i+1,upper+1):
                        lines.append(Line.biSector(self.points[i],self.points[j]))
                        self.points[i].related.append(pair(lines[-1],self.points[j]))
                        self.points[j].related.append(pair(lines[-1],self.points[i]))
                        lines[-1]._p1 = self.points[i]
                        lines[-1]._p2 = self.points[j]
                        mid.append(((self.points[i]+self.points[j])/2,t))
                        dis.append((t,(self.points[i].x-self.points[j].x)**2+(self.points[i].y-self.points[j].y)**2,Line(self.points[i],self.points[j])))
                        t = t+1

                circumcenter = Line.intersect(lines[0],lines[1])
                if circumcenter is not None:
                    tmp_lines = None
                    dis.sort(key = lambda x : x[1])
                    triangle = 'acute'
                    if dis[0][1]+dis[1][1] == dis[2][1]:
                        triangle = 'right'
                        tmp_lines = dis[0:2]
                    elif dis[0][1]+dis[1][1]<dis[2][1]:
                        triangle = 'obtuse'

                    #print triangle
                    s = dis[2][0]
                    t = 0

                    for i in range(lower,upper):
                        for j in range(i+1,upper+1):
                            ab = (Line(self.points[i],self.points[j]))
                            hl = Line(lines[t].p1,circumcenter)
                            result = Line.intersect(hl,ab)

                            #do not determine the longest side of right triangle in the same way
                            if not (triangle == 'right' and t == s):
                                if result  is  None:
                                    #reverse policy for longest side of obtuse
                                    if not (triangle == 'obtuse' and t == s):
                                        lines[t].p1 = circumcenter
                                    else:
                                        lines[t].p2 = circumcenter
                                else:
                                    if not (triangle == 'obtuse' and t == s):
                                        lines[t].p2 = circumcenter
                                    else:
                                        lines[t].p1 = circumcenter
                            t = t+1
                    #now determine the longest side of right triangle
                    if triangle == 'right':
                        t = dis[2][0]
                        if Line.intersect(Line(lines[t].p1,circumcenter),tmp_lines[0][2])  != None or Line.intersect(Line(lines[t].p1,circumcenter),tmp_lines[1][2]) != None:
                            lines[t].p1,lines[t].p2 = circumcenter,lines[t].p2
                        else:
                            lines[t].p1,lines[t].p2 = circumcenter,lines[t].p1

                    #create circumcenter related points
                    circumcenter.iscircumcenter = True
                    lines[0].connected.append(lines[1])
                    lines[0].connected.append(lines[2])
                    lines[1].connected.append(lines[0])
                    lines[1].connected.append(lines[2])
                    lines[2].connected.append(lines[0])
                    lines[2].connected.append(lines[1])


                else:
                    mid.sort(key = lambda s: attrgetter('x','y')(s[0]))
                    t = mid[1][1]
                    del_line = lines[t]
                    for i in range(lower,upper+1):
                        u = self.points[i].related
                        for j in range(0,len(u)):
                            if u[j].line is del_line:
                                del u[j]
                                break
                    del lines[t]
                    #Line.intersect_with_edge(lines,Canvas.edge_painter,'colinear')

                return lines
Exemplo n.º 5
0
    def Voronoi(self,range_points):

        if (range_points[1]-range_points[0]+1) == 2:
            #print 'len = 2'
            lower = range_points[0]
            upper = range_points[1]
            line = [Line.biSector(self.points[lower],self.points[upper])]
            line[0]._p1 = self.points[lower]
            line[0]._p2 = self.points[upper]
            #hash table for point mapping to related biSector
            self.points[lower].related.append(pair(line[0],self.points[upper]))
            self.points[upper].related.append(pair(line[0],self.points[lower]))
            #Line.intersect_with_edge(line,Canvas.edge_painter,'colinear')
            vd = VD(line,range_points,self)
            return vd

        elif (range_points[1]-range_points[0]+1) == 3:
            #print 'len = 3'
            def clip():
                lower = range_points[0]
                upper = range_points[1]
                lines = []
                dis = []
                t = 0
                mid = []
                for i in range(lower,upper):
                    for j in range(i+1,upper+1):
                        lines.append(Line.biSector(self.points[i],self.points[j]))
                        self.points[i].related.append(pair(lines[-1],self.points[j]))
                        self.points[j].related.append(pair(lines[-1],self.points[i]))
                        lines[-1]._p1 = self.points[i]
                        lines[-1]._p2 = self.points[j]
                        mid.append(((self.points[i]+self.points[j])/2,t))
                        dis.append((t,(self.points[i].x-self.points[j].x)**2+(self.points[i].y-self.points[j].y)**2,Line(self.points[i],self.points[j])))
                        t = t+1

                circumcenter = Line.intersect(lines[0],lines[1])
                if circumcenter is not None:
                    tmp_lines = None
                    dis.sort(key = lambda x : x[1])
                    triangle = 'acute'
                    if dis[0][1]+dis[1][1] == dis[2][1]:
                        triangle = 'right'
                        tmp_lines = dis[0:2]
                    elif dis[0][1]+dis[1][1]<dis[2][1]:
                        triangle = 'obtuse'

                    #print triangle
                    s = dis[2][0]
                    t = 0

                    for i in range(lower,upper):
                        for j in range(i+1,upper+1):
                            ab = (Line(self.points[i],self.points[j]))
                            hl = Line(lines[t].p1,circumcenter)
                            result = Line.intersect(hl,ab)

                            #do not determine the longest side of right triangle in the same way
                            if not (triangle == 'right' and t == s):
                                if result  is  None:
                                    #reverse policy for longest side of obtuse
                                    if not (triangle == 'obtuse' and t == s):
                                        lines[t].p1 = circumcenter
                                    else:
                                        lines[t].p2 = circumcenter
                                else:
                                    if not (triangle == 'obtuse' and t == s):
                                        lines[t].p2 = circumcenter
                                    else:
                                        lines[t].p1 = circumcenter
                            t = t+1
                    #now determine the longest side of right triangle
                    if triangle == 'right':
                        t = dis[2][0]
                        if Line.intersect(Line(lines[t].p1,circumcenter),tmp_lines[0][2])  != None or Line.intersect(Line(lines[t].p1,circumcenter),tmp_lines[1][2]) != None:
                            lines[t].p1,lines[t].p2 = circumcenter,lines[t].p2
                        else:
                            lines[t].p1,lines[t].p2 = circumcenter,lines[t].p1

                    #create circumcenter related points
                    circumcenter.iscircumcenter = True
                    lines[0].connected.append(lines[1])
                    lines[0].connected.append(lines[2])
                    lines[1].connected.append(lines[0])
                    lines[1].connected.append(lines[2])
                    lines[2].connected.append(lines[0])
                    lines[2].connected.append(lines[1])


                else:
                    mid.sort(key = lambda s: attrgetter('x','y')(s[0]))
                    t = mid[1][1]
                    del_line = lines[t]
                    for i in range(lower,upper+1):
                        u = self.points[i].related
                        for j in range(0,len(u)):
                            if u[j].line is del_line:
                                del u[j]
                                break
                    del lines[t]
                    #Line.intersect_with_edge(lines,Canvas.edge_painter,'colinear')

                return lines

            lines = []+clip()
            return VD(lines,range_points,self)

        elif (range_points[1]-range_points[0]+1) == 1:
            return VD([],range_points,self)
        else:
            mid = int((range_points[1]+range_points[0])/2)
            VDL = self.Voronoi((range_points[0],mid))

            if self.isstep_by_step == True:
                #vdl = VD(copy.deepcopy(VDL.lines),copy.deepcopy(VDL.range_points),self)
                vdl = savevd(VDL.lines,VDL.range_points,self,VDL.convex)
                vdl.pos = 'left'
                vdl.color = QtCore.Qt.blue
                self.vd[0].append(vdl)

            VDR = self.Voronoi((mid+1,range_points[1]))

            if self.isstep_by_step == True:
                #vdr = VD(copy.deepcopy(VDR.lines),copy.deepcopy(VDR.range_points),self)
                vdr = savevd(VDR.lines,VDR.range_points,self,VDR.convex)
                vdr.pos = 'right'
                vdr.color = QtCore.Qt.red
                vdr.other = vdl
                vdl.other = vdr
                self.vd[0].append(vdr)

            merge_vd = VD.merge(VDL,VDR,self.tangent)
            self.debug_message[0].append(self.msg)
            self.msg = ""
            return merge_vd
Exemplo n.º 6
0
    def merge(VDL,VDR,tangent):

        clip_lines = []
        #used to record ray which intersect with dividing chain
        #using hash table
        ray_list = set()
        def discard_edges(ray,circumcenter,side,SG_bisector):

            def recursive_discard_edge(ray,other_point,base_point,side):
                #want to delete left remaining line
                for candidate in ray.connected:
                    if candidate.avail == True and candidate not in ray_list:
                        next_base_point = None
                        next_other_point = None
                        #catch base point
                        if(candidate.p1 is base_point or candidate.p2 is base_point):
                            if candidate.p1 is base_point:
                                next_base_point = candidate.p2
                                next_other_point = candidate.p1
                            else:
                                next_base_point = candidate.p1
                                next_other_point = candidate.p2

                            if side == 'right':
                                if ConvexHull.cross(base_point,next_base_point,other_point) > 0:
                                    candidate.avail = False
                                    recursive_discard_edge(candidate,next_other_point,next_base_point,'right')
                            elif side == 'left':
                                if ConvexHull.cross(base_point,next_base_point,other_point) < 0:
                                    candidate.avail = False
                                    recursive_discard_edge(candidate,next_other_point,next_base_point,'left')

            if side == 'right':
                #clear the edges extend to the left of HP
                #Line(hole,ray.p1) or Line(hole,ray.p2) must cw to Line(hole,bisector.p1)
                if ConvexHull.cross(circumcenter,ray.p1,SG_bisector.p1)>0:
                    #this means p1 is left to circumcenter,so replace p1 with circumcenter
                    if ray.p1.iscircumcenter == True:
                        recursive_discard_edge(ray,circumcenter,ray.p1,'right')
                    ray.p1 = circumcenter
                else:
                    if ray.p2.iscircumcenter == True:
                        recursive_discard_edge(ray,circumcenter,ray.p2,'right')
                    ray.p2 = circumcenter
            elif side == "left":
                #clear the edges extend to the right of HP
                #Line(hole,ray.p1) or Line(hole,ray.p2) must ccw to Line(hole,bisector.p1)
                if ConvexHull.cross(circumcenter,ray.p1,SG_bisector.p1)<0:
                    #this means p1 is right to circumcenter,so replace p1 with circumcenter
                    if ray.p1.iscircumcenter == True:
                        recursive_discard_edge(ray,circumcenter,ray.p1,'left')
                    ray.p1 = circumcenter
                else:

                    if ray.p2.iscircumcenter == True:
                        recursive_discard_edge(ray,circumcenter,ray.p2,'left')
                    ray.p2 = circumcenter
            else:
                #clear both side
                #clear the edges extend to the right of HP
                #Line(hole,ray.p1) or Line(hole,ray.p2) must ccw to Line(hole,bisector.p1)
                if ConvexHull.cross(circumcenter,ray[0].p1,SG_bisector.p1)<0:
                    #this means p1 is right to circumcenter,so replace p1 with circumcenter
                    if ray[0].p1.iscircumcenter == True:
                        recursive_discard_edge(ray[0],circumcenter,ray[0].p1,'left')
                    ray[0].p1 = circumcenter
                else:
                    if ray[0].p2.iscircumcenter == True:
                        recursive_discard_edge(ray[0],circumcenter,ray[0].p2,'left')
                    ray[0].p2 = circumcenter

                #clear the edges extend to the left of HP
                if ConvexHull.cross(circumcenter,ray[1].p1,SG_bisector.p1)>0:
                    #this means p1 is left to circumcenter,so replace p1 with circumcenter
                    if ray[1].p1.iscircumcenter == True:
                        recursive_discard_edge(ray[1],circumcenter,ray[1].p1,'right')
                    ray[1].p1 = circumcenter
                else:
                    if ray[1].p2.iscircumcenter == True:
                        recursive_discard_edge(ray[1],circumcenter,ray[1].p2,'right')
                    ray[1].p2 = circumcenter

        def nextPoint(pool,SG_bisector):
            ans = None
            first = True
            for candidate in pool:
                if candidate.line.avail== True and SG_bisector.p1 is not candidate.line.hole:
                    result = Line.intersect(candidate.line,SG_bisector)
                    if result is not None:
                        t = (result,candidate.point,candidate.line)
                        if first ==  True:
                            ans = t
                            first = False
                        else:
                            if t[0].y <= ans[0].y:
                                ans = t
            return ans

        upper_tangent,lower_tangent = VD.find_tangent(VDL,VDR)
        ul = (upper_tangent,lower_tangent)
        tangent[0].append(ul)

        HP = []
        SG = upper_tangent
        px = SG.p1
        py = SG.p2
        #p1 of upper_tangent belongs to VDL, and p2 belongs to VDR
        SG_bisector = Line.biSector(SG.p1,SG.p2)
        SG_bisector._p1 = SG.p1
        SG_bisector._p2 = SG.p2

        HP.append(SG_bisector)
        circumcenter = None

        firsttime = True
        newpl = defaultdict(list)

        while not (SG  == lower_tangent):
            #step4 as textBook

            #p1 of SG_bisector is fixed to upper position than p2
            if SG_bisector.p1.y > SG_bisector.p2.y:
                SG_bisector.p1,SG_bisector.p2 = SG_bisector.p2,SG_bisector.p1
            elif abs((SG_bisector.p1.y)-(SG_bisector.p2.y)) <= 0.00005:
                if SG_bisector.p1.x<SG_bisector.p2.x:
                    SG_bisector.p1,SG_bisector.p2 = SG_bisector.p2,SG_bisector.p1

            newpl[SG.p1].append(pair(SG_bisector,SG.p2))
            newpl[SG.p2].append(pair(SG_bisector,SG.p1))

            #orginally p1 is very far from painter,so we need to fix p1 to previous circumcenter
            if firsttime == False and circumcenter is not None:
                SG_bisector.p1 = circumcenter

            pll = px.related
            prl = py.related

            result_l = nextPoint(pll,SG_bisector)
            result_r = nextPoint(prl,SG_bisector)

            side = None
            ray = None
            #with biSector of pyz2 first,that is,VDR first
            if result_l is not None and result_r is not None:
                if abs(result_l[0].x-result_r[0].x) <= 0.05 and abs(result_l[0].y-result_r[0].y) <= 0.05:
                    #VDL.parent.msg = VDL.parent.msg+'both cd'+'\n'
                    SG = Line(result_l[1],result_r[1]);
                    circumcenter = result_l[0]
                    ray = (result_l[2],result_r[2])
                    side = 'both'
                elif result_l[0].y > result_r[0].y:
                    #VDL.parent.msg = VDL.parent.msg+'cd VDR'+'\n'
                    SG = Line(px,result_r[1])
                    circumcenter = result_r[0]
                    ray = result_r[2]
                    side = 'right'
                elif result_l[0].y < result_r[0].y:
                    #VDL.parent.msg = VDL.parent.msg+'cd VDL'+'\n'
                    SG = Line(result_l[1],py)
                    circumcenter = result_l[0]
                    ray = result_l[2]
                    side = 'left'
                else:
                    print 'confused...'
                    #print result_l,result_r
            else:
                if result_l is not None and result_r is None:
                    #VDL.parent.msg = VDL.parent.msg+'VDR is None,cd VDL'+'\n'
                    SG = Line(result_l[1],py)
                    circumcenter = result_l[0]
                    ray = result_l[2]
                    side = 'left'
                elif result_r is not None and result_l is None:
                    #VDL.parent.msg = VDL.parent.msg+'VDL is None,cd VDR'+'\n'
                    SG = Line(px,result_r[1])
                    circumcenter = result_r[0]
                    #print 'circumcenter',(circumcenter.x,circumcenter.y)
                    ray = result_r[2]
                    side = 'right'
                else:
                    #VDL.parent.msg = VDL.parent.msg+'both are None'+'\n'
                    #let SG be lower_tangent
                    SG = lower_tangent
                    SG_bisector = Line.biSector(SG.p1,SG.p2)
                    SG_bisector._p1 = SG.p1
                    SG_bisector._p2 = SG.p2
                    HP.append(SG_bisector)
                    continue

            if ray is not None:
                if not isinstance(ray,tuple):
                    ray.hole = circumcenter
                    t = (ray,SG_bisector,side,circumcenter)
                    if ray not in ray_list:
                        ray_list.add(ray)
                    clip_lines.append(t)
                else:
                    for r in ray:
                        r.hole = circumcenter
                        ray_list.add(r)
                    t = (ray,SG_bisector,side,circumcenter)
                    clip_lines.append(t)

            if circumcenter is not None:
                circumcenter.iscircumcenter = True
                #lower point is replaced by circumcenter
                SG_bisector.p2 = circumcenter


            #new SG
            px = SG.p1
            py = SG.p2
            SG_bisector = Line.biSector(SG.p1,SG.p2)
            SG_bisector._p1 = SG.p1
            SG_bisector._p2 = SG.p2

            HP.append(SG_bisector)
            firsttime = False
            #the end of while loop for HP


        if SG_bisector.p1.y > SG_bisector.p2.y:
            SG_bisector.p1,SG_bisector.p2 = SG_bisector.p2,SG_bisector.p1
        elif abs((SG_bisector.p1.y)-(SG_bisector.p2.y)) <= 0.00005:
            if SG_bisector.p1.x<SG_bisector.p2.x:
                SG_bisector.p1,SG_bisector.p2 = SG_bisector.p2,SG_bisector.p1


        newpl[SG.p1].append(pair(SG_bisector,SG.p2))
        newpl[SG.p2].append(pair(SG_bisector,SG.p1))

        for p in newpl.keys():
            for t in newpl[p]:
                p.related.append(t)

        if circumcenter is not None:
            SG_bisector.p1 = circumcenter


        #clip the unwanted lines
        VDL.parent.msg = VDL.parent.msg+ 'clip lines'+'\n'
        for t in clip_lines:
            ray = t[0]
            circumcenter = t[3]
            SG_bisector = t[1]
            side = t[2]
            discard_edges(ray,circumcenter,side,SG_bisector)

        #add new connected line
        s = 0
        for t in range(0,len(HP)-1):
            #need to add the intersected dividing chain
            HP[t].connected.append(HP[t+1])
            HP[t+1].connected.append(HP[t])
            #need to add the intersected ray
            if s  !=  len(clip_lines):
                if not isinstance(clip_lines[s][0],tuple):
                    HP[t].connected.append(clip_lines[s][0])
                    clip_lines[s][0].connected.append(HP[t])
                    HP[t+1].connected.append(clip_lines[s][0])
                    clip_lines[s][0].connected.append(HP[t+1])
                else:
                    r = clip_lines[s][0]
                    HP[t].connected.append(r[0])
                    r[0].connected.append(HP[t])
                    HP[t+1].connected.append(r[0])
                    r[0].connected.append(HP[t+1])

                    HP[t].connected.append(r[1])
                    r[1].connected.append(HP[t])
                    HP[t+1].connected.append(r[1])
                    r[1].connected.append(HP[t+1])

                    r[1].connected.append(r[0])
                    r[0].connected.append(r[1])
            s = s+1




        lines = []
        #lines = VDR.lines+VDL.lines+HP
        lines.append(VDR.lines)
        lines.append(VDL.lines)
        lines.append(HP)
        if VDL.parent.isstep_by_step == True:
            hp = []
            for h in HP:
                hp.append(Line(Point(h.p1.x,h.p1.y),Point(h.p2.x,h.p2.y)))
            VDR.parent.hp[0].append(hp)
        #VDR.parent.hp[0].append(copy.deepcopy(HP))
        range_points = (VDL.range_points[0],VDR.range_points[1])
        return VD(lines,range_points,VDR.parent)