def __add_detail_features(self, layer, detail_layer, lowres_features): #===================================================================== extra_details = [] for feature in lowres_features: self.__map_properties.update_feature_properties(feature) hires_layer_id = feature.get_property('details') hires_layer = self.__layer_dict.get(hires_layer_id) if hires_layer is None: log.warn("Cannot find details layer '{}'".format( feature.get_property('details'))) continue boundary_feature = hires_layer.boundary_feature if boundary_feature is None: raise KeyError("Cannot find boundary of '{}' layer".format( hires_layer.id)) # Calculate transformation to map source shapes to the destination # NOTE: We reorder the coordinates of the bounding rectangles so that the first # coordinate is the top left-most one. This should ensure that the source # and destination rectangles align as intended, without output features # being rotated by some multiple of 90 degrees. src = np.array(normalised_coords( boundary_feature.geometry.minimum_rotated_rectangle), dtype="float32") dst = np.array(normalised_coords( feature.geometry.minimum_rotated_rectangle), dtype="float32") transform = Transform(cv2.getPerspectiveTransform(src, dst)) minzoom = feature.get_property('maxzoom') + 1 if feature.get_property('type') != 'nerve': # Set the feature's geometry to that of the high-resolution outline feature.geometry = transform.transform_geometry( boundary_feature.geometry) else: # nerve feature.del_property('maxzoom') if hires_layer.source.raster_source is not None: extent = transform.transform_extent(hires_layer.source.extent) layer.add_raster_layer('{}_{}'.format(detail_layer.id, hires_layer.id), extent, hires_layer.source, minzoom, local_world_to_base=transform) # The detail layer gets a scaled copy of each high-resolution feature for hires_feature in hires_layer.features: new_feature = self.__new_detail_feature( layer.id, detail_layer, minzoom, transform.transform_geometry(hires_feature.geometry), hires_feature.properties) if new_feature.has_property('details'): extra_details.append(new_feature) # If hires features that we've just added also have details then add them # to the detail layer if extra_details: self.__add_detail_features(layer, detail_layer, extra_details)
def __init__(self, flatmap, id, source_path, base_layer=True): super().__init__(flatmap, id) self.__source_file = FilePath(source_path) self.__base_layer = base_layer self.__svg = etree.parse(self.__source_file.get_fp()).getroot() if 'viewBox' in self.__svg.attrib: (width, height) = tuple( float(x) for x in self.__svg.attrib['viewBox'].split()[2:]) else: width = length_as_pixels(self.__svg.attrib['width']) height = length_as_pixels(self.__svg.attrib['height']) # Transform from SVG pixels to world coordinates self.__transform = Transform( [[WORLD_METRES_PER_PIXEL, 0, 0], [0, WORLD_METRES_PER_PIXEL, 0], [0, 0, 1]]) @ np.array([[1, 0, -width / 2.0], [0, -1, height / 2.0], [0, 0, 1.0]]) top_left = self.__transform.transform_point((0, 0)) bottom_right = self.__transform.transform_point((width, height)) # southwest and northeast corners self.bounds = (top_left[0], bottom_right[1], bottom_right[0], top_left[1]) self.__layer = SVGLayer(id, self, base_layer) self.add_layer(self.__layer) self.__raster_source = None self.__boundary_geometry = None
def __init__(self, flatmap, id, source_href, boundary_id=None, exported=False): super().__init__(flatmap, id, source_href, 'image') self.__sparc_dataset = sparc_dataset(source_href) self.__boundary_id = boundary_id self.__boundary_geometry = None self.__layer = MapLayer(id, self, exported=exported) self.add_layer(self.__layer) self.__mbf = etree.parse(FilePath(source_href).get_fp()).getroot() self.__ns = self.__mbf.nsmap[None] sparcdata = self.__mbf.find(self.ns_tag('sparcdata')) self.__species = sparcdata.find(self.ns_tag('subject')).get('species') self.__organ = sparcdata.find(self.ns_tag('atlas')).get('rootid') image_element = self.__mbf.find('{}/{}'.format(self.ns_tag('images'), self.ns_tag('image'))) scale_element = image_element.find(self.ns_tag('scale')) scaling = (float(scale_element.get('x', 1.0)), float(scale_element.get('y', 1.0))) # um/px coord_element = image_element.find(self.ns_tag('coord')) offset = (float(coord_element.get('x', 0.0)), float(coord_element.get('y', 0.0))) filename = image_element.find(self.ns_tag('filename')).text image_file = FilePath(urljoin(source_href, filename.split('\\')[-1])) image_array = np.frombuffer(image_file.get_data(), dtype=np.uint8) self.__image = cv2.imdecode(image_array, cv2.IMREAD_UNCHANGED) if self.__image.shape[2] == 3: self.__image = cv2.cvtColor(self.__image, cv2.COLOR_RGB2RGBA) image_size = (self.__image.shape[1], self.__image.shape[0]) self.__image_to_world = ( Transform([[scaling[0] * WORLD_METRES_PER_UM, 0, 0], [0, -scaling[1] * WORLD_METRES_PER_UM, 0], [0, 0, 1]]) @ np.array([[1, 0, -image_size[0] / 2.0], [0, 1, -image_size[1] / 2.0], [0, 0, 1.0]])) self.__world_to_image = self.__image_to_world.inverse() (width, height) = (scaling[0] * image_size[0], scaling[1] * image_size[1]) # um self.__um_to_world = (Transform([[ WORLD_METRES_PER_UM, 0, 0 ], [0, WORLD_METRES_PER_UM, 0], [0, 0, 1]]) @ np.array( [[1, 0, -width / 2.0], [0, 1, height / 2.0], [0, 0, 1.0]])) top_left = self.__um_to_world.transform_point((0, 0)) bottom_right = self.__um_to_world.transform_point((width, -height)) # southwest and northeast corners self.bounds = (top_left[0], bottom_right[1], bottom_right[0], top_left[1])
class SVGSource(MapSource): def __init__(self, flatmap, id, href, kind): # maker v's flatmap (esp. id) super().__init__(flatmap, id, href, kind) self.__source_file = FilePath(href) self.__exported = (kind=='base') svg = etree.parse(self.__source_file.get_fp()).getroot() if 'viewBox' in svg.attrib: (width, height) = tuple(float(x) for x in svg.attrib['viewBox'].split()[2:]) else: width = length_as_pixels(svg.attrib['width']) height = length_as_pixels(svg.attrib['height']) # Transform from SVG pixels to world coordinates self.__transform = Transform([[WORLD_METRES_PER_PIXEL, 0, 0], [ 0, WORLD_METRES_PER_PIXEL, 0], [ 0, 0, 1]])@np.array([[1, 0, -width/2.0], [0, -1, height/2.0], [0, 0, 1.0]]) top_left = self.__transform.transform_point((0, 0)) bottom_right = self.__transform.transform_point((width, height)) # southwest and northeast corners self.bounds = (top_left[0], bottom_right[1], bottom_right[0], top_left[1]) self.__layer = SVGLayer(id, self, svg, exported=self.__exported) self.add_layer(self.__layer) self.__boundary_geometry = None @property def boundary_geometry(self): return self.__boundary_geometry @property def transform(self): return self.__transform def process(self): #================= self.__layer.process() if self.__layer.boundary_feature is not None: self.__boundary_geometry = self.__layer.boundary_feature.geometry if self.__exported: # Save a cleaned copy of the SVG in the map's output directory cleaner = SVGCleaner(self.__source_file, self.flatmap.map_properties) cleaner.clean() with open(os.path.join(settings.get('output'), self.flatmap.id, '{}.svg'.format(self.flatmap.id)), 'wb') as fp: cleaner.save(fp) if settings.get('backgroundTiles', False): cleaner = SVGCleaner(self.__source_file, self.flatmap.map_properties, all_layers=False) cleaner.clean() cleaned_svg = io.BytesIO() cleaner.save(cleaned_svg) cleaned_svg.seek(0) else: cleaned_svg = None self.set_raster_source(RasterSource('svg', cleaned_svg, source=self.__source_file))
def __gradient_matrix(gradient, path): #===================================== if gradient.attrib.get('gradientUnits') == 'userSpaceOnUse': path_transform = Transform.Identity() else: # objectBoundingBox' bounds = path.getBounds() path_transform = Transform([[bounds.width(), 0, bounds.left()], [ 0, bounds.height(), bounds.top()], [ 0, 0, 1]]) svg_transform = SVGTransform(gradient.attrib.get('gradientTransform')) return skia.Matrix(list((path_transform@svg_transform).flatten()))
def __init__(self, raster_layer, tile_set): self.__svg = etree.parse(raster_layer.source_data).getroot() if 'viewBox' in self.__svg.attrib: self.__size = tuple( float(x) for x in self.__svg.attrib['viewBox'].split()[2:]) else: self.__size = (length_as_pixels(self.__svg.attrib['width']), length_as_pixels(self.__svg.attrib['height'])) self.__scaling = (tile_set.pixel_rect.width / self.__size[0], tile_set.pixel_rect.height / self.__size[1]) self.__definitions = DefinitionStore() defs = self.__svg.find(SVG_NS('defs')) if defs is not None: self.__definitions.add_definitions(defs) self.__style_matcher = StyleMatcher(self.__svg.find(SVG_NS('style'))) self.__first_scan = True # Transform from SVG pixels to tile pixels transform = Transform([[self.__scaling[0], 0.0, 0.0], [0.0, self.__scaling[1], 0.0], [0.0, 0.0, 1.0]]) self.__path_list = [] self.__draw_svg(transform, self.__path_list) # Transform from SVG pixels to world coordinates self.__image_to_world = (Transform([ [WORLD_METRES_PER_PIXEL / self.__scaling[0], 0, 0], [0, WORLD_METRES_PER_PIXEL / self.__scaling[1], 0], [0, 0, 1] ]) @ np.array([[1, 0, -self.__scaling[0] * self.__size[0] / 2.0], [0, -1, self.__scaling[1] * self.__size[1] / 2.0], [0, 0, 1.0]])) self.__tile_size = tile_set.tile_size self.__tile_origin = tile_set.start_coords self.__pixel_offset = tuple(tile_set.pixel_rect)[0:2] path_bounding_boxes = [(path, paint, shapely.geometry.box(*tuple(path.getBounds()))) for (path, paint) in self.__path_list] self.__tile_paths = {} for tile in tile_set: tile_set.tile_coords_to_pixels.transform_point((tile.x, tile.y)) x0 = (tile.x - self.__tile_origin[0] ) * self.__tile_size[0] - self.__pixel_offset[0] y0 = (tile.y - self.__tile_origin[1] ) * self.__tile_size[1] - self.__pixel_offset[1] tile_bbox = shapely.prepared.prep( shapely.geometry.box(x0, y0, x0 + self.__tile_size[0], y0 + self.__tile_size[0])) self.__tile_paths[mercantile.quadkey(tile)] = list( filter(lambda ppb: tile_bbox.intersects(ppb[2]), path_bounding_boxes))
class PowerpointSource(MapSource): def __init__(self, flatmap, id, source_path, get_background=False): super().__init__(flatmap, id) self.__pptx = Presentation(FilePath(source_path).get_BytesIO()) self.__slides = self.__pptx.slides (width, height) = (self.__pptx.slide_width, self.__pptx.slide_height) self.__transform = Transform([[WORLD_METRES_PER_EMU, 0, 0], [ 0, -WORLD_METRES_PER_EMU, 0], [ 0, 0, 1]])@np.array([[1, 0, -width/2.0], [0, 1, -height/2.0], [0, 0, 1.0]]) top_left = self.__transform.transform_point((0, 0)) bottom_right = self.__transform.transform_point((width, height)) # southwest and northeast corners self.bounds = (top_left[0], bottom_right[1], bottom_right[0], top_left[1]) if get_background: pdf_source = FilePath('{}_cleaned.pdf'.format(os.path.splitext(source_path)[0])) self.__raster_source = RasterSource('pdf', pdf_source.get_data()) else: self.__raster_source = None @property def raster_source(self): return self.__raster_source @property def transform(self): return self.__transform def process(self): #================= for n in range(len(self.__slides)): slide = self.__slides[n] slide_number = n + 1 slide_layer = PowerpointSlide(self, slide, slide_number) log('Slide {}, {}'.format(slide_number, slide_layer.id)) if settings.get('saveDrawML'): xml = open(os.path.join(self.flatmap.map_directory, '{}.xml'.format(slide_layer.id)), 'w') xml.write(slide.element.xml) xml.close() slide_layer.process() for error in self.errors: log.warn(error) else: self.add_layer(slide_layer)
def __init__(self, flatmap, id, source_href): super().__init__(flatmap, id, source_href, 'slides') self.__pptx = Presentation(FilePath(source_href).get_BytesIO()) self.__slides = self.__pptx.slides (width, height) = (self.__pptx.slide_width, self.__pptx.slide_height) self.__transform = Transform([[WORLD_METRES_PER_EMU, 0, 0], [ 0, -WORLD_METRES_PER_EMU, 0], [ 0, 0, 1]])@np.array([[1, 0, -width/2.0], [0, 1, -height/2.0], [0, 0, 1.0]]) top_left = self.__transform.transform_point((0, 0)) bottom_right = self.__transform.transform_point((width, height)) # southwest and northeast corners self.bounds = (top_left[0], bottom_right[1], bottom_right[0], top_left[1]) pdf_source = FilePath('{}_cleaned.pdf'.format(os.path.splitext(source_href)[0])) self.set_raster_source(RasterSource('pdf', pdf_source.get_data()))
def __init__(self, raster_layer, tile_set): self.__bbox = shapely.geometry.box(*extent_to_bounds(raster_layer.extent)) self.__svg = etree.parse(raster_layer.source_data).getroot() self.__source = raster_layer.source_params.get('source') if 'viewBox' in self.__svg.attrib: self.__size = tuple(float(x) for x in self.__svg.attrib['viewBox'].split()[2:]) else: self.__size = (length_as_pixels(self.__svg.attrib['width']), length_as_pixels(self.__svg.attrib['height'])) self.__scaling = (tile_set.pixel_rect.width/self.__size[0], tile_set.pixel_rect.height/self.__size[1]) self.__definitions = DefinitionStore() self.__style_matcher = StyleMatcher(self.__svg.find(SVG_NS('style'))) self.__clip_paths = ObjectStore() # Transform from SVG pixels to tile pixels svg_to_tile_transform = Transform([[self.__scaling[0], 0.0, 0.0], [ 0.0, self.__scaling[1], 0.0], [ 0.0, 0.0, 1.0]]) self.__svg_drawing = self.__draw_svg(svg_to_tile_transform) # Transform from SVG pixels to world coordinates self.__image_to_world = (Transform([ [WORLD_METRES_PER_PIXEL/self.__scaling[0], 0, 0], [ 0, WORLD_METRES_PER_PIXEL/self.__scaling[1], 0], [ 0, 0, 1]]) @np.array([[1, 0, -self.__scaling[0]*self.__size[0]/2.0], [0, -1, self.__scaling[1]*self.__size[1]/2.0], [0, 0, 1.0]])) self.__tile_size = tile_set.tile_size self.__tile_origin = tile_set.start_coords self.__pixel_offset = tuple(tile_set.pixel_rect)[0:2] self.__tile_bboxes = {} for tile in tile_set: tile_set.tile_coords_to_pixels.transform_point((tile.x, tile.y)) x0 = (tile.x - self.__tile_origin[0])*self.__tile_size[0] - self.__pixel_offset[0] y0 = (tile.y - self.__tile_origin[1])*self.__tile_size[1] - self.__pixel_offset[1] tile_bbox = shapely.geometry.box(x0, y0, x0 + self.__tile_size[0], y0 + self.__tile_size[0]) self.__tile_bboxes[mercantile.quadkey(tile)] = tile_bbox