def test_clip_points_by_polygons_with_holes0(self): """Points can be clipped by polygons with holes """ # Define an outer ring outer_ring = numpy.array([[106.79, -6.233], [106.80, -6.24], [106.78, -6.23], [106.77, -6.21], [106.79, -6.233]]) # Define inner rings inner_rings = [ numpy.array([[106.77827, -6.2252], [106.77775, -6.22378], [106.78, -6.22311], [106.78017, -6.22530], [106.77827, -6.2252]])[::-1], numpy.array([[106.78652, -6.23215], [106.78642, -6.23075], [106.78746, -6.23143], [106.78831, -6.23307], [106.78652, -6.23215]])[::-1] ] v = Vector( geometry=[Polygon(outer_ring=outer_ring, inner_rings=inner_rings)]) assert v.is_polygon_data # Write it to file tmp_filename = unique_filename(suffix='.shp') v.write_to_file(tmp_filename) # Read polygon it back L = read_layer(tmp_filename) P = L.get_geometry(as_geometry_objects=True)[0] outer_ring = P.outer_ring inner_ring0 = P.inner_rings[0] inner_ring1 = P.inner_rings[1] # Make some test points points = generate_random_points_in_bbox(outer_ring, 1000, seed=13) # Clip to outer ring, excluding holes indices = inside_polygon(points, P.outer_ring, holes=P.inner_rings) # Sanity for point in points[indices, :]: # Must be inside outer ring assert is_inside_polygon(point, outer_ring) # But not in any of the inner rings assert not is_inside_polygon(point, inner_ring0) assert not is_inside_polygon(point, inner_ring1) if False: # Store for visual check pol = Vector(geometry=[P]) tmp_filename = unique_filename(suffix='.shp') pol.write_to_file(tmp_filename) # print 'Polygon with holes written to %s' % tmp_filename pts = Vector(geometry=points[indices, :]) tmp_filename = unique_filename(suffix='.shp') pts.write_to_file(tmp_filename)
def make_circular_polygon(centers, radii, attributes=None): """Create circular polygon in geographic coordinates Args: centers: list of (longitude, latitude) radii: desired approximate radii in meters (must be monotonically ascending). Can be either one number or list of numbers attributes (optional): Attributes for each center Returns: Vector polygon layer representing circle in WGS84 """ if not isinstance(radii, list): radii = [radii] # FIXME (Ole): Check that radii are monotonically increasing circles = [] new_attributes = [] for i, center in enumerate(centers): p = Point(longitude=center[0], latitude=center[1]) inner_rings = None for radius in radii: # Generate circle polygon C = p.generate_circle(radius) circles.append(Polygon(outer_ring=C, inner_rings=inner_rings)) # Store current circle and inner ring for next poly inner_rings = [C] # Carry attributes for center forward attr = {} if attributes is not None: for key in attributes[i]: attr[key] = attributes[i][key] # Add radius to this ring attr['Radius'] = radius new_attributes.append(attr) Z = Vector( geometry=circles, # List with circular polygons data=new_attributes, # Associated attributes geometry_type='polygon') return Z
def buffer_points(centers, radii, hazard_zone_attribute, data_table=None): """Buffer points for each center with defined radii. If the data_table is defined, then the data will also be copied to the result. This function is used for making buffer of volcano point hazard. :param centers: All center of each point (longitude, latitude) :type centers: list :param radii: Desired approximate radii in meters (must be monotonically ascending). Can be either one number or list of numbers :type radii: int, list :param hazard_zone_attribute: The name of the attributes representing hazard zone. :type hazard_zone_attribute: str :param data_table: Data for each center (optional) :type data_table: list :return: Vector polygon layer representing circle in WGS84 :rtype: Vector """ if not isinstance(radii, list): radii = [radii] # Check that radii are monotonically increasing monotonically_increasing_flag = all( x < y for x, y in zip(radii, radii[1:])) if not monotonically_increasing_flag: raise RadiiException(RadiiException.suggestion) circles = [] new_data_table = [] for i, center in enumerate(centers): p = Point(longitude=center[0], latitude=center[1]) inner_rings = None for radius in radii: # Generate circle polygon circle = p.generate_circle(radius) circles.append(Polygon(outer_ring=circle, inner_rings=inner_rings)) # Store current circle and inner ring for next poly inner_rings = [circle] # Carry attributes for center forward (deep copy) row = {} if data_table is not None: for key in data_table[i]: row[key] = data_table[i][key] # Add radius to this ring row[hazard_zone_attribute] = radius new_data_table.append(row) circular_polygon = Vector( geometry=circles, # List with circular polygons data=new_data_table, # Associated attributes geometry_type='polygon') return circular_polygon