Пример #1
0
 def _eval_derivs_boundary(self):
    import numpy as np
    import geometry_planar as GP
    
    # get x,y for boundary
    x,y      = GP.coords2xy(self.coords)
    F_x,F_y  = self.eval_gradient(x,y)
    
    # get tangent derivative
    ctd   = np.cos(self.tangent_dirn)
    std   = np.sin(self.tangent_dirn)
    F_s   = ctd*F_x+std*F_y
    
    # get normal derivative
    F_n   = -std*F_x + ctd*F_y
    
    # get stream function on boundary:
    # G_s = -F_n -> integrate
    G	 = np.zeros(len(x))
    Nc = len(x)
    for n in range(1,Nc):
       Gs    = -F_n[n]
       ds    = self.spacings[n]
       G[n]  = G[n-1]+Gs*ds
    
    self.tangent_deriv	= F_s
    self.normal_deriv		= F_n
    self.stream_func		= G
    return
Пример #2
0
   def _eval_solution_boundary(self):
      import geometry_planar as GP
      
      # get x,y for boundary
      x,y   = GP.coords2xy(self.coords)
      
      # evaluate func on boundary
      self.func_vals_approx   = self.eval_solution_fast(x,y)
      
      # calculate error
      self.boundary_error  = GP.vector_norm(self.func_vals-self.func_vals_approx)\
      			      /GP.vector_norm(self.func_vals)

      return
Пример #3
0
    def _get_arctan2_constants(self):

        # disjoint polygons
        MPlist = self.disjoint_polygons
        Ncl = len(MPlist)
        isec_types = self.intersection_types

        # connected polygons
        pol_conn = self.connected_polygon
        const_atan2 = []
        const_atan2_bdy = []

        #####################################################################################################
        # loop over disjoint polygons
        for i in range(Ncl):
            pol_disj = MPlist[i]
            int_bdy = isec_types.crossing_lines[i]
            Li = int_bdy.length

            # to see jump across int_bdy, get 2 points
            # - one from just inside pol_conn
            # - one from just inside pol_disj
            pic = int_bdy.centroid
            dsk_c = pic.buffer(1.e-4 * Li / 2.).intersection(pol_conn)
            dsk_d = pic.buffer(1.e-4 * Li / 2.).intersection(pol_disj)
            xi, yi = GP.coords2xy(pic.coords)
            xc, yc = GP.coords2xy(dsk_c.centroid.coords)
            xd, yd = GP.coords2xy(dsk_d.centroid.coords)

            Ac = GP.arctan2_branch(yc - y0, xc - x0, branch_dir=linedir)
            Ad = GP.arctan2_branch(yd - y0, xd - x0, branch_dir=linedir)
            Ai = GP.arctan2_branch(yi - y0, xi - x0, branch_dir=linedir)

            ##################################################################################################
            # correction inside the disjoint polygon
            if Ad < Ac - np.pi:
                const_atan2.append(
                    1
                )  # need to add 2*pi to Ad to make it continuous across the boundary
            elif Ad > Ac + np.pi:
                const_atan2.append(
                    -1
                )  # need to add -2*pi to Ad to make it continuous across the boundary

            # correction on the boundary itself
            if Ai < Ac - np.pi:
                const_atan2_bdy.append(
                    1
                )  # need to add 2*pi to Ai to make it continuous across the boundary
            elif Ai > Ac + np.pi:
                const_atan2_bdy.append(
                    -1
                )  # need to add -2*pi to Ai to make it continuous across the boundary
            else:
                const_atan2_bdy.append(
                    0)  # arctan2_branch is continous approaching the boundary
                # (the jump is just after the boundary)
            ##################################################################################################

            self.corrections_internal = const_atan2
            self.corrections_boundary = const_atan2_bdy
        # finish loop over disjoint polygons
        #####################################################################################################

        return
Пример #4
0
        pol_conn = MPlist[-1]
        const_atan2 = []
        const_atan2_bdy = []

        for i in range(Ncl):
            pol_disj = MPlist[i]
            int_bdy = isec_types.crossing_lines[i]
            Li = int_bdy.length

            # to see jump across int_bdy, get 2 points
            # - one from just inside pol_conn
            # - one from just inside pol_disj
            pic = int_bdy.centroid
            dsk_c = pic.buffer(1.e-4 * Li / 2.).intersection(pol_conn)
            dsk_d = pic.buffer(1.e-4 * Li / 2.).intersection(pol_disj)
            xi, yi = GP.coords2xy(pic.coords)
            xc, yc = GP.coords2xy(dsk_c.centroid.coords)
            xd, yd = GP.coords2xy(dsk_d.centroid.coords)

            Ac = GP.arctan2_branch(yc - y0, xc - x0, linedir=linedir)
            Ad = GP.arctan2_branch(yd - y0, xd - x0, linedir=linedir)
            Ai = GP.arctan2_branch(yi - y0, xi - x0, linedir=linedir)

            # print('**************************************************')
            # print('getting arctan2 constants')
            # print(pol_disj)
            # print(pol_conn)
            # print(pic)
            # print((xc,yc))
            # print((xd,yd))
            # print(' ')
Пример #5
0
   def plot_solution(self,pobj=None,plot_boundary=True,show=True,\
         cbar=True,**kwargs):

      import numpy            as np
      import shapefile_utils  as SFU
      import geometry_planar  as GP
      from matplotlib import cm
      from matplotlib import pyplot as plt
      
      if pobj is None:
         # set a plot object if none exists
         fig = plt.figure()
         ax  = fig.add_subplot(1,1,1)
      else:
         fig,ax   = pobj
      
      if plot_boundary:
         # just plot values of F at boundary
         ss = self.get_arc_length()/1.e3 # km
         ax.plot(ss,self.func_vals_approx,'b',**kwargs)
         ax.plot(ss,self.func_vals,'.k',**kwargs)

         x2,y2  = np.array(self.coords).transpose() # coords can be reversed
         f2     = self.eval_solution_fast(x2,y2)
         ax.plot(ss,f2,'--r',**kwargs)
         xc  = np.round(10.*self.coords[0][0]/1.e3)/10. # km (1dp)
         yc  = np.round(10.*self.coords[0][1]/1.e3)/10. # km (1dp)
         ax.set_xlabel('arc length (km) from '+str((xc,yc))+' (km)')
         ax.set_ylabel('values of target function')

      else:
         # plot F everywhere
         bbox	= self.shapely_polygon.bounds
         eps	= self.resolution/2.

         # get a grid to plot F on:
         x0  = bbox[0]
         y0  = bbox[1]
         x1  = bbox[2]
         y1  = bbox[3]
         x   = np.arange(x0,x1+eps,eps)
         y   = np.arange(y0,y1+eps,eps)
         xp  = np.arange(x0-.5*eps,x1+1.5*eps,eps)/1.e3 #km
         yp  = np.arange(y0-.5*eps,y1+1.5*eps,eps)/1.e3

         # make pcolor/contour plot
         nlevels  = 10
         vmin	  = self.func_vals.min()
         vmax	  = self.func_vals.max()
         dv	  = (vmax-vmin)/(nlevels)
         vlev	  = np.arange(vmin,vmax+dv,dv)
         #
         X,Y	= np.meshgrid(x,y)
         F	= self.eval_solution(X,Y)
         #
         cmap	= cm.jet
         cmap.set_bad(color='w')
         Fm  = np.ma.array(F,mask=np.isnan(F))

         ##################################################################
         if 'basemap' not in str(type(ax)):
            # plotter is not a basemap (eg a normal axis object)
            PC  = ax.pcolor(xp,yp,Fm,vmin=vmin,vmax=vmax,cmap=cmap,**kwargs)
            if cbar:
               fig.colorbar(PC)
            ax.contour(X/1.e3,Y/1.e3,F,vlev,colors='k',**kwargs)

            # plot polygon boundary
            x,y   = GP.coords2xy(self.coords)
            ax.plot(x/1.e3,y/1.e3,'k',linewidth=2,**kwargs)

            # plot singularities
            x,y   = GP.coords2xy(self.singularities)
            ax.plot(x/1.e3,y/1.e3,'.k',markersize=5)

            # axes labels
            ax.set_xlabel('x, km')
            ax.set_ylabel('y, km')
         else:
            # plotter is a basemap

            # NB need units in m for basemap
            PC = ax.pcolor(xp*1e3,yp*1e3,Fm,vmin=vmin,vmax=vmax,cmap=cmap,**kwargs)
            if cbar:
               fig.colorbar(PC)

            # plot outline
            x,y   = GP.coords2xy(self.coords)
            ax.plot(x,y,'k',linewidth=2,**kwargs)

            # plot singularities
            x,y   = GP.coords2xy(self.singularities)
            ax.plot(x,y,'.k',markersize=5,**kwargs)
         ##################################################################

      if show:
         plt.show(fig)

      return
	def __init__(self,coords,func_vals,singularities=None):
			# initialise object

			import numpy as np
			import shapely.geometry as shgeom # http://toblerity.org/shapely/manual.html
			import geometry_planar	as GP 	  # also in py_funs
			import rtree.index	as Rindex

			#######################################################
			self.func_vals = np.array(func_vals)
			self.coords		= 1*coords # no longer pointer to list from outside the function
			pcoords				= 1*coords

			if (pcoords[0][0]!=pcoords[-1][0]) and (pcoords[0][1]!=pcoords[-1][1]):
				# not periodic
				# - BUT need last and first coordinate the same for shapely polygon
				print('not periodic')
				pcoords.append(pcoords[0])
			#######################################################

			#######################################################
			# make shapely polygon
			# (coords now has end-point repeated,
			#	self.coords doesn't)
			self.shapely_polygon	= shgeom.Polygon(pcoords)
			#######################################################
			
			#######################################################
			# want to go round curve anti-clockwise
			x,y				= GP.coords2xy(self.coords)
			area				= GP.area_polygon_euclidean(x,y)
			self.area	= abs(area)

			if area<0:
				print("Curve traversed in clockwise direction - reversing arrays' order")
				self.func_vals = list(self.func_vals)
				self.func_vals.reverse()
				self.func_vals = np.array(self.func_vals)
				#
				self.coords		= list(self.coords)
				self.coords.reverse()
				self.coords		= self.coords

			# make rtree index
			idx	= Rindex.Index()
			for i,(xp,yp) in enumerate(self.coords):
				idx.insert(i,(xp,yp,xp,yp)) # a point is a rectangle of zero side-length
			self.coord_index	= idx
			#######################################################

			self.number_of_points	= len(self.coords)

			# gets spacings,directions between points, and perimeter
			self.perimeter,self.resolution,\
						self.spacings,self.tangent_dirn	= GP.curve_info(self.coords)
			#

			# get points around boundary of polygon, then
			# expand points by an amount related to the spacings of the coords
			self.buffer_resolution	= 16 # default buffer resolution
																	# (number of segments used to approximate a quarter circle around a point.)

			# self.solve_exactly	= solve_exactly
			# # if True: number of singularities and number of boundary points should be the same

			if singularities is None:
				get_sings = True
			else:
				get_sings		       = False
				self.singularities	       = singularities 
				self.number_of_singularities   = len(self.singularities)
				print('Number of boundary points : '+str(self.number_of_points))
				print('Number of singularities	: '+str(self.number_of_singularities)+'\n')

			while get_sings:
				# May need a couple of repetitions if too few singularities are found
				get_sings	= self._get_singularities()

			# solve Laplace's eqn (get a_n)
			self._solve_laplace_eqn()

			# # evaluate error on boundary:
			print('\nCalculating error on the boundary...')
			self._eval_solution_boundary()
			print(str(self.boundary_error)+'\n')

			if 0:
				# evaluate normal derivative -> stream function on boundary:
				print('\nCalculating normal derivative -> stream function on the boundary...\n')
				self._eval_derivs_boundary()

			elif 1:
				# use analytical definition of stream function
				# - for log, this is arctan2 (+const)
				self._get_stream_func_bdy()

			return
Пример #7
0
    if isec.geom_type == 'LineString':
        # 1 intersection
        print(isec.coords)
        Ni = 1
    elif isec.geom_type == 'Point':
        Ni = -1
    else:
        Ni = len(isec.geoms)
        if Ni > 0:
            # just use 1 pair (1st/last):
            c0 = isec.geoms[0].coords[0]
            c1 = isec.geoms[-1].coords[-1]
            isec = shgeom.LineString([c0, c1])

    xp, yp = GP.coords2xy(rect0)
    plt.plot(xp, yp, 'b')

    xl, yl = ll.coords.xy
    plt.plot(xl, yl, 'k')

    xi, yi = isec.coords.xy
    plt.plot(xi, yi, '.g')

    if Ni > 0:
        if 1:
            print('shortest')
            clst = GP.line_splits_polygon(pol, isec, shortest=True)
        else:
            print('longest')
            clst = GP.line_splits_polygon(pol, isec, shortest=False)