def test_linestring(self): a = numpy.array([[1.0, 1.0, 2.0, 2.0, 1.0], [3.0, 4.0, 4.0, 3.0, 3.0]]) t = a.T s = geometry.asLineString(t) self.failUnlessEqual( list(s.coords), [(1.0, 3.0), (1.0, 4.0), (2.0, 4.0), (2.0, 3.0), (1.0, 3.0)] )
def __init__(self, *args, **kwargs): super(UnstructuredMap, self).__init__(*args, **kwargs) self._point = {} last_offset = 0 for (cell_id, offset) in enumerate(self._offset): cell = self._connectivity[last_offset:offset] last_offset = offset for point_id in cell: try: self._point[point_id].append(cell_id) except KeyError: self._point[point_id] = [cell_id] (point_x, point_y) = (self.get_x(), self.get_y()) self._polys = [] last_offset = 0 for (cell_id, offset) in enumerate(self._offset): cell = self._connectivity[last_offset:offset] last_offset = offset (x, y) = (point_x.take(cell), point_y.take(cell)) if len(x) > 2: self._polys.append(asPolygon(zip(x, y))) elif len(x) == 2: self._polys.append(asLineString(zip(x, y))) else: self._polys.append(asPoint(zip(x, y)))
def rasterize(poly,F,T): """ Create binary array on an arbitrary grid that's True only for points inside poly. Uses a scanline algorithm. poly a shapely Polygon F an array of scalars defining the grid for frequency (row) coordinates T an array of scalars defining the grid for time (column) coordinates Returns a boolean len(F) by len(T) array """ imask = nx.zeros((F.size,T.size,),dtype='bool') # use a single numpy array for the scanline to avoid creating a lot of objects scanline = nx.array([[T[0],0.0],[T[-1],0.0]]) sl = geometry.asLineString(scanline) for i,f in enumerate(F): scanline[:,1] = f ml = poly.intersection(sl) # several different types of objects may be returned from this if ml.geom_type == 'LineString': ml = [ml] for el in ml: # single points are tangents, drop them if el.geom_type != 'LineString': continue idx = slice(*T.searchsorted(el.xy[0])) imask[i,idx] = True return imask
def shapeup(self, ob): if isinstance(ob, BaseGeometry): return ob else: try: return asShape(ob) except ValueError: return asLineString(ob)
def test_linestring(self): # From coordinate tuples line = LineString(((1.0, 2.0), (3.0, 4.0))) self.assertEqual(len(line.coords), 2) self.assertEqual(line.coords[:], [(1.0, 2.0), (3.0, 4.0)]) # From Points line2 = LineString((Point(1.0, 2.0), Point(3.0, 4.0))) self.assertEqual(len(line2.coords), 2) self.assertEqual(line2.coords[:], [(1.0, 2.0), (3.0, 4.0)]) # From mix of tuples and Points line3 = LineString((Point(1.0, 2.0), (2.0, 3.0), Point(3.0, 4.0))) self.assertEqual(len(line3.coords), 3) self.assertEqual(line3.coords[:], [(1.0, 2.0), (2.0, 3.0), (3.0, 4.0)]) # Bounds self.assertEqual(line.bounds, (1.0, 2.0, 3.0, 4.0)) # Coordinate access self.assertEqual(tuple(line.coords), ((1.0, 2.0), (3.0, 4.0))) self.assertEqual(line.coords[0], (1.0, 2.0)) self.assertEqual(line.coords[1], (3.0, 4.0)) with self.assertRaises(IndexError): line.coords[2] # index out of range # Geo interface self.assertEqual(line.__geo_interface__, {'type': 'LineString', 'coordinates': ((1.0, 2.0), (3.0, 4.0))}) # Coordinate modification line.coords = ((-1.0, -1.0), (1.0, 1.0)) self.assertEqual(line.__geo_interface__, {'type': 'LineString', 'coordinates': ((-1.0, -1.0), (1.0, 1.0))}) # Adapt a coordinate list to a line string coords = [[5.0, 6.0], [7.0, 8.0]] la = asLineString(coords) self.assertEqual(la.coords[:], [(5.0, 6.0), (7.0, 8.0)]) # Test Non-operability of Null geometry l_null = LineString() self.assertEqual(l_null.wkt, 'GEOMETRYCOLLECTION EMPTY') self.assertEqual(l_null.length, 0.0) # Check that we can set coordinates of a null geometry l_null.coords = [(0, 0), (1, 1)] self.assertAlmostEqual(l_null.length, 1.4142135623730951)
def loadDistanceData(): # Load if possible, but calculate if not possible try: distances = np.load(os.path.join(DATA_DIR, "distance_matrix.npy")) locations = np.load(os.path.join(DATA_DIR, "baltimore_grid.npy")) except IOError: # TODO: Replace this with a call to refine_baltimore_distance_matrix baltimore_grid = gb.getBaltimoreGrid(5, 5) baltimore_grid.long, baltimore_grid.lat = sg.asLineString(baltimore_grid).xy locations = np.array([baltimore_grid.lat, baltimore_grid.long]).T distances = dr.distance_matrix(locations) distances = np.save(os.path.join(DATA_DIR, "distance_matrix.npy"), distances, False) locations = np.save(os.path.join(DATA_DIR, "baltimore_grid.npy"), locations, False) return distances, locations
def adjust_channel_depth(grd,shpfile,lcmax=500.): """ Adjusts the depths of a suntans grid object using a line shapefile. The shapefile must have an attribute called "contour" """ from shapely import geometry, speedups from maptools import readShpPointLine if speedups.available: speedups.enable() print 'Adjusting depths in channel regions with a shapefile...' # Load the shapefile xyline,contour = readShpPointLine(shpfile,FIELDNAME='contour') # Load all of the points into shapely type geometry # Distance method won't work with numpy array #P = geometry.asPoint(xy) P = [geometry.Point(grd.xv[i],grd.yv[i]) for i in range(grd.Nc)] L=[] for ll in xyline: L.append(geometry.asLineString(ll)) nlines = len(L) weight_all = np.zeros((grd.Nc,nlines)) for n in range(nlines): print 'Calculating distance from line %d...'%n dist = [L[n].distance(P[i]) for i in range(grd.Nc)] dist = np.array(dist) # Calculate the weight from the distance weight = -dist/lcmax+1. weight[dist>=lcmax]=0. weight_all[:,n] = weight # Now go through and re-calculate the depths dv = grd.dv*(1-weight_all.sum(axis=-1)) for n in range(nlines): dv += weight_all[:,n]*contour[n] grd.dv=dv return grd
def test_numpy(self): from numpy import array, asarray from numpy.testing import assert_array_equal # Construct from a numpy array line = LineString(array([[0.0, 0.0], [1.0, 2.0]])) self.assertEqual(len(line.coords), 2) self.assertEqual(line.coords[:], [(0.0, 0.0), (1.0, 2.0)]) line = LineString(((1.0, 2.0), (3.0, 4.0))) la = asarray(line) expected = array([[1.0, 2.0], [3.0, 4.0]]) assert_array_equal(la, expected) # Coordinate sequences can be adapted as well la = asarray(line.coords) assert_array_equal(la, expected) # Adapt a Numpy array to a line string a = array([[1.0, 2.0], [3.0, 4.0]]) la = asLineString(a) assert_array_equal(la.context, a) self.assertEqual(la.coords[:], [(1.0, 2.0), (3.0, 4.0)]) # Now, the inverse self.assertEqual(la.__array_interface__, la.context.__array_interface__) pas = asarray(la) assert_array_equal(pas, array([[1.0, 2.0], [3.0, 4.0]])) # From Array.txt a = asarray([[0.0, 0.0], [2.0, 2.0], [1.0, 1.0]]) line = LineString(a) self.assertEqual(line.coords[:], [(0.0, 0.0), (2.0, 2.0), (1.0, 1.0)]) data = line.ctypes self.assertEqual(data[0], 0.0) self.assertEqual(data[5], 1.0) b = asarray(line) assert_array_equal(b, array([[0., 0.], [2., 2.], [1., 1.]])) # Test array interface of empty linestring le = LineString() a = asarray(le) self.assertEqual(a.shape[0], 0)
def __init__(self, data, p1, p2, reverse=False, z_adjustment=None): self.data = data self.p1, self.p2 = p1, p2 self.projection = None self.line = None self.date = None if reverse == True: self.data.sort_index(ascending=False, inplace=True) # flip sections shot right to left if z_adjustment != None: self.data['z'] = self.data['z'] + z_adjustment self.projection = og.project_points(self.data, self.p1, self.p2) self.line = asLineString(list(zip(self.projection['d'],self.projection['z']))) self.date = (self.data.iloc[0]['t']).split('T')[0]
def parse_trajectory_geometry(self, variable, coord_names): xvar = self.cd.nc.variables[coord_names['xname']] yvar = self.cd.nc.variables[coord_names['yname']] # one less order of magnitude eg 390000 -> 10000 slice_factor = 10 ** (int(math.log10(xvar.size)) - 1) if slice_factor < 1: slice_factor = 1 # TODO: don't split x/y as separate arrays. Refactor to # use single numpy array instead with both lon/lat # tabledap datasets must be treated differently than # standard DAP endpoints. Retrieve geojson instead of # trying to access as a DAP endpoint if 'erddap/tabledap' in self.service.get('url'): # take off 's.' from erddap gj = self.erddap_geojson_url(coord_names) # type defaults to MultiPoint, change to LineString coords = np.array(gj['coordinates'][::slice_factor] + gj['coordinates'][-1:]) xs = coords[:, 0] ys = coords[:, 1] else: xs = np.concatenate((xvar[::slice_factor], xvar[-1:])) ys = np.concatenate((yvar[::slice_factor], yvar[-1:])) # both coords must be valid to have a valid vertex # get rid of any nans and unreasonable lon/lats valid_idx = ((~np.isnan(xs)) & (np.absolute(xs) <= 180) & (~np.isnan(ys)) & (np.absolute(ys) <= 90)) xs = xs[valid_idx] ys = ys[valid_idx] # Shapely seems to require float64 values or incorrect # values will propagate for the generated lineString # if the array is not numpy's float64 dtype lineCoords = np.array([xs, ys]).T.astype('float64') gj = mapping(asLineString(lineCoords)) self.messages.append(u"Variable %s was used to calculate " u"trajectory geometry, and is a " u"naive sampling." % variable) return gj
def __init__(self, data, p1, p2, backsight=0.0, datum=0.0, reverse=False, z_adjustment=None): self.data = data self.datum = datum self.backsight = backsight self.location = None # this will assign x,y values to the data based on p1, p2 coordinates self.line = None if {'f'}.isin(self.data.columns): logger.info('calculate elevations') if reverse == True: self.data.sort(ascending=False, inplace=True) # flip sections shot right to left if z_adjustment != None: self.data['z'] = self.data['z'] + z_adjustment if p1 != None and p2 != None: # calculate locations, but instead of dou, calculate xyz # xyzdou self.location = og.locate_points(self.data, self.p1, self.p2) self.line = asLineString(list(zip(self.data['d'],self.data['z'])))
def linestring_shpfromdf(df, shpname, IDname, Xname, Yname, Zname, prj, aggregate=None): ''' creates point shape file from pandas dataframe shp: name of shapefile to write Xname: name of column containing Xcoordinates Yname: name of column containing Ycoordinates Zname: name of column containing Zcoordinates IDname: column with unique integers for each line aggregate = dict of column names (keys) and operations (entries) ''' # setup properties for schema # if including other properties besides line identifier, # aggregate those to single value for line, using supplied aggregate dictionary if aggregate: cols = [IDname] + list(aggregate.keys()) aggregated = df[cols].groupby(IDname).agg(aggregate) aggregated[IDname] = aggregated.index properties = shp_properties(aggregated) # otherwise setup properties to just include line identifier else: properties = {IDname: 'int'} aggregated = pd.DataFrame(df[IDname].astype('int32')) schema = {'geometry': '3D LineString', 'properties': properties} lines = list(np.unique(df[IDname].astype('int32'))) with fiona.collection(shpname, "w", "ESRI Shapefile", schema) as output: for line in lines: lineinfo = df[df[IDname] == line] vertices = lineinfo[[Xname, Yname, Zname]].values linestring = asLineString(vertices) props = dict(list(zip(aggregated.columns, aggregated.ix[line, :]))) output.write({'properties': props, 'geometry': mapping(linestring)}) shutil.copyfile(prj, "{}.prj".format(shpname[:-4]))
def mask_segments(segments: np.array, mask: np.array, diff: bool = True) -> np.array: """ Take a array of 3D segments and masks them with a 2D polygon. The polygon is assumed to be perpendicular to the Z axis and the masking is done along the Z axis :param segments: Nx2x3 array of segments :param mask: Mx2 polygon to be used for masking :param diff: if True, the mask area is removed from segment, otherwise the intersection is kept :return: Lx2x3 array of segments whose length might differ from input """ _validate_segments(segments) if len(mask.shape) != 2 or mask.shape[1] != 2: raise ValueError( f"mask array must be of dimension (Nx2) instead of {mask.shape}") if len(segments) == 0: return np.array(segments) poly = Polygon(mask) # The following is the parallel implementation, which passes the tests but generates # a lot of lines (https://github.com/Toblerity/Shapely/issues/779) # mls = asMultiLineString(segments) # if diff: # mls2 = mls.difference(poly) # else: # mls2 = mls.intersection(poly) # # if mls2.geom_type == "LineString": # return np.array([mls2.coords]) # elif mls2.geom_type == "MultiLineString": # return np.array([np.array(ls.coords) for ls in mls2]) # elif mls2.geom_type == "MultiPoint": # return np.empty((0, 2, 3)) # else: # raise ValueError(f"Unexpected geometry: {mls2.geom_type}") # The following is a slower (?), segment-by-segment implementation that does not exhibit # the line multiplication issue op = "difference" if diff else "intersection" output = [] for i in range(len(segments)): ls = asLineString(segments[i, :, :]) res = getattr(ls, op)(poly) # segments with identical start/stop location are sometime returned if np.isclose(res.length, 0, atol=ATOL, rtol=RTOL): continue if res.geom_type == "LineString": output.append(np.array([res.coords])) elif res.geom_type == "MultiLineString": output.append(np.array([np.array(l.coords) for l in res])) if output: res = np.vstack(output) # https://github.com/Toblerity/Shapely/issues/780 # Some z-coordinate are being erroneously affected by the difference. This ugly # hack attempts to restore them. for s in segments: idx, = np.where( np.all(np.all(s[:, 0:2] == res[:, :, 0:2], axis=2), axis=1)) res[idx, :, 2] = s[:, 2] return res else: return np.empty((0, 2, 3))
]) start = pntCounter bezCurve = bezier.bezier(xList, yList) # add interpolated points to newpoints list newPointList = np.concatenate((newPointList, bezCurve), 0) disTot = 0 del bezCurve, xList, yList, bezMidPoint pntCounter += 1 else: newPointList = np.concatenate( (newPointList, [points[pntCounter - 1]]), 0 ) # for lines consider removing this as it always closes it? newLinestring = asLineString( newPointList) # could also use linear rings newMultiLine.append(newLinestring) bendedLines.append(MultiLineString(newMultiLine[0:])) elif lines.geom_type == "LineString": try: xList = [point[0] for point in linemerge(lines).coords] yList = [point[1] for point in linemerge(lines).coords] bezCurve = bezier.bezier(xList, yList) bendedLines.append(asLineString(bezCurve)) except: pointReduce = lines.simplify( minHalfCircleBend) # just reduce the points bendedLines.append(pointReduce)
pt_buf = point.buffer(5) print(pt_buf.wkt) # Numpy from numpy import asarray a = asarray(point) a.size a.shape from numpy import array from shapely.geometry import asLineString a = array([[1.0, 2.0], [3.0, 4.0]]) line = asLineString(a) print(line.wkt) # Geo jiekou d = {"type": "point", "coordinates": (0.0, 0.0)} from shapely.geometry import asShape shape = asShape(d) print(shape.geom_type) tuple(shape.coords) class GeoThing(object): def __init__(self, d): self.__geo_interface__ = d
def test_linestring_adapter(self): # Adapt a coordinate list to a line string coords = [[5.0, 6.0], [7.0, 8.0]] la = asLineString(coords) self.assertEqual(la.coords[:], [(5.0, 6.0), (7.0, 8.0)])
def test_linestring_adapter_deprecated(): coords = [[5.0, 6.0], [7.0, 8.0]] with pytest.warns(ShapelyDeprecationWarning, match="proxy geometries"): asLineString(coords)
# self.bng.step(50) sleep(2) except Exception: # When we brutally kill this process there's no need to log an exception l.error("Fatal Error", exc_info=True) finally: self.bng.close() if __name__ == '__test__': # if __name__ == '__main__': from numpy import array, load from shapely.geometry import asLineString driving_path = asLineString(load('driving.npy')) mu = 0.8 speed_limit_meter_per_sec = 90.0 / 3.6 road_profiler = RoadProfiler(mu, speed_limit_meter_per_sec) car_model = dict() # Is this m/s**2 car_model['max_acc'] = 3.0 car_model['max_dec'] = -6.3 ai_script = road_profiler.compute_ai_script(driving_path, car_model) if __name__ == '__main__': import argparse parser = argparse.ArgumentParser() parser.add_argument('--max-speed', type=int, default=90,
def harvest(self): """ Identify the type of CF dataset this is: * UGRID * CGRID * RGRID * DSG """ try: cd = CommonDataset.open(self.service.get('url')) except Exception as e: app.logger.error("Could not open DAP dataset from '%s'\n" "Exception %s: %s" % (self.service.get('url'), type(e).__name__, e)) return 'Not harvested' # For DAP, the unique ID is the URL unique_id = self.service.get('url') with app.app_context(): dataset = db.Dataset.find_one( { 'uid' : unicode(unique_id) } ) if dataset is None: dataset = db.Dataset() dataset.uid = unicode(unique_id) dataset['active'] = True # Find service reference in Dataset.services and remove (to replace it) tmp = dataset.services[:] for d in tmp: if d['service_id'] == self.service.get('_id'): dataset.services.remove(d) # Parsing messages messages = [] # NAME name = None try: name = unicode_or_none(cd.nc.getncattr('title')) except AttributeError: messages.append(u"Could not get dataset name. No global attribute named 'title'.") # DESCRIPTION description = None try: description = unicode_or_none(cd.nc.getncattr('summary')) except AttributeError: messages.append(u"Could not get dataset description. No global attribute named 'summary'.") # KEYWORDS keywords = [] try: keywords = sorted(map(lambda x: unicode(x.strip()), cd.nc.getncattr('keywords').split(","))) except AttributeError: messages.append(u"Could not get dataset keywords. No global attribute named 'keywords' or was not comma seperated list.") # VARIABLES prefix = "" # Add additonal prefix mappings as they become available. try: standard_name_vocabulary = unicode(cd.nc.getncattr("standard_name_vocabulary")) cf_regex = [re.compile("CF-"), re.compile('http://www.cgd.ucar.edu/cms/eaton/cf-metadata/standard_name.html')] for reg in cf_regex: if reg.match(standard_name_vocabulary) is not None: prefix = "http://mmisw.org/ont/cf/parameter/" break except AttributeError: pass # Get variables with a standard_name std_variables = [cd.get_varname_from_stdname(x)[0] for x in self.get_standard_variables(cd.nc) if x not in self.STD_AXIS_NAMES and len(cd.nc.variables[cd.get_varname_from_stdname(x)[0]].shape) > 0] # Get variables that are not axis variables or metadata variables and are not already in the 'std_variables' variable non_std_variables = list(set([x for x in cd.nc.variables if x not in itertools.chain(_possibley, _possiblex, _possiblez, _possiblet, self.METADATA_VAR_NAMES, self.COMMON_AXIS_NAMES) and len(cd.nc.variables[x].shape) > 0 and x not in std_variables])) axis_names = DapHarvest.get_axis_variables(cd.nc) """ var_to_get_geo_from = None if len(std_names) > 0: var_to_get_geo_from = cd.get_varname_from_stdname(std_names[-1])[0] messages.append(u"Variable '%s' with standard name '%s' was used to calculate geometry." % (var_to_get_geo_from, std_names[-1])) else: # No idea which variable to generate geometry from... try to factor variables with a shape > 1. try: var_to_get_geo_from = [x for x in variables if len(cd.nc.variables[x].shape) > 1][-1] except IndexError: messages.append(u"Could not find any non-axis variables to compute geometry from.") else: messages.append(u"No 'standard_name' attributes were found on non-axis variables. Variable '%s' was used to calculate geometry." % var_to_get_geo_from) """ # LOCATION (from Paegan) # Try POLYGON and fall back to BBOX # paegan does not support ugrid, so try to detect this condition and skip is_ugrid = False is_trajectory = False for vname, v in cd.nc.variables.iteritems(): if 'cf_role' in v.ncattrs(): if v.getncattr('cf_role') == 'mesh_topology': is_ugrid = True break elif v.getncattr('cf_role') == 'trajectory_id': is_trajectory = True break gj = None if is_ugrid: messages.append(u"The underlying 'Paegan' data access library does not support UGRID and cannot parse geometry.") elif is_trajectory: coord_names = {} # try to get info for x, y, z, t axes for v in itertools.chain(std_variables, non_std_variables): try: coord_names = cd.get_coord_names(v, **axis_names) if coord_names['xname'] is not None and \ coord_names['yname'] is not None: break except (AssertionError, AttributeError, ValueError, KeyError): pass else: messages.append(u"Trajectory discovered but could not detect coordinate variables using the underlying 'Paegan' data access library.") if 'xname' in coord_names: try: xvar = cd.nc.variables[coord_names['xname']] yvar = cd.nc.variables[coord_names['yname']] # one less order of magnitude eg 390000 -> 10000 slice_factor = 10 ** (int(math.log10(xvar.size)) - 1) xs = np.concatenate((xvar[::slice_factor], xvar[-1:])) ys = np.concatenate((yvar[::slice_factor], yvar[-1:])) # both coords must be valid to have a valid vertex # get rid of any nans and unreasonable lon/lats valid_idx = ((~np.isnan(xs)) & (np.absolute(xs) <= 180) & (~np.isnan(ys)) & (np.absolute(ys) <= 90)) xs = xs[valid_idx] ys = ys[valid_idx] # Shapely seems to require float64 values or incorrect # values will propagate for the generated lineString # if the array is not numpy's float64 dtype lineCoords = np.array([xs, ys]).T.astype('float64') gj = mapping(asLineString(lineCoords)) messages.append(u"Variable %s was used to calculate " u"trajectory geometry, and is a " u"naive sampling." % v) except (AssertionError, AttributeError, ValueError, KeyError, IndexError) as e: app.logger.warn("Trajectory error occured: %s", e) messages.append(u"Trajectory discovered but could not create a geometry.") else: for v in itertools.chain(std_variables, non_std_variables): try: gj = mapping(cd.getboundingpolygon(var=v, **axis_names ).simplify(0.5)) except (AttributeError, AssertionError, ValueError, KeyError, IndexError): try: # Returns a tuple of four coordinates, but box takes in four seperate positional argouments # Asterik magic to expland the tuple into positional arguments app.logger.exception("Error calculating bounding box") # handles "points" aka single position NCELLs bbox = cd.getbbox(var=v, **axis_names) gj = self.get_bbox_or_point(bbox) except (AttributeError, AssertionError, ValueError, KeyError, IndexError): pass if gj is not None: # We computed something, break out of loop. messages.append(u"Variable %s was used to calculate geometry." % v) break if gj is None: # Try the globals gj = self.global_bounding_box(cd.nc) messages.append(u"Bounding Box calculated using global attributes") if gj is None: messages.append(u"The underlying 'Paegan' data access library could not determine a bounding BOX for this dataset.") messages.append(u"The underlying 'Paegan' data access library could not determine a bounding POLYGON for this dataset.") messages.append(u"Failed to calculate geometry using all of the following variables: %s" % ", ".join(itertools.chain(std_variables, non_std_variables))) # TODO: compute bounding box using global attributes final_var_names = [] if prefix == "": messages.append(u"Could not find a standard name vocabulary. No global attribute named 'standard_name_vocabulary'. Variable list may be incorrect or contain non-measured quantities.") final_var_names = non_std_variables + std_variables else: final_var_names = non_std_variables + list(map(unicode, ["%s%s" % (prefix, cd.nc.variables[x].getncattr("standard_name")) for x in std_variables])) service = { 'name': name, 'description': description, 'service_type': self.service.get('service_type'), 'service_id': ObjectId(self.service.get('_id')), 'data_provider': self.service.get('data_provider'), 'metadata_type': u'ncml', 'metadata_value': unicode(dataset2ncml(cd.nc, url=self.service.get('url'))), 'messages': map(unicode, messages), 'keywords': keywords, 'variables': map(unicode, final_var_names), 'asset_type': get_common_name(DapHarvest.get_asset_type(cd)), 'geojson': gj, 'updated': datetime.utcnow() } with app.app_context(): dataset.services.append(service) dataset.updated = datetime.utcnow() dataset.save() ncdataset = Dataset(self.service.get('url')) scores = self.ccheck_dataset(ncdataset) metamap = self.metamap_dataset(ncdataset) try: metadata_rec = self.save_ccheck_dataset('ioos', dataset._id, scores, metamap) except Exception as e: metadata_rec = None app.logger.error("could not save compliancecheck/metamap information", exc_info=True) return "Harvested"
if args.startpoint: args.skip = coords.index(args.startpoint) print( f'Moving starting point of tour forward to {args.startpoint} (polygon point #{args.skip})' ) if args.skip > 0: print( f'Moving tour starting point forward to {args.skip} point(s) into the original polygon' ) coords = coords[args.skip:] + coords[:args.skip] if args.simplify != None: origcount = len(coords) # TODO make simplify dynamic based on distance coords = asLineString(coords).simplify(args.simplify, False).coords print(f'Smoothed tour from {origcount} down to {len(coords)} points') # calculate total runtime before trimming anything distanceoffsets = cumulativedistances(coords) totaldistance = distanceoffsets[-1] totalframes = distancetoframe( totaldistance) + 1 # plus one because distance 0 frame was not counted totalseconds = totalframes / args.framerate # these should be the same totaltotalseconds = totaltotalseconds + totalseconds print() print( f'Total runtime of the COMPLETE {round(totaldistance)}km tour at {args.kmh} km/h would be {formatruntime(totalseconds)} ({totalframes} video frames)' )
def get_and_save_edges(self): """Identifies and saves the left, top, right, and bottom (LTRB) edges. This method saves the LTRB edges as attributes within the layer object. self.left : np.array, coords for left edge self.top : np.array, coords for top edge self.right : np.array, coords for right edge self.bottom : np.array, coords for bottom edge """ edges = self.get_edges() # get centroids centroids = [] triangular_region = False for edge in edges: try: centroids.append(asLineString(edge).centroid) except ValueError: # if the region is triangular, one of its "edges" will be a # point, not a line string. triangular_region = True # determine which edges are top, bottom, left, and right if not triangular_region: l = range(4) # list of indices, one for each edge c = np.array([[centroids[0].x, centroids[0].y], [centroids[1].x, centroids[1].y], [centroids[2].x, centroids[2].y], [centroids[3].x, centroids[3].y]]) cx = c[:,0] cy = c[:,1] x_max_ind = np.nonzero(cx==cx.max())[0][0] x_min_ind = np.nonzero(cx==cx.min())[0][0] y_max_ind = np.nonzero(cy==cy.max())[0][0] y_min_ind = np.nonzero(cy==cy.min())[0][0] else: l = range(3) c = np.array([[centroids[0].x, centroids[0].y], [centroids[1].x, centroids[1].y], [centroids[2].x, centroids[2].y]]) cx = c[:,0] cy = c[:,1] x_min_ind = np.nonzero(cx==cx.min())[0][0] y_max_ind = np.nonzero(cy==cy.max())[0][0] y_min_ind = np.nonzero(cy==cy.min())[0][0] if self.parent_part.__class__.__name__ == 'RootBuildup': # find centroid at x=0 ind_x = np.nonzero(cx==0.0)[0][0] l.remove(ind_x) # remove the index for the right edge # find centroid at y=0 ind_y = np.nonzero(cy==0.0)[0][0] l.remove(ind_y) # remove the index for the left edge if self.name == 'triax, lower left': self.right = edges[ind_x] # right edge saved! self.left = edges[ind_y] # left edge saved! elif self.name == 'triax, lower right': self.left = edges[ind_x] # left edge saved! self.right = edges[ind_y] # right edge saved! elif self.name == 'triax, upper right': self.left = edges[ind_x] # left edge saved! self.right = edges[ind_y] # right edge saved! elif self.name == 'triax, upper left': self.right = edges[ind_x] # right edge saved! self.left = edges[ind_y] # left edge saved! # find top and bottom edges if centroids[l[0]].y > centroids[l[1]].y: self.top = edges[l[0]] # top edge saved! self.bottom = edges[l[1]] # bottom edge saved! else: self.top = edges[l[1]] # top edge saved! self.bottom = edges[l[0]] # bottom edge saved! elif self.parent_part.__class__.__name__ == 'LE_Panel': l.remove(x_min_ind) # remove the index for the left edge self.left = edges[x_min_ind] # left edge saved! l.remove(y_max_ind) # remove the index for the top edge self.top = edges[y_max_ind] # top edge saved! l.remove(y_min_ind) # remove the index for the bottom edge self.bottom = edges[y_min_ind] # bottom edge saved! self.right = edges[l[0]] # right edge saved! elif self.parent_part.__class__.__name__ == 'SparCap': l.remove(x_min_ind) # remove the index for the left edge self.left = edges[x_min_ind] # left edge saved! l.remove(x_max_ind) # remove the index for the right edge self.right = edges[x_max_ind] # right edge saved! if centroids[l[0]].y > centroids[l[1]].y: self.top = edges[l[0]] # top edge saved! self.bottom = edges[l[1]] # bottom edge saved! else: self.top = edges[l[1]] # top edge saved! self.bottom = edges[l[0]] # bottom edge saved! elif self.parent_part.__class__.__name__ == 'AftPanel': l.remove(x_min_ind) # remove the index for the left edge self.left = edges[x_min_ind] # left edge saved! l.remove(x_max_ind) # remove the index for the right edge self.right = edges[x_max_ind] # right edge saved! if centroids[l[0]].y > centroids[l[1]].y: self.top = edges[l[0]] # top edge saved! self.bottom = edges[l[1]] # bottom edge saved! else: self.top = edges[l[1]] # top edge saved! self.bottom = edges[l[0]] # bottom edge saved! elif self.parent_part.__class__.__name__ == 'TE_Reinforcement': if self.name == 'uniax' or self.name == 'foam': l.remove(x_max_ind) # remove the index for the right edge self.right = edges[x_max_ind] # right edge saved! l.remove(y_max_ind) # remove the index for the top edge self.top = edges[y_max_ind] # top edge saved! l.remove(y_min_ind) # remove the index for the bottom edge self.bottom = edges[y_min_ind] # bottom edge saved! self.left = edges[l[0]] # left edge saved! else: # this is an alternate layer l.remove(x_min_ind) # remove the index for the left edge self.left = edges[x_min_ind] # left edge saved! if not triangular_region: # if this region is rectangular, assign the right edge l.remove(x_max_ind) # remove the index for the right edge self.right = edges[x_max_ind] # right edge saved! else: self.right = None if centroids[l[0]].y > centroids[l[1]].y: self.top = edges[l[0]] # top edge saved! self.bottom = edges[l[1]] # bottom edge saved! else: self.top = edges[l[1]] # top edge saved! self.bottom = edges[l[0]] # bottom edge saved! elif self.parent_part.__class__.__name__ == 'ShearWeb': l.remove(x_min_ind) # remove the index for the left edge self.left = edges[x_min_ind] # left edge saved! l.remove(x_max_ind) # remove the index for the right edge self.right = edges[x_max_ind] # right edge saved! if centroids[l[0]].y > centroids[l[1]].y: self.top = edges[l[0]] # top edge saved! self.bottom = edges[l[1]] # bottom edge saved! else: self.top = edges[l[1]] # top edge saved! self.bottom = edges[l[0]] # bottom edge saved!
driver = ogr.GetDriverByName('ESRI Shapefile') outds = driver.CreateDataSource(outfile) outlayer = CloneLayer( outds, lyr ) for i in range(lyr.GetFeatureCount()): feat = lyr.GetFeature(i) geom = loads(feat.GetGeometryRef().ExportToWkb()) line = asarray(geom) smooth_line = calcBezierFromLine( line, num_bezpts, beztype, t) if show_only is True: pylab.plot( line[:,0] - 2., line[:,1] ) pylab.plot( smooth_line[:,0], smooth_line[:,1] ) else: sl = asLineString( smooth_line ) # Loop thru fields and clone attributes field_count = lyr.GetLayerDefn().GetFieldCount() outfeature = ogr.Feature(feature_def=outlayer.GetLayerDefn()) for i in range(field_count): outfeature.SetField( i, feat.GetField(i) ) new_geom = ogr.CreateGeometryFromWkt(sl.wkt) outfeature.SetGeometry( new_geom ) outlayer.CreateFeature( outfeature ) if show_only is True: pylab.show() else: ds.Destroy()
def mask_segment(segment: np.ndarray, faces: np.ndarray) -> np.ndarray: """ Compute the visibility of the segment given the provided faces. Segments are hidden when the are on the opposite side of the normal :param segment: (2x3) the segment to process :param faces: (Nx3x3) the faces to consider :return: (Mx2x3) list of visible sub-segments """ if not _validate_shape(segment, 2, 3): raise ValueError( f"segment has shape {segment.shape} instead of (2, 3)") if not _validate_shape(faces, None, 3, 3): raise ValueError(f"faces has shape {faces.shape} instead of (M, 3, 3)") # Check 2D overlap, all non-overlapping faces can be ignored active = triangles_overlap_segment_2d(faces, segment) if not np.any(active): return segment.reshape((1, 2, 3)) # Iterate over every triangle and run the intersection function mask = [] for i, face in enumerate(faces[active]): res, r, s, t, itrsct, b = segment_triangle_intersection(segment, face) if res in ( DEGENERATE, NO_INT_SHORT_SEGMENT_FRONT, NO_INT_PARALLEL_FRONT, INT_COPLANAR, ): # this face is not masking the segment continue elif res in (NO_INT_PARALLEL_BEHIND, NO_INT_SHORT_SEGMENT_BEHIND): # this face is masking the segment mask.append(face) elif res == NO_INT_OUTSIDE_FACE: # segment crosses the face's plane, but not the face itself # masking occurs if the rear half-segment 2D-overlaps the face if b > 0: test_seg = np.array([segment[0], itrsct]) else: test_seg = np.array([itrsct, segment[1]]) overlap = triangles_overlap_segment_2d(np.array([face]), np.array(test_seg), accept_vertex_only=False) if overlap[0]: mask.append(face) elif res == INT_INSIDE: # lets consider the 3 sub-faces with itrsct as vertex, at least one should 2D- # intersect with the rear half-segment and should be added to the mask if b > 0: test_seg = np.array([segment[0], itrsct]) elif b < 0: test_seg = np.array([itrsct, segment[1]]) else: continue subfaces = np.array([ (face[0], face[1], itrsct), (face[1], face[2], itrsct), (face[2], face[0], itrsct), ]) overlap = triangles_overlap_segment_2d(subfaces, test_seg, accept_vertex_only=False) if np.any(overlap): mask.append(subfaces[np.argmax(overlap)]) else: logging.warning( f"inconsistent INTERSECTION_INSIDE with segment {segment} and " f"face {face}: no overlapping sub-face") elif res == INT_EDGE: # in this case, itrsct defines two sub-faces, at least one should 2D-intersect with # the rear half-segment and should be added to the mask if b > 0: test_seg = np.array([segment[0], itrsct]) elif b < 0: test_seg = np.array([itrsct, segment[1]]) else: continue if ~np.isclose(np.linalg.norm(test_seg[1] - test_seg[0]), 0, atol=ATOL, rtol=RTOL): if s == 0: subfaces = np.array([(face[0], face[1], itrsct), (itrsct, face[1], face[2])]) elif t == 0: subfaces = np.array([(face[0], itrsct, face[2]), (itrsct, face[1], face[2])]) else: subfaces = np.array([(face[0], itrsct, face[2]), (face[0], face[1], itrsct)]) overlap = triangles_overlap_segment_2d( subfaces, test_seg, accept_vertex_only=False) mask.extend(subfaces[overlap]) elif res == INT_VERTEX: # in that case we add the face to the mask if the rear half-segment 2D intersects # with the face if b > 0: test_seg = np.array([segment[0], itrsct]) elif b < 0: test_seg = np.array([itrsct, segment[1]]) else: continue if ~np.isclose(np.linalg.norm(test_seg[1] - test_seg[0]), 0, atol=ATOL, rtol=RTOL): overlap = triangles_overlap_segment_2d( np.array([face]), test_seg, accept_vertex_only=False) if overlap[0]: mask.append(face) else: logging.warning( f"inconsistent result code {res} from segment_triangle_intersection with " f"segment {segment} and face {face}") # apply mask on segment polys = [] for f in mask: p = Polygon(f[:, 0:2].round(decimals=14)) if p.is_valid: polys.append(p) msk_seg = asLineString(segment).difference(shapely.ops.unary_union(polys)) # TODO: cases where we might want to keep a point # - seg parallel to camera axis # - others? if np.isclose(msk_seg.length, 0, atol=ATOL, rtol=RTOL): # segments with identical start/stop location are sometime returned return np.empty(shape=(0, 2, 3)) elif msk_seg.geom_type == "LineString": return np.array([msk_seg.coords]) elif msk_seg.geom_type == "MultiLineString": output = np.array( [np.array(l.coords) for l in msk_seg if l.length > 1e-14]) return np.empty(shape=(0, 2, 3)) if len(output) == 0 else output
def mask_segment_parallel(segment: np.ndarray, faces: np.ndarray) -> np.ndarray: """ Compute the visibility of the segment given the provided faces. Segments are hidden when the are on the opposite side of the normal :param segment: (2x3) the segment to process :param faces: (Nx3x3) the faces to consider :return: (Mx2x3) list of visible sub-segments """ if not _validate_shape(segment, 2, 3): raise ValueError( f"segment has shape {segment.shape} instead of (2, 3)") if not _validate_shape(faces, None, 3, 3): raise ValueError(f"faces has shape {faces.shape} instead of (M, 3, 3)") # Check 2D overlap, all non-overlapping faces can be ignored active = triangles_overlap_segment_2d(faces, segment) if not np.any(active): return segment.reshape((1, 2, 3)) mask = [] # noinspection PyShadowingNames,PyUnusedLocal def callback(segment, triangles, res, r, s, t, b, itrsct): nonlocal mask if res in (NO_INT_PARALLEL_BEHIND, NO_INT_SHORT_SEGMENT_BEHIND): # this face is masking the segment mask.extend(triangles) return elif res in [ DEGENERATE, NO_INT_SHORT_SEGMENT_FRONT, NO_INT_PARALLEL_FRONT, INT_COPLANAR, ]: return # build an array of rear half-segments half_segments = np.repeat(segment.reshape(1, 2, 3), len(triangles), axis=0) idx = b > 0 half_segments[idx, 1, :] = itrsct[idx, :] half_segments[~idx, 0, :] = itrsct[~idx, :] if res == NO_INT_OUTSIDE_FACE: # segment crosses the face's plane, but not the face itself # masking occurs if the rear half-segment 2D-overlaps the face overlap = triangles_overlap_segment_2d(triangles, half_segments, accept_vertex_only=False) mask.extend(triangles[overlap]) elif res == INT_INSIDE: # lets consider the 3 sub-faces with itrsct as vertex, at least one should 2D- # intersect with the rear half-segment and should be added to the mask # TODO: this case is not vectorized but is rather rare anyway for i in range(len(triangles)): subfaces = np.array([ (triangles[i, 0], triangles[i, 1], itrsct[i]), (triangles[i, 1], triangles[i, 2], itrsct[i]), (triangles[i, 2], triangles[i, 0], itrsct[i]), ]) overlap = triangles_overlap_segment_2d( subfaces, half_segments[i], accept_vertex_only=False) if np.any(overlap): mask.append(subfaces[np.argmax(overlap)]) else: logging.warning( f"inconsistent INTERSECTION_INSIDE with segment {segment} and " f"face {triangles[i]}: no overlapping sub-face") elif res == INT_EDGE: # in this case, itrsct defines two sub-faces, at least one should 2D-intersect with # the rear half-segment and should be added to the mask idx, = np.nonzero(~np.isclose( np.linalg.norm(half_segments[:, 1] - half_segments[:, 0], axis=1), 0, atol=ATOL, rtol=RTOL, )) for i in idx: if s[i] == 0: subfaces = np.array([ (triangles[i, 0], triangles[i, 1], itrsct[i]), (itrsct[i], triangles[i, 1], triangles[i, 2]), ]) elif t[i] == 0: subfaces = np.array([ (triangles[i, 0], itrsct[i], triangles[i, 2]), (itrsct[i], triangles[i, 1], triangles[i, 2]), ]) else: subfaces = np.array([ (triangles[i, 0], itrsct[i], triangles[i, 2]), (triangles[i, 0], triangles[i, 1], itrsct[i]), ]) overlap = triangles_overlap_segment_2d( subfaces, half_segments[i], accept_vertex_only=False) mask.extend(subfaces[overlap]) elif res == INT_VERTEX: # in that case we add the face to the mask if the rear half-segment 2D intersects # with the face idx = ~np.isclose( np.linalg.norm(half_segments[:, 1] - half_segments[:, 0], axis=1), 0, atol=ATOL, rtol=RTOL, ) overlap = triangles_overlap_segment_2d(triangles[idx], half_segments[idx], accept_vertex_only=False) mask.extend(triangles[idx][overlap]) segment_triangles_intersection(segment, faces[active], callback) # apply mask on segment polys = [] for f in mask: p = Polygon(f[:, 0:2].round(decimals=14)) if p.is_valid: polys.append(p) msk_seg = asLineString(segment).difference(shapely.ops.unary_union(polys)) geom_type = msk_seg.geom_type length = msk_seg.length # TODO: cases where we might want to keep a point # - seg parallel to camera axis # - others? if np.isclose(length, 0, atol=ATOL, rtol=RTOL): # segments with identical start/stop location are sometime returned output = np.empty(shape=(0, 2, 3)) elif geom_type == "LineString": output = np.array([msk_seg.coords]) elif geom_type == "MultiLineString": output = np.array( [np.array(l.coords) for l in msk_seg if l.length > 1e-14]) if len(output) == 0: output.shape = (0, 2, 3) else: output = np.empty(shape=(0, 2, 3)) return output
def Place_Electrodes(l, phi_0, lambda_approx, electrodes_angle, electrodes_thickness, removal_thickness, IDT_data, electrode_type, electrode_rotate_angle=0): plot = False Rlist = IDT_data['R'] Thetalist = IDT_data['Theta'] Rmin = [] Rmax = [] Rline = [[], []] for polarity in range(len(Rlist)): for i in range(len(Rlist[polarity])): R = Rlist[polarity][i] Theta = Thetalist[polarity][i] Rmin = min([R.min(), Rmin]) Rmax = max([R.max(), Rmax]) xy = pol2cart(Theta, R) if l == 0: #Rline[polarity].append(shapely_geom.LinearRing(shapely_geom.asLineString(xy))) Rline[polarity].append(shapely_geom.asLinearRing(xy)) else: Rline[polarity].append(shapely_geom.asLineString(xy)) Rmax = 1.5 * Rmax xyelect0 = pol2cart([electrodes_angle[0], electrodes_angle[0]], [Rmin, Rmax]) xyelect1 = pol2cart([electrodes_angle[1], electrodes_angle[1]], [Rmin, Rmax]) elect0 = shapely_geom.LineString([(xyelect0[0, 0], xyelect0[0, 1]), (xyelect0[1, 0], xyelect0[1, 1])]) elect1 = shapely_geom.LineString([(xyelect1[0, 0], xyelect1[0, 1]), (xyelect1[1, 0], xyelect1[1, 1])]) elect0 = shapely_affinity.rotate(elect0, electrode_rotate_angle, origin=(xyelect0[0, 0], xyelect0[0, 1]), use_radians=False) elect1 = shapely_affinity.rotate(elect1, electrode_rotate_angle, origin=(xyelect1[0, 0], xyelect1[0, 1]), use_radians=False) removal0 = deepcopy(elect0) removal1 = deepcopy(elect1) removal_center = shapely_geom.Point( 0., 0.).buffer(Rmin - electrodes_thickness * thickness_factor(electrode_type) / 2) Elect0_polyg = elect0.buffer(electrodes_thickness / 2) Elect1_polyg = elect1.buffer(electrodes_thickness / 2) IDT_data['removal'] = { 'removal0': removal0.buffer(removal_thickness / 2), 'removal1': removal1.buffer(removal_thickness / 2), 'removal_center': removal_center } if False: #electrode_rotate_angle != 0. : #draw hollow electrode to avoid forcing opposite voltage to the wave Hole_elect0 = elect0.buffer( electrodes_thickness / 4) #up to 50% of the power branch can be hollow Hole_elect1 = elect1.buffer(electrodes_thickness / 4) Phi_0 = Electrode_pattern(electrode_type, phi_0) N = Phi_0[0].size + Phi_0[1].size #number of electrodes over lambda Hole_elect0 = Hole_elect0.intersection( shapely_geom.MultiLineString(Rline[1]).buffer(lambda_approx / (4 * N))) Hole_elect1 = Hole_elect1.intersection( shapely_geom.MultiLineString(Rline[0]).buffer(lambda_approx / (4 * N))) IDT_data['removal']['Hole_elect0'] = Hole_elect0 IDT_data['removal']['Hole_elect1'] = Hole_elect1 #Elect0_polyg = Elect0_polyg.difference(Hole_elect0) #Elect1_polyg = Elect1_polyg.difference(Hole_elect1) Rline = clean_edges(Rline, elect0, elect1) IDT_data['electrodes'] = {'elect0': Elect0_polyg, 'elect1': Elect1_polyg} IDT_data['Rline'] = Rline if plot: ax = plt.subplot(111) patch1 = PolygonPatch(elect0.buffer(electrodes_thickness / 2), fc=RED, ec=RED, alpha=0.5, zorder=2) ax.add_patch(patch1) patch2 = PolygonPatch(elect1.buffer(electrodes_thickness / 2), fc=BLUE, ec=BLUE, alpha=0.5, zorder=2) ax.add_patch(patch2) ax.set_title('a) dilation, cap_style=3') xrange = [-0.005, +0.005] yrange = [-0.005, +0.005] ax.axis([xrange[0], xrange[1], yrange[0], yrange[1]]) ax.set_aspect(1) plt.show()
def calcElev(linestring): # Holds coordinates where we check for elevation pointArrayX = [] pointArrayY = [] # Holds distance according to above coordinates distArray = [] # # Convert line to spherical mercator # #print "Starter transformering..." # Convert to numpy array ag = np.asarray(linestring) # Extract one array for lon and one for lat lon, lat = zip(*ag) # Define projections #fromProj = pyproj.Proj(init='epsg:3785') fromProj = pyproj.Proj(init='epsg:4326') toProj = pyproj.Proj(init='epsg:32633') # Reproject the line x2, y2 = pyproj.transform(fromProj, toProj, lon, lat) # Create new numpy array a = np.array(zip(x2,y2)) # Recreate linestring projectedLinestrings = asLineString(a) #print projectedLinestrings.length #print "Slutt transformering..." # # Set distance for interpolation on line according to length of route # - projectedLinestrings.length defines length of route in meter # - stepDist defines how often we want to extract a height value # i.e. stepDist=50 defines that we should extract an elevation value for # every 50 meter along the route stepDist = 0 if projectedLinestrings.length < 2000: stepDist = 20 elif projectedLinestrings.length >1999 and projectedLinestrings.length < 4000: stepDist = 100 elif projectedLinestrings.length >3999 and projectedLinestrings.length < 10000: stepDist = 100 else: stepDist = 200 # # Make interpolation point along line with stepDist form above. # Add these point to arrays. # step = 0 # Trur ikke multilinestringer kommer inn her lenger # så koden kan sannsynligvis fjernes #print "Starter interpolering..." if(projectedLinestrings.geom_type == "LineString"): #linestring = projectedLinestrings while step<projectedLinestrings.length+stepDist: point = projectedLinestrings.interpolate(step) # Project back to spherical mercator coordinates x, y = pyproj.transform(toProj, pyproj.Proj(init='epsg:3785'), point.x, point.y) #x, y = point.x, point.y pointArrayX.append(x) pointArrayY.append(y) distArray.append(step) step = step + stepDist #print "Slutt interpolering..." """ for coords in projectedLinestrings.coords: point = Point(coords) x, y = pyproj.transform(toProj, fromProj, point.x, point.y) pointArrayX.append(x) pointArrayY.append(y) distArray.append(projectedLinestrings.project(point)) """ # # Convert line to spherical mercator # #print "Starter transformering..." # Convert to numpy array ag = np.asarray(linestring) # Extract one array for lon and one for lat lon, lat = zip(*ag) # Define projections #fromProj = pyproj.Proj(init='epsg:3785') fromProj = pyproj.Proj(init='epsg:4326') toProj = pyproj.Proj(init='epsg:3785') # Reproject the line x2, y2 = pyproj.transform(fromProj, toProj, lon, lat) # Create new numpy array a = np.array(zip(x2,y2)) # Recreate linestring projectedLinestrings = asLineString(a) #print "Slutt transformering..." # Calculate area in image to get # Get bounding box of area bbox = projectedLinestrings.bounds # Expand the bounding box with 200 meter on each side ulx = bbox[0]-200 uly = bbox[3]+200 lrx = bbox[2]+200 lry = bbox[1]-200 gt, band_array = createRasterArray(ulx, uly, lrx, lry) nx = len(band_array[0]) ny = len(band_array) # Compute mid-point grid spacings ax = np.array([ulx + ix*gt[1] + gt[1]/2.0 for ix in range(nx)]) ay = np.array([uly + iy*gt[5] + gt[5]/2.0 for iy in range(ny)]) # Create numpy array z = np.array(band_array) # Set min/max values of image ny, nx = z.shape xmin, xmax = ax[0], ax[nx-1] #ax[5136] ymin, ymax = ay[ny-1], ay[0] #ay[5144], ay[0] # Turn these into arrays of x & y coords xi = np.array(pointArrayX, dtype=np.float) yi = np.array(pointArrayY, dtype=np.float) # Now, we'll set points outside the boundaries to lie along an edge xi[xi > xmax] = xmax xi[xi < xmin] = xmin yi[yi > ymax] = ymax yi[yi < ymin] = ymin # We need to convert these to (float) indicies # (xi should range from 0 to (nx - 1), etc) xi = (nx - 1) * (xi - xmin) / (xmax - xmin) yi = -(ny - 1) * (yi - ymax) / (ymax - ymin) # Interpolate elevation values # map_coordinates does cubic interpolation by default, # use "order=1" to preform bilinear interpolation elev = map_coordinates(z, [yi, xi], order=1) return (distArray, elev, pointArrayX, pointArrayY)
def test_linestring_adapter(self): a = numpy.array([[1.0, 1.0, 2.0, 2.0, 1.0], [3.0, 4.0, 4.0, 3.0, 3.0]]) t = a.T s = geometry.asLineString(t) self.assertEqual(list(s.coords), [(1.0, 3.0), (1.0, 4.0), (2.0, 4.0), (2.0, 3.0), (1.0, 3.0)])
def create_pos_file(posfile,scalefile, xlims,ylims,dx,\ geofile=None,ndmin=5, lcmax=2000.,r=1.05, scalefac=1.0): """ Generates a gmsh background scale file (*.pos) If a geofile is specified the mesh is embedded """ from shapely import geometry, speedups if speedups.available: speedups.enable() X,Y = np.meshgrid(np.arange(xlims[0],xlims[1],dx),np.arange(ylims[0],ylims[1],dx)) xy = np.vstack((X.ravel(),Y.ravel())).T Np = xy.shape[0] nj,ni=X.shape # Load the scalefile xyscale,gridscale = readShpPointLine(scalefile,FIELDNAME='scale') # Load all of the points into shapely type geometry # Distance method won't work with numpy array #P = geometry.asPoint(xy) P = [geometry.Point(xy[i,0],xy[i,1]) for i in range(Np)] L=[] for ll in xyscale: L.append(geometry.asLineString(ll)) nlines = len(L) scale_all = np.zeros((nj,ni,nlines)) for n in range(nlines): print 'Calculating distance from line %d...'%n ss = gridscale[n] * scalefac lmin = ndmin * ss # Find the maximum distance Nk = np.log(lcmax/ss)/np.log(r) print ss,Nk lmax = lmin + Nk * ss dist = [L[n].distance(P[i]) for i in range(Np)] dist = np.array(dist).reshape((nj,ni)) # Calculate the scale N = (dist-lmin)/ss scale = ss*r**N ind = dist<=lmin if ind.any(): scale[ind] = ss ind = scale>lcmax if ind.any(): scale[ind] = lcmax scale_all[:,:,n] = scale scale_min = scale_all.min(axis=-1) write_pos_file(posfile,X,Y,scale_min) if not geofile == None: fgeo = open(geofile,'a') fgeo.write("// Merge a post-processing view containing the target mesh sizes\n") fgeo.write('Merge "%s";'%posfile) fgeo.write("// Apply the view as the current background mesh\n") fgeo.write("Background Mesh View[0];\n") fgeo.close()
def init_mesh_point(self, x, y): # ищем точку в созданных или создаём f = list(filter(lambda p: (p.xy == [x, y]).all(), self.points)) if len(f) == 0: point = MeshPoint(x, y, self.mean_z, index=len(self.points)) self.points.append(point) else: point = f[0] # точка сверху if point.up is None: # если соседняя точка лежит вне области if not self.geom.contains(asPoint([x, y + self.dy])): # перессекаем boundary с вертикальной прямой xyz = np.array(self.geom.boundary.intersection( asLineString([[x, y], [x, self.max_y]]))) # если xyz содержит несколько точек, берём ближнюю if xyz.shape != (3,): xyz = sorted(xyz, key=lambda v: v[1])[0] # создаём точку up = MeshPoint(*xyz, index=len(self.points), is_boundary=True) self.points.append(up) else: up = self.init_mesh_point(x, y + self.dy) point.set_up(up) # точка справа if point.right is None: # если соседняя точка лежит вне области if not self.geom.contains(asPoint([x + self.dx, y])): # перессекаем boundary с горизонтальной прямой xyz = np.array(self.geom.boundary.intersection( asLineString([[x, y], [self.max_x, y]]))) # если xyz содержит несколько точек, берём ближнюю if xyz.shape != (3,): xyz = sorted(xyz, key=lambda v: v[0])[0] # создаём точку right = MeshPoint(*xyz, index=len(self.points), is_boundary=True) self.points.append(right) else: right = self.init_mesh_point(x + self.dx, y) point.set_right(right) # точка снизу if point.down is None: # если соседняя точка лежит вне области if not self.geom.contains(asPoint([x, y - self.dy])): # перессекаем boundary с вертикальной прямой xyz = np.array(self.geom.boundary.intersection( asLineString([[x, self.min_y], [x, y]]))) # если xyz содержит несколько точек, берём ближнюю if xyz.shape != (3,): xyz = sorted(xyz, key=lambda v: v[1], reversed=True)[0] # создаём точку down = MeshPoint(*xyz, index=len(self.points), is_boundary=True) self.points.append(down) else: down = self.init_mesh_point(x, y - self.dy) point.set_down(down) # точка слева if point.left is None: # если соседняя точка лежит вне области if not self.geom.contains(asPoint([x - self.dx, y])): # перессекаем boundary с горизонтальной прямой xyz = np.array(self.geom.boundary.intersection( asLineString([[self.min_x, y], [x, y]]))) # если xyz содержит несколько точек, берём ближнюю if xyz.shape != (3,): xyz = sorted(xyz, key=lambda v: v[0], reversed=True)[0] # создаём точку left = MeshPoint(*xyz, index=len(self.points), is_boundary=True) self.points.append(left) else: left = self.init_mesh_point(x - self.dx, y) point.set_left(left) return point
def create_pos_file(posfile,scalefile, xlims,ylims,dx,\ geofile=None,ndmin=5, lcmax=2000.,r=1.05, scalefac=1.0): """ Generates a gmsh background scale file (*.pos) If a geofile is specified the mesh is embedded """ from shapely import geometry, speedups import pandas as pd if speedups.available: speedups.enable() X, Y = np.meshgrid(np.arange(xlims[0], xlims[1], dx), np.arange(ylims[0], ylims[1], dx)) xy = np.vstack((X.ravel(), Y.ravel())).T Np = xy.shape[0] nj, ni = X.shape # Load the scalefile xyscale, gridscale = readShpPointLine(scalefile, FIELDNAME='scale') # Load all of the points into shapely type geometry # Distance method won't work with numpy array #P = geometry.asPoint(xy) P = [geometry.Point(xy[i, 0], xy[i, 1]) for i in range(Np)] L = [] for ll in xyscale: L.append(geometry.asLineString(ll)) # Vectorize operations using pandas geo_points = pd.DataFrame({'single_column':xy.tolist()}).single_column.\ apply(lambda x: geometry.Point(x[0],x[1])).values geo_lines = pd.DataFrame({'single_column':xyscale}).single_column.\ apply(lambda x: geometry.LineString(x)).values def distance(a_point, a_line): return a_point.distance(a_line) distance_vec = np.vectorize(distance) dist_all = distance_vec(geo_points[..., np.newaxis], geo_lines) nlines = len(L) scale_all = np.zeros((nj, ni, nlines)) for n in range(nlines): print('Calculating distance from line %d...' % n) ss = gridscale[n] * scalefac lmin = ndmin * ss # Find the maximum distance Nk = np.log(lcmax / ss) / np.log(r) print(ss, Nk) lmax = lmin + Nk * ss #dist = [L[n].distance(P[i]) for i in range(Np)] #dist = np.array(dist).reshape((nj,ni)) dist = dist_all[:, n].reshape((nj, ni)) # Calculate the scale N = (dist - lmin) / ss scale = ss * r**N ind = dist <= lmin if ind.any(): scale[ind] = ss ind = scale > lcmax if ind.any(): scale[ind] = lcmax scale_all[:, :, n] = scale scale_min = scale_all.min(axis=-1) write_pos_file(posfile, X, Y, scale_min) if not geofile is None: fgeo = open(geofile, 'a') fgeo.write( "// Merge a post-processing view containing the target mesh sizes\n" ) fgeo.write('Merge "%s";' % posfile) fgeo.write("// Apply the view as the current background mesh\n") fgeo.write("Background Mesh View[0];\n") fgeo.close()
def write_line_string(hull): with open("data/line_{0}.csv".format(hull.shape[0]), "w") as file: file.write('\"line\"\n') text = asLineString(hull).wkt file.write('\"' + text + '\"\n')
def get_path(n0, n1): """If n0 and n1 are connected nodes in the graph, this function return an array of point coordinates along the line linking these two nodes.""" return np.array(json.loads(nx_list_subgraph[n0][n1]['Json'])['coordinates']) def get_full_path(path): """ Create numpy array line result :param path: results of nx.shortest_path function :return: coordinate pairs along a path """ p_list = [] curp = None for i in range(len(path)-1): p = get_path(path[i], path[i+1]) if curp is None: curp = p if np.sum((p[0]-curp)**2) > np.sum((p[-1]-curp)**2): p = p[::-1, :] p_list.append(p) curp = p[-1] return np.vstack(p_list) # create numpy array of coordinates representing result path nx_array_path = get_full_path(nx_short_path) # convert numpy array to Shapely Linestring out_shortest_path = asLineString(nx_array_path) write_geojson("../geodata/ch08_final_netx_sh_path.geojson", out_shortest_path.__geo_interface__ )
def calculate(self, k=3): """ Calculates the convex hull of the data set as an array of points :param k: Number of nearest neighbors :return: Array of points (N, 2) with the concave hull of the data set """ if self.data_set.shape[0] < 3: return None if self.data_set.shape[0] == 3: return self.data_set # Make sure that k neighbors can be found kk = min(k, self.data_set.shape[0]) first_point = self.get_lowest_latitude_index(self.data_set) current_point = first_point # Note that hull and test_hull are matrices (N, 2) hull = np.reshape(np.array(self.data_set[first_point, :]), (1, 2)) test_hull = hull # Remove the first point self.indices[first_point] = False prev_angle = 270 # Initial reference id due west. North is zero, measured clockwise. step = 2 stop = 2 + kk while ((current_point != first_point) or (step == 2)) and len(self.indices[self.indices]) > 0: if step == stop: self.indices[first_point] = True knn = self.get_k_nearest(current_point, kk) # Calculates the headings between first_point and the knn points # Returns angles in the same indexing sequence as in knn angles = self.calculate_headings(current_point, knn, prev_angle) # Calculate the candidate indexes (largest angles first) candidates = np.argsort(-angles) i = 0 invalid_hull = True while invalid_hull and i < len(candidates): candidate = candidates[i] # Create a test hull to check if there are any self-intersections next_point = np.reshape(self.data_set[knn[candidate]], (1, 2)) test_hull = np.append(hull, next_point, axis=0) line = asLineString(test_hull) invalid_hull = not line.is_simple i += 1 if invalid_hull: return self.recurse_calculate() # prev_angle = self.calculate_headings(current_point, np.array([knn[candidate]])) prev_angle = self.calculate_headings(knn[candidate], np.array([current_point])) current_point = knn[candidate] hull = test_hull # write_line_string(hull) self.indices[current_point] = False step += 1 poly = asPolygon(hull) count = 0 total = self.data_set.shape[0] for ix in range(total): pt = asPoint(self.data_set[ix, :]) if poly.intersects(pt) or pt.within(poly): count += 1 else: d = poly.distance(pt) if d < 1e-5: count += 1 if count == total: return hull else: return self.recurse_calculate()
points = [] prev_x = 0 prev_y = 0 for i in range(0, len(coords) - 1, 2): if coords[i] == 0 and coords[i + 1] == 0: continue prev_x += coords[i + 1] prev_y += coords[i] # A round to 6 digits ensures that the floats are the same as when they were encoded points.append((round(prev_x, 6), round(prev_y, 6))) return points # Go through each row of the data file and decode the encoded polyline into an SRID:3857 WKT LineString output, count = [], 0 file_name = "gps_routes_sample.tsv" with open(file_name, "rU") as f: reader = csv.reader(f, delimiter="\t") for i, row in enumerate(reader): decoded_polyline = decode(row[0]) # decode the polyline into an [x,y] coordinate array of arrays linestring = asLineString(decoded_polyline) # create a WKT LineString from the coordinate array output.append([count, "SRID=3857;" + transform(project, linestring).wkt]) # project to SRID: 3857 count += 1 # Write the transformed LineString data to a tab delimited file - easy to COPY into PostgreSQL database with open("gps_routes_sample_parsed.tab", "a") as tab: writer = csv.writer(tab, delimiter="\t") writer.writerows(output)
#!/usr/bin/env python3 # -*- coding: utf-8 -*- ############################################################################### from shapely.geometry import Point from numpy import array array(Point(0, 0)) from shapely.geometry import LineString array(LineString([(0, 0), (1, 1)])) ############################################################################### Point(0, 0).xy LineString([(0, 0), (1, 1)]).xy ############################################################################### from shapely.geometry import asPoint pa = asPoint(array([0.0, 0.0])) pa.wkt ############################################################################### from shapely.geometry import asLineString la = asLineString(array([[1.0, 2.0], [3.0, 4.0]])) la.wkt