Beispiel #1
0
    def find_tangent(VDL, VDR):
        pl = VDL.parent.points[VDL.range_points[1]]
        pr = VDR.parent.points[VDR.range_points[0]]

        #handle collinear point
        while not (VD.isupper_tangent(pl, pr, 'left')
                   and VD.isupper_tangent(pl, pr, 'right')):
            while not VD.isupper_tangent(pl, pr, 'left'):
                pl = pl.ccw
            while not VD.isupper_tangent(pl, pr, 'right'):
                pr = pr.cw

        upper_tangent = Line(pl, pr)

        #VDL.parent.msg = VDL.parent.msg + 'upper_tangent = '+upper_tangent.p1.display+' '+upper_tangent.p2.display+'\n'

        pl = VDL.parent.points[VDL.range_points[1]]
        pr = VDR.parent.points[VDR.range_points[0]]

        while not (VD.islower_tangent(pl, pr, 'left')
                   and VD.islower_tangent(pl, pr, 'right')):
            while not VD.islower_tangent(pl, pr, 'left'):
                pl = pl.cw
            while not VD.islower_tangent(pl, pr, 'right'):
                pr = pr.ccw

        lower_tangent = Line(pl, pr)

        #VDL.parent.msg =  VDL.parent.msg+'lower_tangent = '+lower_tangent.p1.display+' '+lower_tangent.p2.display+'\n'

        return (upper_tangent, lower_tangent)
Beispiel #2
0
    def step_by_step(self):
        self.parent.step_button.setEnabled(True)
        if not self.isstep_by_step == True:
            self.isstep_by_step = True
            self.prepare()
            final = self.Voronoi((0,len(self.points)-1))
            #for run after step
            self.lines = final.lines
            self.vertex = final.convex.vertex
            Line.intersect_with_edge(final.lines,Canvas.edge_painter)
            #final_vd = VD(copy.deepcopy(final.lines),copy.deepcopy(final.range_points),self)
            final_vd = savevd(final.lines,final.range_points,self,final.convex)
            final_vd.pos = 'final'
            final_vd.color = QtCore.Qt.black
            self.vd[0].append(final_vd)

        self.repaint()
        if self.vd[1] == len(self.vd[0])-1:
            self.drawDisplay.display_output()
        self.vd[1] = self.vd[1]+1
        if self.vd[1]  >= len(self.vd[0]):
            self.parent.step_button.setEnabled(False)
            self.vd = [[],0]
            self.hp = [[],0]
            self.isstep_by_step = False
Beispiel #3
0
    def step_by_step(self):
        self.parent.step_button.setEnabled(True)
        if not self.isstep_by_step == True:
            self.isstep_by_step = True
            self.prepare()
            final = self.Voronoi((0,len(self.points)-1))
            #for run after step
            self.lines = final.lines
            self.vertex = final.convex.vertex
            Line.intersect_with_edge(final.lines,Canvas.edge_painter)
            #final_vd = VD(copy.deepcopy(final.lines),copy.deepcopy(final.range_points),self)
            final_vd = savevd(final.lines,final.range_points,self,final.convex)
            final_vd.pos = 'final'
            final_vd.color = QtCore.Qt.black
            self.vd[0].append(final_vd)

        self.repaint()
        if self.vd[1] == len(self.vd[0])-1:
            self.drawDisplay.display_output()
        self.vd[1] = self.vd[1]+1
        if self.vd[1]  >= len(self.vd[0]):
            self.parent.step_button.setEnabled(False)
            self.vd = [[],0]
            self.hp = [[],0]
            self.isstep_by_step = False
Beispiel #4
0
 def test_cross_point_line(self):
     self.assertEqual(
         Circle(Point(2, 3),
                2).cross_point_line(Line(Point(0, 3), Point(1, 3))),
         [Point(0, 3), Point(4, 3)])
     self.assertEqual(
         Circle(Point(2, 3),
                2).cross_point_line(Line(Point(4, 0), Point(4, 6))),
         [Point(4, 3), Point(4, 3)])
Beispiel #5
0
def savevd(lines,range_points,self,convex):
    line = []
    for l in traverse(lines):
        p1 = copy.deepcopy(l.p1)
        p2 = copy.deepcopy(l.p2)
        t = Line(p1,p2)
        t.avail = l.avail
        line.append(t)
    return VD(line,range_points,self,convex = convex)
Beispiel #6
0
def savevd(lines,range_points,self,convex):
    line = []
    for l in traverse(lines):
        p1 = copy.deepcopy(l.p1)
        p2 = copy.deepcopy(l.p2)
        t = Line(p1,p2)
        t.avail = l.avail
        line.append(t)
    return VD(line,range_points,self,convex = convex)
Beispiel #7
0
def main() -> None:
    x1, y1, x2, y2 = [int(x) for x in input().split()]
    p1 = Point(x1, y1)
    p2 = Point(x2, y2)
    l = Line(p1, p2)

    q = int(input())

    for _ in range(q):
        x, y = [int(x) for x in input().split()]
        p = Point(x, y)
        a = l.reflection(p)
        print(a.x, a.y)
Beispiel #8
0
def prepare(size, polygons_info, start, end):
    '''
        something neccesary such as construct the whole picture
    '''
    polygons = generate_polygons(*polygons_info)
    for each in polygons:
        add_polygon_to_plot(each)
    start = Point(start)
    end = Point(end)
    points = [start]
    for polygon in polygons:
        points += polygon.vertices
    points += [end]

    #get successor_and_costs for every points
    for i in xrange(len(points)-1):
        # -1 for end point does not need to get successor
        point_i = points[i]
        siblings = [point_i]
        belonging = check_belonging(point_i, polygons)
        if belonging[0]:
            for each in belonging[1]:
                point_i.add_successor(each)
            siblings = belonging[2].vertices
        for other_point in points:
            if other_point in siblings:
                continue
            flag = True
            for polygon in polygons:
                if polygon.whether_intersect_line(Line((point_i, other_point))):
                    flag = False
                    break
            if flag:
                point_i.add_successor(other_point)
    return points
Beispiel #9
0
    def read_output(self):
        self.painter.drawDisplay.ClearCanvas()
        filename, _ = QtWidgets.QFileDialog.getOpenFileName()
        if filename:
            f = open(filename, 'r')
            lines = f.readlines()
            points = []
            _points = []
            for l in lines:
                t = l.split()
                if t[0] == 'P':
                    #need to create new attribute to save original point set which include duplicates
                    t1 = int(t[1])
                    t2 = int(t[2])
                    p = Point(t1, t2)
                    _points.append(p)
                    if p not in self.painter.points:
                        points.append(p)
                        self.painter.points.add((Point(t1, t2)))
                elif t[0] == 'E':
                    self.painter.lines.append(
                        Line(Point(int(t[1]), int(t[2])),
                             Point(int(t[3]), int(t[4]))))

            self.painter.points = points
            self.painter._points = _points
            for p in _points:
                self.painter.drawDisplay.display_points(p)
            self.painter.drawDisplay.display_output()
            self.painter.update()
            f.close()
Beispiel #10
0
    def set_self(self, start, end, image_dict, colour):
        self.line = Line(start, end)
        self.colour = colour
        line_length = int(
            round(pythagory(self.line.vector[0], self.line.vector[1])))
        w = line_length + 2 * PLATFORM.BORDER + 2 * PLATFORM.SIDE_GAP
        h = PLATFORM.IMAGE_HEIGHT
        base_image = pygame.Surface([w, h])
        base_image = base_image.convert_alpha()
        base_image.fill((1, 1, 1, 0))
        base_image.blit(image_dict['platform' + colour + '-left'], (0, 0))
        side_w = image_dict['platform' + colour + '-left'].get_width()
        for x in range(line_length / PLATFORM.MIDDLE_WIDTH):
            base_image.blit(image_dict['platform' + colour + '-middle'],
                            (side_w + x * PLATFORM.MIDDLE_WIDTH, 0))
        #if line_length%PLATFORM.MIDDLE_WIDTH != 0:
        base_image.blit(
            image_dict['platform' + colour + '-middle'],
            (side_w +
             (line_length / PLATFORM.MIDDLE_WIDTH) * PLATFORM.MIDDLE_WIDTH, 0),
            pygame.Rect(0, 0, line_length % PLATFORM.MIDDLE_WIDTH,
                        PLATFORM.IMAGE_HEIGHT))
        base_image.blit(image_dict['platform' + colour + '-right'],
                        (w - side_w, 0))

        self.image = pygame.transform.rotozoom(
            base_image, -vector_to_angle(self.line.vector) - 90, 1.0)
        self.image_position = start[
            0] - self.line.vector[0] / 2 - self.image.get_width() / 2, start[
                1] - self.line.vector[1] / 2 - self.image.get_height() / 2
Beispiel #11
0
 def draw(self, vis_graph):
     '''Draws the shape and a line connecting the node to its parent'''
     self.shape.draw()
     if self.node.parent != None:
         if self.is_path is True:
             parent = vis_graph.get_visual(self.node.parent)
             parent_line = Line(self.position, parent.position, self.shape.surface, (150,255,25),1)
             parent_line.draw()
         else:
             parent = vis_graph.get_visual(self.node.parent)
             parent_line = Line(self.position, parent.position, self.shape.surface, (150,50,50),1)
             parent_line.draw()
Beispiel #12
0
 def createLine(self, x1, y1, x2, y2, strokewidth=1, stroke="black"):
     """
     Creates a line
     @type  x1: string or int
     @param x1:  starting x-coordinate
     @type  y1: string or int
     @param y1:  starting y-coordinate
     @type  x2: string or int
     @param x2:  ending x-coordinate
     @type  y2: string or int
     @param y2:  ending y-coordinate
     @type  strokewidth: string or int
     @param strokewidth:  width of the pen used to draw
     @type  stroke: string (either css constants like "black" or
      numerical values like "#FFFFFF")
     @param stroke:  color with which to draw the outer limits
     @return:  a line object
     """
     style_dict = {'stroke-width': strokewidth, 'stroke': stroke}
     myStyle = StyleBuilder(style_dict)
     l = Line(x1, y1, x2, y2)
     l.set_style(myStyle.getStyle())
     return l
Beispiel #13
0
    def Run(self):
        if self.isstep_by_step == False:
            self.prepare()
            ans = self.Voronoi((0,len(self.points)-1))
            Line.intersect_with_edge(ans.lines,Canvas.edge_painter)
            self.lines = ans.lines
            self.vertex = ans.convex.vertex
            self.drawDisplay.display_output()
            self.update()
        else:
            #current state is step_by_step, switch to run all vd
            while True:
                self.parent.step_button.setEnabled(False)
                self.repaint()
                if self.vd[1] == len(self.vd[0])-1:
                    self.drawDisplay.display_output()
                time.sleep(1)
                self.vd[1] = self.vd[1]+1
                if self.vd[1]  >= len(self.vd[0]):
                    break

            self.vd = [[],0]
            self.hp = [[],0]
            self.isstep_by_step = False
Beispiel #14
0
 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
Beispiel #15
0
 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
Beispiel #16
0
    def Run(self):
        if self.isstep_by_step == False:
            self.prepare()
            ans = self.Voronoi((0,len(self.points)-1))
            Line.intersect_with_edge(ans.lines,Canvas.edge_painter)
            self.lines = ans.lines
            self.vertex = ans.convex.vertex
            self.drawDisplay.display_output()
            self.update()
        else:
            #current state is step_by_step, switch to run all vd
            while True:
                self.parent.step_button.setEnabled(False)
                self.repaint()
                if self.vd[1] == len(self.vd[0])-1:
                    self.drawDisplay.display_output()
                time.sleep(1)
                self.vd[1] = self.vd[1]+1
                if self.vd[1]  >= len(self.vd[0]):
                    break

            self.vd = [[],0]
            self.hp = [[],0]
            self.isstep_by_step = False
Beispiel #17
0
 def __init__(self, type, img_dict, obj, position_or_angle):
     Monster.__init__(self)
     self.type = type
     self.has_line = True
     self.border = MONSTER.EYE.RADIUS
     self.frame = 0
     if self.type == MONSTER.TYPE_ANGLE: # count start_position
         self.start = sum(obj.circle.center, multiply(angle_to_vector(position_or_angle), obj.circle.radius + MONSTER.EYE.RADIUS))
         self.angle = position_or_angle
         self.vector = angle_to_vector(self.angle)
     else:
         self.vector = inverse(perpendicular(normalise(obj.line.vector)))
         shift = multiply(obj.line.vector, -position_or_angle/100.0) # side shift
         self.start = sum(sum(obj.line.start, multiply(self.vector, PLATFORM.BORDER - 3 + MONSTER.EYE.RADIUS)), shift)
         self.angle = vector_to_angle(self.vector)
     end = sum(self.start, multiply(self.vector, MONSTER.EYE.LINE_LENGTH))
     self.line = Line(self.start, end)
     self.img_list = []
     for i in img_dict['eye']:
         self.img_list.append(pygame.transform.rotozoom(i, -self.angle,1.))
     self.shift_constant = img_dict['eye'][0].get_height()/2 - MONSTER.EYE.RADIUS
     self.image_offset = subtract(multiply(self.vector, self.shift_constant), (self.img_list[0].get_width()/2, self.img_list[0].get_height()/2))
     self.image_position = sum(self.start, self.image_offset)
     self.image = self.img_list[0]
Beispiel #18
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
Beispiel #19
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
Beispiel #20
0
        # cv2.drawContours(img, [box], 0, (0, 255,0), 2)

        # Fit line trough the shape
          # img: width, height
        # https://docs.opencv.org/3.1.0/d3/dc0/group__imgproc__shape.html#gaf849da1fdafa67ee84b1e9a23b93f91f
        # Output line parameters. In case of 2D fitting, it should be a vector of 4 elements (like Vec4f) - (vx, vy, x0, y0),
        # where (vx, vy) is a normalized vector collinear to the line and (x0, y0) is a point on the line.
        [vx, vy, x, y] = cv2.fitLine(c, cv2.DIST_L2, 0, 0.01, 0.01)
        lefty = int((-x * vy / vx) + y)
        righty = int(((cols - x) * vy / vx) + y)

        point1 = (cols - 1, righty)
        point2 = (0, lefty)

        # cv2.line(img, point1, point2, (0, 255, 0), 2)
        newline = Line((cX, cY), point1, point2, img_center)

        lines.append(newline)
        # plt.plot([cols - 1, righty], [0, lefty], color='k', linestyle='-', linewidth=2)
        # break

    lines.sort(key=lambda l: l.angle)

    bestline = Line((int(cols / 2), int(rows / 2)), (0, int(rows / 2)), (cols, int(rows / 2)), img_center) # Initial best line is worst ever, 90 degrees with flight path

    # find all good lines (closest to Y axis)
    goodlines = []
    for l in lines:
        if l.angle < abs(bestline.angle):
            goodlines.append(l)
Beispiel #21
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)
Beispiel #22
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)
Beispiel #23
0
class Canvas(QtWidgets.QWidget):
    edge_painter = (Line(Point(0,0),Point(610,0)),Line(Point(0,0),Point(0,610)),Line(Point(610,0),Point(610,610)),Line(Point(0,610),Point(610,610)))
    def __init__(self,parent = None):
        super(Canvas, self).__init__()
        self.IOData = IOData(self)
        self.drawDisplay = drawDisplay(self)
        self.parent = parent
        self.points = []
        #used to output original points include duplicate
        self._points = []
        self.lines = []
        self.vd = [[],0]
        self.tangent = [[],0]
        self.hp = [[],0]
        self.isstep_by_step = False
        self.debug_message = [[],0]
        self.msg = ""
        self.vertex = []
        self.setMouseTracking(True)

    def mousePressEvent(self,event):
        p = Point(event.x(),event.y())
        self._points.append(p)
        if p not in self.points:
            self.points.append(p)
        self.drawDisplay.display_points(p)
        self.update()

    def mouseMoveEvent(self, event):
        self.parent.mouse_location.setText("("+event.x().__str__()+","+event.y().__str__()+")")

    def paintEvent(self, event):
        qp = QtGui.QPainter()
        qp.begin(self)
        #print 'paintEvent'
        self.drawDisplay.drawPoints(qp)
        self.drawDisplay.drawLines(qp)
        qp.end()

    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

    def prepare(self):
        pset = set(self.points)
        self.points = []
        for p in pset:
            self.points.append(p)
        self.points.sort(key= attrgetter('x','y'))

    def Run(self):
        if self.isstep_by_step == False:
            self.prepare()
            ans = self.Voronoi((0,len(self.points)-1))
            Line.intersect_with_edge(ans.lines,Canvas.edge_painter)
            self.lines = ans.lines
            self.vertex = ans.convex.vertex
            self.drawDisplay.display_output()
            self.update()
        else:
            #current state is step_by_step, switch to run all vd
            while True:
                self.parent.step_button.setEnabled(False)
                self.repaint()
                if self.vd[1] == len(self.vd[0])-1:
                    self.drawDisplay.display_output()
                time.sleep(1)
                self.vd[1] = self.vd[1]+1
                if self.vd[1]  >= len(self.vd[0]):
                    break

            self.vd = [[],0]
            self.hp = [[],0]
            self.isstep_by_step = False

    def step_by_step(self):
        self.parent.step_button.setEnabled(True)
        if not self.isstep_by_step == True:
            self.isstep_by_step = True
            self.prepare()
            final = self.Voronoi((0,len(self.points)-1))
            #for run after step
            self.lines = final.lines
            self.vertex = final.convex.vertex
            Line.intersect_with_edge(final.lines,Canvas.edge_painter)
            #final_vd = VD(copy.deepcopy(final.lines),copy.deepcopy(final.range_points),self)
            final_vd = savevd(final.lines,final.range_points,self,final.convex)
            final_vd.pos = 'final'
            final_vd.color = QtCore.Qt.black
            self.vd[0].append(final_vd)

        self.repaint()
        if self.vd[1] == len(self.vd[0])-1:
            self.drawDisplay.display_output()
        self.vd[1] = self.vd[1]+1
        if self.vd[1]  >= len(self.vd[0]):
            self.parent.step_button.setEnabled(False)
            self.vd = [[],0]
            self.hp = [[],0]
            self.isstep_by_step = False
Beispiel #24
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
Beispiel #25
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