Пример #1
0
    def _remove(self, site, points, triangles):
        '''
        Update the triangulation by removing the surrounding triangles 
        and then filling this cavity with new Delaunay triangles.
        Challenge: Maintain neighborhood control.
        Ref: Mir Abolfazl Mostafavi, Christopher Gold, and Maciej Dakowicz. 
             2003. Delete and insert operations in Voronoi/Delaunay methods 
             and applications. Comput. Geosci. 29, 4 (May 2003), 523-530. 
             DOI=10.1016/S0098-3004(03)00017-7 
             http://dx.doi.org/10.1016/S0098-3004(03)00017-7
        '''
        # verify compatibility of surrounding points and old triangles
        if len(points) != len(triangles):
            raise Exception("Triangulation has different sizes.")
        # verify is the triangulation is empty (or insufficient?)
        if len(points) < 3:
            return
        # initialize new triangulation controls
        i = -1
        new_triangles = {}
        # while there are points to form more than the last triangle
        while len(points) > 3:
            # checks the possible triangles considering 
            # all three consecutive points (i, i1, i2 in a cycle) 
            # of surrounding points of the site
            i += 1
            npoints = len(points)
            if (i >= npoints):
                raise Exception("Inexists a valid ear? Is it possible?")
            i1 = (i + 1) % npoints
            i2 = (i1 + 1) % npoints
            # verify if points represent a valid triangle to site,
            # like a ear listen to the site:
            # 1: gets triangle orientation (CW or CCW)
            o_ear = Triangle.orientation(points[i], points[i1], points[i2])
            # 2: gets direction of triangle to the site (CW or CCW)
            o_ear_site = Triangle.orientation(points[i], points[i2], site)
            # 3: if points are collinear, try another edge as a reference
            # ??why don't take this edge at first place??
            if o_ear_site == 0:
                o_ear_site = Triangle.orientation(points[i], points[i1], site)
            # 4: the directions is the same?
            if (o_ear * o_ear_site) > 0:
                # if so, this a valid ear (possible triangulation)
                valid_ear = Triangle(points[i], points[i1], points[i2])
                # verify if this ear is a Delaunay Triangulation
                ear_is_delaunay = True
                # 1. for all other surrounding points
                for p in points:
                    # 1.1: is this other point (not in ear)?
                    if not valid_ear.contains(p):
                        # verify if ear won't circumcircle it
                        if valid_ear.circumscribe(p):
                            # if circumcircle, ear is not a Delaunay triangle
                            ear_is_delaunay = False
                            break
                # if it is a Delaunay triangle...
                if ear_is_delaunay:
                    # include to new triangle control
                    new_triangles[valid_ear] = None
                    # include to neighborhood control
                    self.neighborhood[valid_ear] = {}
                    # link to the opposite triangles from the removed vertices
                    self._link_ear(site, valid_ear, triangles[i], 
                                   new_triangles)
                    self._link_ear(site, valid_ear, triangles[i1], 
                                   new_triangles)
                    # change triangle related to vertex by the new one
                    # remove old triangle by switching the diagonal
                    triangles[i] = valid_ear
                    # remove middle point (leave the corners) 
                    del points[i1]
                    del triangles[i1]
                    # restart cycle of surrounding points
                    i = -1
        # if has only three neighbours remaining in the surrounding points, 
        # merged these three points (triangles) into last triangulation
        last_ear = Triangle(points[0], points[1], points[2])
        self.neighborhood[last_ear] = {}
        new_triangles[last_ear] = None
        # last triangle closes the triangulation and 
        # needs update the link with all sides (neighborhood)
        self._link_ear(site, last_ear, triangles[0], new_triangles)
        self._link_ear(site, last_ear, triangles[1], new_triangles)
        self._link_ear(site, last_ear, triangles[2], new_triangles)

        if self.main_site is not None:
            if self.main_site == site:
                self.main_site = None
        self._new_version()
        if self.check_triangulation:
            if not self.valid():
                print "### Removing failure"