def gen_sine_sine(): t = np.linspace(1.0,12*np.pi,400) x1 = 100*t y1 = 200*np.sin(t) # each 2*pi, the radius gets bigger by exp(2pi*b) x2 = x1 y2 = y1+50 # now perturb both sides, but keep amplitude < 20 y1 = y1 + 20*np.sin(10*t) y2 = y2 + 10*np.cos(5*t) x = np.concatenate( (x1,x2[::-1]) ) y = np.concatenate( (y1,y2[::-1]) ) shore = np.swapaxes( np.concatenate( (x[None,:],y[None,:]) ), 0,1) rings = [shore] # and make some islands: north_island_shore = 0.4*y1 + 0.6*y2 south_island_shore = 0.6*y1 + 0.4*y2 Nislands = 20 # islands same length as space between islands, so divide # island shorelines into 2*Nislands blocks for i in range(Nislands): i_start = int( (2*i+0.5)*len(t)/(2*Nislands) ) i_stop = int( (2*i+1.5)*len(t)/(2*Nislands) ) north_y = north_island_shore[i_start:i_stop] south_y = south_island_shore[i_start:i_stop] north_x = x1[i_start:i_stop] south_x = x2[i_start:i_stop] x = np.concatenate( (north_x,south_x[::-1]) ) y = np.concatenate( (north_y,south_y[::-1]) ) island = np.swapaxes( np.concatenate( (x[None,:],y[None,:]) ), 0,1) rings.append(island) density = field.ConstantField(25.0) min_density = field.ConstantField(2.0) p = paver.Paving(rings,density=density,min_density=min_density) print("Smoothing to nominal 1.0m") # mostly just to make sure that long segments are # sampled well relative to the local feature scale. p.smooth() print("Adjusting other densities to local feature size") p.telescope_rate=1.1 p.adjust_density_by_apollonius() return p
def test_embedded_channel(): assert False # no API yet. # trying out degenerate internal lines - the trick may be mostly in # how to specify them. # make a large rectangle, with a sinuous channel in the middle L = 500.0 W = 300.0 rect = np.array([[0, 0], [L, 0], [L, W], [0, W]]) x = np.linspace(0.1 * L, 0.9 * L, 50) y = W / 2 + 0.1 * W * np.cos(4 * np.pi * x / L) shore = np.swapaxes(np.concatenate((x[None, :], y[None, :])), 0, 1) density = field.ConstantField(10) # this will probably get moved into Paver itself. # Note closed_ring=0 ! shore = resample_linearring(shore, density, closed_ring=0) south_shore = shore - np.array([0, 0.1 * W]) north_shore = shore + np.array([0, 0.1 * W]) p = paver.Paving([rect], density, degenerates=[north_shore, south_shore]) p.pave_all()
def test_long_channel(): l = 2000 w = 50 long_channel = np.array([[0, 0], [l, 0], [l, w], [0, w]], np.float64) density = field.ConstantField(19.245) trifront_wrapper([long_channel], density, label='long_channel')
def test_tight_with_island(): # build a peanut first: r = 100 thetas = np.linspace(0, 2 * np.pi, 250) peanut = np.zeros((len(thetas), 2), np.float64) x = r * np.cos(thetas) y = r * np.sin(thetas) * (0.9 / 10000 * x * x + 0.05) peanut[:, 0] = x peanut[:, 1] = y # put two holes into it thetas = np.linspace(0, 2 * np.pi, 30) hole1 = np.zeros((len(thetas), 2), np.float64) hole1[:, 0] = 10 * np.cos(thetas) - 75 hole1[:, 1] = 10 * np.sin(thetas) hole2 = np.zeros((len(thetas), 2), np.float64) hole2[:, 0] = 20 * np.cos(thetas) + 75 hole2[:, 1] = 20 * np.sin(thetas) rings = [peanut, hole1, hole2] density = field.ConstantField(6.0) trifront_wrapper(rings, density, label='tight_with_island')
def test_pave_quad(): # Define a polygon rings = [np.array([[0, 0], [1000, 0], [1000, 1000], [0, 1000]])] # And the scale: scale = field.ConstantField(50) return trifront_wrapper(rings, scale, label='quad')
def test_sine_sine(): rings = sine_sine_rings() density = field.ConstantField(25.0) if 0: # no support for min_density yet min_density = field.ConstantField(2.0) # mostly just to make sure that long segments are # sampled well relative to the local feature scale. if 0: # no support yet p.smooth() print("Adjusting other densities to local feature size") p.telescope_rate = 1.1 p.adjust_density_by_apollonius() trifront_wrapper(rings, density, label='sine_sine')
def test_long_channel(): l = 2000 w = 50 long_channel = np.array([[0, 0], [l, 0], [l, w], [0, w]], np.float64) density = field.ConstantField(19.245) p = paver.Paving(long_channel, density) p.pave_all()
def test_dumbarton(): shp=os.path.join( os.path.dirname(__file__), 'data','dumbarton.shp') features=wkb2shp.shp2geom(shp) geom = features['geom'][0] dumbarton = np.array(geom.exterior) density = field.ConstantField(250.0) p=paver.Paving(dumbarton, density,label='dumbarton') p.pave_all()
def test_cul_de_sac(): r = 5 theta = np.linspace(-np.pi / 2, np.pi / 2, 20) cap = r * np.swapaxes(np.array([np.cos(theta), np.sin(theta)]), 0, 1) box = np.array([[-3 * r, r], [-4 * r, -r]]) ring = np.concatenate((box, cap)) density = field.ConstantField(2 * r / (np.sqrt(3) / 2)) trifront_wrapper([ring], density, label='cul_de_sac')
def test_narrow_channel(): l = 1000 w = 50 long_channel = np.array([[0, 0], [l, 0.375 * w], [l, 0.625 * w], [0, w]], np.float64) density = field.ConstantField(w / np.sin(60 * np.pi / 180.) / 4) p = paver.Paving(long_channel, density) p.pave_all()
def test_pave_basic(): # big square with right triangle inside # Define a polygon boundary = np.array([[0, 0], [1000, 0], [1000, 1000], [0, 1000]]) island = np.array([[200, 200], [600, 200], [200, 600]]) rings = [boundary, island] # And the scale: scale = field.ConstantField(50) return trifront_wrapper(rings, scale, label='basic_island')
def test_tight_peanut(): r = 100 thetas = np.linspace(0, 2 * np.pi, 300) peanut = np.zeros((len(thetas), 2), np.float64) x = r * np.cos(thetas) y = r * np.sin(thetas) * (0.9 / 10000 * x * x + 0.05) peanut[:, 0] = x peanut[:, 1] = y density = field.ConstantField(6.0) trifront_wrapper([peanut], density, label='tight_peanut')
def test_bow(): x = np.linspace(-100, 100, 50) # with /1000 it seems to do okay # with /500 it still looks okay y = x**2 / 250.0 bow = np.swapaxes(np.concatenate((x[None, :], y[None, :])), 0, 1) height = np.array([0, 20]) ring = np.concatenate((bow + height, bow[::-1] - height)) density = field.ConstantField(2) trifront_wrapper([ring], density, label='bow')
def test_long_channel_rigid(): l = 2000 w = 50 long_channel = np.array([[0, 0], [l, 0], [l, w], [0, w]], np.float64) density = field.ConstantField(19.245) p = paver.Paving(long_channel, density, initial_node_status=paver.Paving.RIGID) p.pave_all()
def test_narrow_channel(): # This passes now, but the result looks like it could use better # tuning of the parameters -- grid jumps from 1 to 3 cells across # the channel. l = 1000 w = 50 long_channel = np.array([[0, 0], [l, 0.375 * w], [l, 0.625 * w], [0, w]], np.float64) density = field.ConstantField(w / np.sin(60 * np.pi / 180.) / 4) trifront_wrapper([long_channel], density, label='narrow_channel')
def test_long_channel_rigid(): assert False # no RIGID initialization yet l = 2000 w = 50 long_channel = np.array([[0, 0], [l, 0], [l, w], [0, w]], np.float64) density = field.ConstantField(19.245) trifront_wrapper([long_channel], density, initial_node_status=paver.Paving.RIGID, label='long_channel_rigid')
def test_tight_peanut(): r = 100 thetas = np.linspace(0,2*np.pi,300) peanut = np.zeros( (len(thetas),2), np.float64) x = r*np.cos(thetas) y = r*np.sin(thetas) * (0.9/10000 * x*x + 0.05) peanut[:,0] = x peanut[:,1] = y density = field.ConstantField( 6.0 ) p=paver.Paving(peanut,density,label='tight_peanut') p.pave_all()
def test_expansion(): # 40: too close to a 120deg angle - always bisect on centerline # 30: rows alternate with wall and bisect seams # 35: starts to diverge, but recovers. # 37: too close to 120. d = 36 pnts = np.array([[0., 0.], [100, -d], [200, 0], [200, 100], [100, 100 + d], [0, 100]]) density = field.ConstantField(6) trifront_wrapper([pnts], density, label='expansion')
def test_peninsula(): r = 100 thetas = np.linspace(0, 2 * np.pi, 1000) pen = np.zeros((len(thetas), 2), np.float64) pen[:, 0] = r * (0.2 + np.abs(np.sin(2 * thetas))**0.2) * np.cos(thetas) pen[:, 1] = r * (0.2 + np.abs(np.sin(2 * thetas))**0.2) * np.sin(thetas) density = field.ConstantField(10.0) pen2 = upsample_linearring(pen, density) trifront_wrapper([pen2], density, label='peninsula')
def test_basic_setup(): boundary=hex_curve() af=front.AdvancingTriangles() scale=field.ConstantField(3) af.add_curve(boundary) af.set_edge_scale(scale) # create boundary edges based on scale and curves: af.initialize_boundaries() return af
def test_basic(): # Define a polygon boundary=np.array([[0,0],[1000,0],[1000,1000],[0,1000]]) island =np.array([[200,200],[600,200],[200,600]]) rings=[boundary,island] # And the scale: scale=field.ConstantField(50) p=paver.Paving(rings=rings,density=scale) p.pave_all()
def test_curve_upsample(): boundary = hex_curve() scale = field.ConstantField(3) pnts, dists = boundary.upsample(scale, return_sources=True) if plt: plt.clf() line = boundary.plot() plt.setp(line, lw=0.5, color='0.5') #f=np.linspace(0,crv.total_distance(),25) #crvX=crv(f) plt.scatter(pnts[:, 0], pnts[:, 1], 30, dists, lw=0)
def test_small_island(): l = 100 square = np.array([[0, 0], [l, 0], [l, l], [0, l]], np.float64) r = 10 theta = np.linspace(0, 2 * np.pi, 30) circle = r / np.sqrt(2) * np.swapaxes( np.array([np.cos(theta), np.sin(theta)]), 0, 1) island1 = circle + np.array([45, 45]) island2 = circle + np.array([65, 65]) island3 = circle + np.array([20, 80]) rings = [square, island1, island2, island3] density = field.ConstantField(10) trifront_wrapper(rings, density, label='small_island')
def test_ngon(nsides=7): # hexagon works ok, though a bit of perturbation # septagon starts to show expansion issues, but never pronounced # octagon - works fine. theta = np.linspace(0, 2 * np.pi, nsides + 1)[:-1] r = 100 x = r * np.cos(theta) y = r * np.sin(theta) poly = np.swapaxes(np.concatenate((x[None, :], y[None, :])), 0, 1) density = field.ConstantField(6) trifront_wrapper([poly], density, label='ngon%02d' % nsides)
def test_free_span(): r = 5 theta = np.linspace(-np.pi / 2, np.pi / 2, 20) cap = r * np.swapaxes(np.array([np.cos(theta), np.sin(theta)]), 0, 1) box = np.array([[-3 * r, r], [-4 * r, -r]]) ring = np.concatenate((box, cap)) density = field.ConstantField(2 * r / (np.sqrt(3) / 2)) af = front.AdvancingTriangles() af.set_edge_scale(density) af.add_curve(ring, interior=False) af.initialize_boundaries() # N.B. this edge is not given proper cell neighbors af.grid.add_edge(nodes=[22, 3]) af.plot_summary() he = af.grid.nodes_to_halfedge(4, 5) span_dist, span_nodes = af.free_span(he, 25, 1) assert span_nodes[-1] != 4
def test_basic_setup(): boundary = hex_curve() af = front.AdvancingTriangles() scale = field.ConstantField(3) af.add_curve(boundary) af.set_edge_scale(scale) # create boundary edges based on scale and curves: af.initialize_boundaries() if 0 and plt: plt.clf() g = af.grid g.plot_edges() g.plot_nodes() # coll = g.plot_halfedges(values=g.edges['cells']) coll.set_lw(0) coll.set_cmap('winter') return af
## plt.figure(3).clf() fig, ax = plt.subplots(1, 1, num=3) scat = ax.scatter(cutoff_xyz[:, 0], cutoff_xyz[:, 1], 20, cutoff_xyz[:, 2]) plot_wkb.plot_wkb(total_poly, zorder=-2) ax.axis('equal') ## from stompy.spatial import field from stompy.grid import paver six.moves.reload_module(paver) p = paver.Paving(geom=total_poly, density=field.ConstantField(Lres)) p.verbose = 1 p.pave_all() ## # But better to just use a subset of the existing grid. select = g.select_nodes_intersecting(total_poly) g_sub = g.copy() for n in np.nonzero(~select)[0]: g_sub.delete_node_cascade(n) g_sub.renumber() g_sub.orient_edges()
def triangulate_hole(grid,seed_point,max_nodes=5000): # manually tell it where the region to be filled is. # 5000 ought to be plenty of nodes to get around this loop nodes=grid.enclosing_nodestring(seed_point,max_nodes) xy_shore=grid.nodes['x'][nodes] # Construct a scale based on existing spacing # But only do this for edges that are part of one of the original grids grid.edge_to_cells() # update edges['cells'] sample_xy=[] sample_scale=[] ec=grid.edges_center() el=grid.edges_length() for na,nb in utils.circular_pairs(nodes): j=grid.nodes_to_edge([na,nb]) if np.any( grid.edges['cells'][j] >= 0 ): sample_xy.append(ec[j]) sample_scale.append(el[j]) sample_xy=np.array(sample_xy) sample_scale=np.array(sample_scale) apollo=field.PyApolloniusField(X=sample_xy,F=sample_scale) # Prepare that shoreline for grid generation. grid_to_pave=unstructured_grid.UnstructuredGrid(max_sides=6) AT=front.AdvancingTriangles(grid=grid_to_pave) AT.add_curve(xy_shore) # This should be safe about not resampling existing edges AT.scale=field.ConstantField(50000) AT.initialize_boundaries() AT.grid.nodes['fixed'][:]=AT.RIGID AT.grid.edges['fixed'][:]=AT.RIGID # Old code compared nodes to original grids to figure out RIGID # more general, if it works, to see if a node participates in any cells. # At the same time, record original nodes which end up HINT, so they can # be removed later on. src_hints=[] for n in AT.grid.valid_node_iter(): n_src=grid.select_nodes_nearest(AT.grid.nodes['x'][n]) delta=utils.dist( grid.nodes['x'][n_src], AT.grid.nodes['x'][n] ) assert delta<0.1 # should be 0.0 if len(grid.node_to_cells(n_src))==0: # It should be a HINT AT.grid.nodes['fixed'][n]=AT.HINT src_hints.append(n_src) # And any edges it participates in should not be RIGID either. for j in AT.grid.node_to_edges(n): AT.grid.edges['fixed'][j]=AT.UNSET AT.scale=apollo if AT.loop(): AT.grid.renumber() else: print("Grid generation failed") return AT # for debugging -- need to keep a handle on this to see what's up. for n in src_hints: grid.delete_node_cascade(n) grid.add_grid(AT.grid) # Surprisingly, this works! grid.merge_duplicate_nodes() grid.renumber() return grid
# New in v02: # Apply a max filter across the DEM. # for a 5m radius and 2m pixels, not much hope in really resolving # a disc, but here goes footprint = np.array([[0, 1, 1, 1, 0], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [0, 1, 1, 1, 0]]) ## # The real deal - update dem in place (in RAM, not on disk) dem.F = ndimage.maximum_filter(dem.F, footprint=footprint) ## res = field.ConstantField(5.0) # target output linear resolution # count total features so that files can be concatenated without issue. total_count = 0 # no longer split by class, all filtering already complete in the input # shapefile g = unstructured_grid.UnstructuredGrid(extra_node_fields=[('elev_m', 'f8')], extra_edge_fields=[('mean_elev_m', 'f8') ]) for ix, sel_i in enumerate(np.nonzero(sel)[0]): geom = inv['geom'][sel_i] coords = np.array(geom) # not 100% sure about whether it's necessary to test for closed_ring
# Lagoon (552129.3226207336, 552521.6926489467, 4124153.228958399, 4124603.800540797) # The main issue was actually lagoon-lidar2017 above, which had too sharp of a transition # Also decreased the feather on lagoon, and use min() lagoon_dem = field.GdalGrid("lagoon-1m.tif") params('lagoon', priority=85, src=lagoon_dem, data_mode='min()', alpha_mode='valid(),feather_in(10.0)', geom=field_bounds(lagoon_dem)) params('feeder_culvert', priority=95, src=field.ConstantField(0.6), alpha_mode='feather_in(3.0),feather_out(4.0)', data_mode='min()') params('south_channel_culvert', priority=95, src=field.ConstantField(1.0), alpha_mode='feather_in(3.0)', data_mode='min()') # a few survey points are 1.0. With the blur_alpha(), as the polygon # gets narrower the min depth is going to decrease, too. The value # of the ConstantField doesn't necessarily dictate the min depth. params('north_ditch', priority=95, src=field.ConstantField(0.7),