def test_unset_paths(self): path = Path(__file__).parent.joinpath( 'invalid_output_dir/canvas_builder_invalid_path.png') canvas_builder = CanvasBuilder() canvas_builder.set_path(path) canvas_builder.set_size(Cu.from_px(100), Cu.from_px(100)) with self.assertRaises(RuntimeError): canvas_builder.build() assert not path.exists()
def test_png(self): path = Path(__file__).parent.joinpath('output/canvas_builder.png') path.unlink(missing_ok=True) canvas_builder = CanvasBuilder() canvas_builder.set_path(path) canvas_builder.set_size(Cu.from_px(100), Cu.from_px(100)) canvas_builder.set_pixel_scale_factor(2) canvas = canvas_builder.build() canvas.close() assert path.exists()
def test_validating_pixel_scale_factor(self): path = Path(__file__).parent.joinpath( 'output/canvas_builder_pixel_scale_factor.svg') canvas_builder = CanvasBuilder() canvas_builder.set_path(path) canvas_builder.set_size(Cu.from_px(100), Cu.from_px(100)) canvas_builder.set_pixel_scale_factor(2) with self.assertRaises(RuntimeError): canvas_builder.build() assert not path.exists()
def test_identity(self): assert CanvasUnit.from_pt(1).pt == 1 assert CanvasUnit.from_in(1).inches == 1 assert CanvasUnit.from_cm(1).cm == 1 assert CanvasUnit.from_mm(1).mm == 1 assert CanvasUnit.from_px(1).px == 1 assert CanvasUnit.from_pango(1).pango == 1 assert CanvasUnit.from_pt(2).pt == 2 assert CanvasUnit.from_in(2).inches == 2 assert CanvasUnit.from_cm(2).cm == 2 assert CanvasUnit.from_mm(2).mm == 2 assert CanvasUnit.from_px(2).px == 2 assert CanvasUnit.from_pango(2).pango == 2
def build_canvas(self, name: str) -> Canvas: name = re.sub(r'[^0-9A-Za-z_-]', '', name) path = Path(__file__).parent.joinpath( 'output/azimuthal_rendering_%s.svg' % name ) path.unlink(missing_ok=True) canvas_builder = CanvasBuilder() canvas_builder.set_path(path) canvas_builder.set_size( Cu.from_px( self.margin * 3 + self.azimuthal_width + self.wgs84_width ), Cu.from_px( self.margin * 2 + self.azimuthal_height ) ) return canvas_builder.build()
def get_file_dimensions_and_scale( path: Path) -> Tuple[float, float, float]: width: float height: float scale: float if path.suffix.lower() == '.pdf': pipe = subprocess.Popen( ['grep', '-a', 'MediaBox', path.as_posix()], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout, stderr = pipe.communicate() stdout_str = str(stdout.decode('utf-8')) match = re.search(r'([0-9.]+) ([0-9.]+) ]', stdout_str) width = float(match.group(1)) height = float(match.group(2)) scale = 1.0 elif path.suffix.lower() == '.svg': pipe = subprocess.Popen( ['grep', '-a', '<svg', path.as_posix()], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout, stderr = pipe.communicate() stdout_str = str(stdout.decode('utf-8')) width_match = re.search(r'width="([0-9.]+)pt"', stdout_str) height_match = re.search(r'height="([0-9.]+)pt"', stdout_str) width = float(width_match.group(1)) height = float(height_match.group(1)) scale = 1.0 else: from PIL import Image image = Image.open(path.as_posix()) width, height = image.size scale = CanvasUnit.from_px(float(image.info['dpi'][0])).inches image.close() return width, height, scale
def test_comparisons(self): assert CanvasUnit.from_in(1).pt > CanvasUnit.from_cm(1).pt assert CanvasUnit.from_cm(1).pt > CanvasUnit.from_mm(1).pt assert CanvasUnit.from_mm(1).pt > CanvasUnit.from_pt(1).pt assert CanvasUnit.from_pt(1).pt > CanvasUnit.from_px(1).pt assert CanvasUnit.from_px(1).pt > CanvasUnit.from_pango(1).pt
def draw_azimuthal( self, canvas: Canvas, crs: CRS, mask_proj: Polygon, world_map_wgs84: MultiPolygon, flight_paths_wgs84: MultiLineString ): origin_for_geo = GeoCoordinate(0, 0, crs) origin_x = Cu.from_px(self.margin + self.azimuthal_width / 2) origin_y = Cu.from_px(self.margin + self.azimuthal_height / 2) origin_for_canvas = CanvasCoordinate(origin_x, origin_y) # Fit the projected radius as the width of the canvas geo_to_canvas_scale = geo_canvas_ops.GeoCanvasScale( crs.ellipsoid.semi_major_metre, Cu.from_px(self.azimuthal_width / 2) ) # Convert the projected mask to the canvas. proj_to_canvas = geo_canvas_ops.build_transformer( crs=crs, data_crs=crs, scale=geo_to_canvas_scale, origin_for_geo=origin_for_geo, origin_for_canvas=origin_for_canvas ) mask_canvas = ops.transform(proj_to_canvas, mask_proj) # Convert the world map, from wgs84 to proj to canvas wgs84_crs = CRS.from_epsg(4326) wgs84_to_canvas = geo_canvas_ops.build_transformer( crs=crs, data_crs=wgs84_crs, scale=geo_to_canvas_scale, origin_for_geo=origin_for_geo, origin_for_canvas=origin_for_canvas ) world_map_canvas = transform_interpolated_euclidean( wgs84_to_canvas, world_map_wgs84 ) flight_paths_canvas = transform_interpolated_euclidean( wgs84_to_canvas, flight_paths_wgs84 ) # Render the polygons polygon_drawer = PolygonDrawer() polygon_drawer.fill_color = self.sea_color polygon_drawer.geoms = [mask_canvas] polygon_drawer.draw(canvas) polygon_drawer = PolygonDrawer() polygon_drawer.fill_color = self.land_color polygon_drawer.geoms = [world_map_canvas] polygon_drawer.draw(canvas) polygon_drawer = LineDrawer() polygon_drawer.stroke_color = self.line_color polygon_drawer.geoms = [flight_paths_canvas] polygon_drawer.draw(canvas)
def draw_wgs84( self, canvas: Canvas, mask_wgs84: MultiPolygon, world_map_wgs84: MultiPolygon, flight_paths_wgs84: MultiLineString ): wgs84_crs = CRS.from_epsg(4326) origin_for_geo = GeoCoordinate( 0, 0, wgs84_crs ) origin_for_canvas = CanvasCoordinate( Cu.from_px(self.margin * 2 + self.azimuthal_width + self.wgs84_width / 2), Cu.from_px(self.margin + self.wgs84_height / 2) ) # 1 pixel for every degree geo_to_canvas_scale = geo_canvas_ops.GeoCanvasScale( 1, Cu.from_px(1) ) # Todo: These transformations should be handled by build_transformer. mask_wgs84 = ops.transform(lambda x, y: (y, x), mask_wgs84) world_map_wgs84 = ops.transform(lambda x, y: (y, x), world_map_wgs84) flight_paths_wgs84 = ops.transform( lambda x, y: (y, x), flight_paths_wgs84 ) # Generate a polygon that represents the full range. domain_wgs84 = Polygon( [(-180, -90), (180, -90), (180, 90), (-180, 90)] ) wgs84_to_canvas = geo_canvas_ops.build_transformer( crs=wgs84_crs, data_crs=wgs84_crs, scale=geo_to_canvas_scale, origin_for_geo=origin_for_geo, origin_for_canvas=origin_for_canvas ) mask_canvas = ops.transform(wgs84_to_canvas, mask_wgs84) world_map_canvas = ops.transform(wgs84_to_canvas, world_map_wgs84) flight_paths_canvas = ops.transform( wgs84_to_canvas, flight_paths_wgs84 ) domain_canvas = ops.transform(wgs84_to_canvas, domain_wgs84) polygon_drawer = PolygonDrawer() polygon_drawer.fill_color = (0, 0, 0) polygon_drawer.geoms = [domain_canvas] polygon_drawer.draw(canvas) polygon_drawer = PolygonDrawer() polygon_drawer.fill_color = self.sea_color polygon_drawer.geoms = [mask_canvas] polygon_drawer.draw(canvas) polygon_drawer = PolygonDrawer() polygon_drawer.fill_color = self.land_color polygon_drawer.geoms = [world_map_canvas] polygon_drawer.draw(canvas) polygon_drawer = LineDrawer() polygon_drawer.stroke_color = self.line_color polygon_drawer.geoms = [flight_paths_canvas] polygon_drawer.draw(canvas)
def from_px(cls, x: float, y: float) -> 'CanvasCoordinate': return CanvasCoordinate(CanvasUnit.from_px(x), CanvasUnit.from_px(y))