def trend_3rd_order(X): '''3rd order surface trend.''' validate_2d_array(X, n_cols=2) _a2b = X[:, 0]**2. * X[:, 1] _ab2 = X[:, 0] * X[:, 1]**2. return np.hstack([ X**3., X**2., X, _a2b[:, None], _ab2[:, None], X.prod(axis=1)[:, None] ])
def voronoi_polygons(X, margin=0): ''' Returns a set of Voronoi polygons corresponding to a set of points X. :param X: Array of points (optional). Numpy array, shape = [n, 2]. :param margin: Minimum margin to extend the outer polygons of the tessellation. Non-negative float. :return: Geopandas data frame. ''' validate_2d_array(X, n_cols=2) n_points = X.shape[0] c1, c2 = np.sort(X[:, 0]), np.sort(X[:, 1]) _diffs = np.array( [max(margin, np.diff(c1).mean()), max(margin, np.diff(c2).mean())]) min_c1, min_c2 = X.min(0) - _diffs max_c1, max_c2 = X.max(0) + _diffs extra_points = np.vstack([ np.vstack([np.repeat(min_c1, n_points), c2]).T, np.vstack([np.repeat(max_c1, n_points), c2]).T, np.vstack([c1, np.repeat(min_c2, n_points)]).T, np.vstack([c1, np.repeat(max_c2, n_points)]).T ]) _X = np.vstack([X, extra_points]) # Define polygons geometry based on tessellation vor = Voronoi(_X) lines = [ geometry.LineString(vor.vertices[li]) for li in vor.ridge_vertices if -1 not in li ] disord = geometry.MultiPolygon(list(polygonize(lines))) ix_order = np.array( [[i for i, di in enumerate(disord) if di.contains(geometry.Point(pi))] for pi in X]).ravel() return geop.GeoDataFrame( {'geometry': geometry.MultiPolygon([disord[i] for i in ix_order])})
def locate(self, X): ''' Associate geometries in the region with a set of locations X. :param X: Set of coordinates. Numpy array, shape = [n, 2] :return: Array with tiles per point (-1 for points outside the spatial frame). Numpy array of integers. ''' validate_2d_array(X) geom_points = geop.GeoDataFrame( crs=self.projection, geometry=[geometry.Point(xi) for xi in X]) ix = geop.tools.sjoin(geom_points, self.region, how='left')['index_right'] ix[np.isnan(ix)] = -1 return np.array(ix).astype(int)
def regular_polygons(X, radius, n_angles=8): ''' Return a set of regular polygons around points X. :param X: Array of points (optional). Numpy array, shape = [n, 2]. :param radius: Circumradius of the polygon. Positive float. :param n_angles: Number of angles of each polygon. Integer >= 3. :return: Geopandas data frame. ''' validate_2d_array(X, n_cols=2) assert isinstance(n_angles, int), 'n_angles must be an integer.' assert n_angles >= 3, 'Angles must be greater than two.' vertex = np.pi * np.linspace(0, 2, n_angles + 1) if isinstance(radius, float): assert radius > 0, 'Radius must be positive.' polys = [ np.vstack([ xi + radius * np.array([np.cos(t), np.sin(t)]) for t in vertex ]) for xi in X ] else: validate_1d_array(radius, size=X.shape[0]) polys = [ np.vstack( [xi + ri * np.array([np.cos(t), np.sin(t)]) for t in vertex]) for xi, ri in zip(X, radius) ] return geop.GeoDataFrame({ 'geometry': geometry.MultiPolygon([geometry.Polygon(pi) for pi in polys]) })
def __init__(self, points, attributes=None, crs=None): ''' General class to handle point pattern observations in space. :param points: Set of coordinates. Numpy array, shape = [n_points, 2]. :param attributes: Attributes associated to the points (optional). Numpy array or pandas DataFrame, shape = [n_points, m]. :param crs: Coordinate reference system (optional). String. ''' # NOTE: The use of crs is not tested yet!!! # Validate input points if isinstance(points, pd.DataFrame): points = np.array(points) validate_2d_array(points, n_cols=2) if crs is not None: #assert isinstance(crs, str) raise NotImplementedError # Define points geometry _region = {'geometry': [geometry.Point(pi) for pi in points]} if attributes is not None: _region = self._add_attributes(region_dict=_region, attributes=attributes) # Define region as GeoDataFrame self.centroids = points self.projection = crs self.region = geopandas.GeoDataFrame(_region, crs=self.projection) self.region.index.name = None # Bounding box _box = np.asarray(geometry.MultiPoint(points).bounds) self.box = pd.DataFrame({'x': _box[[0, 2]], 'y': _box[[1, 3]]})
def trend_1st_order(X): '''Bilinear surface trend.''' validate_2d_array(X, n_cols=2) return np.hstack([X, X.prod(axis=1)[:, None]])
def trend_2nd_order(X): '''2nd order surface trend.''' validate_2d_array(X, n_cols=2) return np.hstack([X**2., X, X.prod(axis=1)[:, None]])