Пример #1
0
    def boundary_envelope(self,node):
        """ return a polygon that approximates the region that
        a boundary node can move in without disrupting the
        boundary too much
        """
        # find it's boundary neighbors:
        edges = self.edges[self.pnt2edges( node )]

        boundary_nodes = unique( edges[ edges[:,4]==-1,:2 ] )
        if len(boundary_nodes) != 3:
            print "How can node %i not have some friends on the boundary?"%node
            print boundary_nodes
            
        nodeA,nodeC = setdiff1d(boundary_nodes,[node])

        offset = 0.03 # nodes can move 0.1 of the segment length

        pntA = self.points[nodeA,:2]
        pntB = self.points[node,:2]
        pntC = self.points[nodeC,:2]

        tot_length = norm(pntA-pntB) + norm(pntB-pntC)

        # first, the rectangle based on AB
        AB_unit = (pntB-pntA)/norm(pntB-pntA)
        perp_vec = offset*tot_length*rot(pi/2,AB_unit)

        pntNW = pntA+perp_vec
        pntSW = pntA-perp_vec

        pntNE = pntA + AB_unit*tot_length + perp_vec
        pntSE = pntA + AB_unit*tot_length - perp_vec

        AB_ring = array([pntNW,pntSW,pntSE,pntNE])

        AB_geom = geometry.Polygon( AB_ring )

        # and the rectangle based on BC
        CB_unit = (pntB-pntC)/norm(pntB-pntC)
        perp_vec = offset*tot_length*rot(pi/2,CB_unit)

        pntNW = pntC+perp_vec
        pntSW = pntC-perp_vec

        pntNE = pntC + CB_unit*tot_length + perp_vec
        pntSE = pntC + CB_unit*tot_length - perp_vec

        CB_ring = array([pntNW,pntSW,pntSE,pntNE])

        CB_geom = geometry.Polygon( CB_ring )

        return CB_geom.intersection(AB_geom)
Пример #2
0
def free_node_bounds(points,max_angle=85*pi/180. ):
    """ assumed that the first point can be moved and the
    other two are fixed

    returns an array of vertices that bound the legal region
    for the free node

    currently this uses four vertices to approximate the shape
    of the region
    """
    
    # try to construct a tight-ish bound on the legal locations for
    # one node of a triangle where the other two nodes are constrained
    if len(points) == 3:
        orig_pntC = points[0]

        pntA = points[1]  # should be oriented such that with A,B,C is CCW
        pntB = points[2]

        # make sure the orientation is correct:
        if dot( rot(pi/2,(pntB-pntA)),orig_pntC - pntA) < 0:
            pntA,pntB = pntB,pntA
    else:
        # we got only the fixed points, which are assumed to be CCW, with
        # free point to the left of AB
        pntA,pntB = points
        
    # point at the tip of the triangle:
    pntC1 = 0.5*(pntA+pntB) + rot(pi/2,pntB-pntA)*tan(max_angle)/2

    # closest legal point to pntA:
    pntC2 = pntB + rot(-(pi-2*max_angle), pntA-pntB)
    # closest legal point to pntB:
    pntC3 = pntA + rot(pi-2*max_angle, pntB-pntA)

    # and find the closest point in the middle
    min_isosc_angle = (pi - max_angle)/2
    pntC4 = 0.5*(pntA+pntB) + rot(pi/2,(pntB-pntA))*tan(min_isosc_angle)/2

    if 0:
        C_edges = array([pntC2,pntC1,pntC3,pntC4,pntC2])
        plot( C_edges[:,0],C_edges[:,1],'c')

    return array( [pntC2,pntC1,pntC3,pntC4] )
Пример #3
0
 def rotate_grid(self,angle):
     """ rotates the oversized grid and translates to get the origin in the right place.
     """
     # translate to get centered on the extra bit we asked for:
     self.points[:] -= 2*self.dens
     # rotate
     self.points[:] = trigrid.rot(angle,self.points)
     # and get our origin to a nice place
     self.points[:,0] += self.final_L * np.sin(angle)**2
     self.points[:,1] -= self.final_L * np.sin(angle)*np.cos(angle)
Пример #4
0
 def rotate_grid(self, angle):
     """ rotates the oversized grid and translates to get the origin in the right place.
     """
     # translate to get centered on the extra bit we asked for:
     self.points[:] -= 2 * self.dens
     # rotate
     self.points[:] = trigrid.rot(angle, self.points)
     # and get our origin to a nice place
     self.points[:, 0] += self.final_L * np.sin(angle)**2
     self.points[:, 1] -= self.final_L * np.sin(angle) * np.cos(angle)
Пример #5
0
def free_node_bounds_conservative(points,max_angle=85*pi/180.):
    """ Given the two points, with the intended third point lying
    to the left, return points describing a polygon the ensures a
    relatively nice triangle.

    here nice means that we take the closest point that the new
    vertex can be, and force the new point to be at least that
    far away, so avoiding narrow isosceles triangles.
    """
    pntA,pntB = points
        
    # point at the tip of the triangle:
    pntC1 = 0.5*(pntA+pntB) + rot(pi/2,pntB-pntA)*tan(max_angle)/2

    l_ab = norm(pntB - pntA)
    
    l_leg = l_ab*0.5 / (tan(max_angle/2.) * sin(max_angle) )

    pntC2 = pntA + l_leg * (pntC1-pntA) / norm(pntC1-pntA)
    pntC3 = pntB + l_leg * (pntC1-pntB) / norm(pntC1-pntB)
    
    arc_points = [pntC1,pntC2,pntC3]
    
    return array( arc_points )
Пример #6
0
def free_node_bounds_fine(points,max_angle=85*pi/180.,region_steps=3 ):
    """ assumed that the first point can be moved and the
    other two are fixed

    returns an array of vertices that bound the legal region
    for the free node

    this version discretizes the curved boundary with variable number of
    nodes
    """
    
    # try to construct a tight-ish bound on the legal locations for
    # one node of a triangle where the other two nodes are constrained

    if len(points) == 3:
        orig_pntC = points[0]

        pntA = points[1]  # should be oriented such that with A,B,C is CCW
        pntB = points[2]

        # make sure the orientation is correct:
        if dot( rot(pi/2,(pntB-pntA)),orig_pntC - pntA) < 0:
            pntA,pntB = pntB,pntA
    else:
        # we got only the fixed points, which are assumed to be CCW, with
        # free point to the left of AB
        pntA,pntB = points
        
    # point at the tip of the triangle:
    pntC1 = 0.5*(pntA+pntB) + rot(pi/2,pntB-pntA)*tan(max_angle)/2

    # # closest legal point to pntA:
    # pntC2 = pntB + rot(-(pi-2*max_angle), pntA-pntB)
    # # closest legal point to pntB:
    # pntC3 = pntA + rot(pi-2*max_angle, pntB-pntA)

    min_angle_A = pi - 2*max_angle
    max_angle_A = max_angle

    arc_points = [pntC1]
    
    for angle_A in linspace(min_angle_A,max_angle_A,region_steps):
        # too lazy to write robust predicate here - just dish it out
        # to shapely
        angle_B = pi-max_angle-angle_A
        # 10 is overkill - I think this can easily be bounded by
        # the dimensions of the equilateral
        Aray = pntA + rot(angle_A,10*(pntB-pntA))
        Bray = pntB + rot(-angle_B,10*(pntA-pntB))
        Aline = geometry.LineString([pntA,Aray])
        Bline = geometry.LineString([pntB,Bray])
        
        crossing = Aline.intersection(Bline)
        try:
            new_point = array(crossing.coords[0])
        except:
            print "Couldn't find intersection of",crossing
            print Aline
            print Bline
            raise

        arc_points.append(new_point)
        
    arc_points = array(arc_points)
        
    return array( arc_points )