def _where_to_draw_from_and_to( self, b): def fix_bbox( a): x, y = a.x, a.y data = self._vertex_to_bbox.get( a, None) if data: (ox, oy), bbox = data dx = x - ox dy = y - oy bbox = [bbox[0]+dx,bbox[1]+dy,bbox[2]+dx,bbox[3]+dy] return bbox return None # at first check if the bboxes are not overlapping atom1, atom2 = b.vertices x1, y1 = atom1.x, atom1.y x2, y2 = atom2.x, atom2.y bbox1 = fix_bbox( atom1) bbox2 = fix_bbox( atom2) if bbox1 and bbox2 and geometry.do_rectangles_intersect( bbox1, bbox2): return None # then we continue with computation if bbox1: x1, y1 = geometry.intersection_of_line_and_rect( (x1,y1,x2,y2), bbox1, round_edges=0) if bbox2: x2, y2 = geometry.intersection_of_line_and_rect( (x1,y1,x2,y2), bbox2, round_edges=0) if geometry.point_distance( x1, y1, x2, y2) <= 1.0: return None else: return (x1, y1, x2, y2)
def _where_to_draw_from_and_to(self, b): def fix_bbox(a): x, y = a.x, a.y data = self._vertex_to_bbox.get(a, None) if data: (ox, oy), bbox = data dx = x - ox dy = y - oy bbox = [bbox[0] + dx, bbox[1] + dy, bbox[2] + dx, bbox[3] + dy] return bbox return None # at first check if the bboxes are not overlapping atom1, atom2 = b.vertices x1, y1 = atom1.x, atom1.y x2, y2 = atom2.x, atom2.y bbox1 = fix_bbox(atom1) bbox2 = fix_bbox(atom2) if bbox1 and bbox2 and geometry.do_rectangles_intersect(bbox1, bbox2): return None # then we continue with computation if bbox1: x1, y1 = geometry.intersection_of_line_and_rect((x1, y1, x2, y2), bbox1, round_edges=0) if bbox2: x2, y2 = geometry.intersection_of_line_and_rect((x1, y1, x2, y2), bbox2, round_edges=0) if geometry.point_distance(x1, y1, x2, y2) <= 1.0: return None else: return (x1, y1, x2, y2)
def _draw_vertex( self, v): pos = sum( [(a.x < v.x) and -1 or 1 for a in v.neighbors if abs(a.x-v.x)>0.2]) if 'show_symbol' in v.properties_: show_symbol = v.properties_['show_symbol'] else: show_symbol = (v.symbol != "C" or v.degree == 0 or self.show_carbon_symbol) if show_symbol: x = v.x y = v.y text = v.symbol hs = "" if self.show_hydrogens_on_hetero or v.properties_.get( 'show_hydrogens', False): if v.free_valency == 1: hs = "H" elif v.free_valency > 1: hs = "H<sub>%d</sub>" % v.free_valency if not hs: pos = -1 if pos <= 0: text += hs else: text = hs + text # charge charge = "" if v.charge == 1: charge = "<sup>+</sup>" elif v.charge == -1: charge = "<sup>−</sup>" elif v.charge > 1: charge = "<sup>%d+</sup>" % v.charge elif v.charge < -1: charge = "<sup>%d−</sup>" % abs( v.charge) if charge: if self._is_there_place( v, v.x+3, v.y-2) or v.charge < 0: # we place negative charge regardless of available place # otherwise minus might be mistaken for a bond text += charge charge = "" # coloring if self.color_atoms: color = self.atom_colors.get( v.symbol, (0,0,0)) else: color = (0,0,0) center_letter = pos <= 0 and 'first' or 'last' bbox = self._draw_text( (x,y), text, center_letter=center_letter, color=color) self._vertex_to_bbox[v] = ((x,y), geometry.expand_rectangle( bbox, self.space_around_atom)) # sometimes charge is done here, if it wasn't done before if charge: assert v.charge > 0 # if charge was not dealt with we change its appearance from 2+ to ++ charge = v.charge * "+" if self._is_there_place( v, v.x, v.y-10): angle = 1.5*math.pi elif self._is_there_place( v, v.x, v.y+10): angle = 0.5*math.pi else: angle = self._find_place_around_atom( v) self.context.set_font_size( self.subscript_size_ratio * self.font_size) xbearing, ybearing, width, height, x_advance, y_advance = self.context.text_extents( charge) x0 = v.x + 40*math.cos( angle) y0 = v.y + 40*math.sin( angle) line = (v.x,v.y,x0,y0) charge_bbox = [x0-0.5*width,y0-0.5*height,x0+0.5*width,y0+0.5*height] x1, y1 = geometry.intersection_of_line_and_rect( line, bbox, round_edges=0) x2, y2 = geometry.intersection_of_line_and_rect( line, charge_bbox, round_edges=0) x2, y2 = geometry.elongate_line( x1,y1,x2,y2, -self.space_around_atom) x = x0 + x1 - x2 y = y0 + y1 - y2 # draw self.context.set_source_rgb( *color) self.context.move_to( round( x-xbearing-0.5*width), round( y+0.5*height)) self.context.show_text( charge)
def _draw_vertex(self, v): pos = sum([(a.x < v.x) and -1 or 1 for a in v.neighbors if abs(a.x - v.x) > 0.2]) if 'show_symbol' in v.properties_: show_symbol = v.properties_['show_symbol'] else: show_symbol = (v.symbol != "C" or v.degree == 0 or self.show_carbon_symbol) if show_symbol: x = v.x y = v.y text = v.symbol hs = "" if self.show_hydrogens_on_hetero or v.properties_.get( 'show_hydrogens', False): if v.free_valency == 1: hs = "H" elif v.free_valency > 1: hs = "H<sub>%d</sub>" % v.free_valency if not hs: pos = -1 if pos <= 0: text += hs else: text = hs + text # charge charge = "" if v.charge == 1: charge = "<sup>+</sup>" elif v.charge == -1: charge = "<sup>−</sup>" elif v.charge > 1: charge = "<sup>%d+</sup>" % v.charge elif v.charge < -1: charge = "<sup>%d−</sup>" % abs(v.charge) if charge: if self._is_there_place(v, v.x + 3, v.y - 2) or v.charge < 0: # we place negative charge regardless of available place # otherwise minus might be mistaken for a bond text += charge charge = "" # coloring if self.color_atoms: color = self.atom_colors.get(v.symbol, (0, 0, 0)) else: color = (0, 0, 0) center_letter = pos <= 0 and 'first' or 'last' bbox = self._draw_text((x, y), text, center_letter=center_letter, color=color) self._vertex_to_bbox[v] = ((x, y), geometry.expand_rectangle( bbox, self.space_around_atom)) # sometimes charge is done here, if it wasn't done before if charge: assert v.charge > 0 # if charge was not dealt with we change its appearance from 2+ to ++ charge = v.charge * "+" if self._is_there_place(v, v.x, v.y - 10): angle = 1.5 * math.pi elif self._is_there_place(v, v.x, v.y + 10): angle = 0.5 * math.pi else: angle = self._find_place_around_atom(v) self.context.set_font_size(self.subscript_size_ratio * self.font_size) xbearing, ybearing, width, height, x_advance, y_advance = self.context.text_extents( charge) x0 = v.x + 40 * math.cos(angle) y0 = v.y + 40 * math.sin(angle) line = (v.x, v.y, x0, y0) charge_bbox = [ x0 - 0.5 * width, y0 - 0.5 * height, x0 + 0.5 * width, y0 + 0.5 * height ] x1, y1 = geometry.intersection_of_line_and_rect(line, bbox, round_edges=0) x2, y2 = geometry.intersection_of_line_and_rect(line, charge_bbox, round_edges=0) x2, y2 = geometry.elongate_line(x1, y1, x2, y2, -self.space_around_atom) x = x0 + x1 - x2 y = y0 + y1 - y2 # draw self.context.set_source_rgb(*color) self.context.move_to(round(x - xbearing - 0.5 * width), round(y + 0.5 * height)) self.context.show_text(charge)