def draw_plain_or_colored_wedge(_start, _end): x1, y1 = _start x2, y2 = _end x, y, x0, y0 = geometry.find_parallel(x1, y1, x2, y2, self.wedge_width / 2.0) xa, ya, xb, yb = geometry.find_parallel(x1, y1, x2, y2, self.line_width / 2.0) # no coloring now if not has_shown_vertex or not self.color_bonds: self._create_cairo_path([(xa, ya), (x0, y0), (2 * x2 - x0, 2 * y2 - y0), (2 * x1 - xa, 2 * y1 - ya)], closed=True) self.context.set_source_rgb(0, 0, 0) self.context.fill() else: # ratio 0.4 looks better than 0.5 because the area difference # is percieved more than length difference ratio = 0.4 xm1 = ratio * xa + (1 - ratio) * x0 ym1 = ratio * ya + (1 - ratio) * y0 xm2 = (1 - ratio) * (2 * x2 - x0) + ratio * (2 * x1 - xa) ym2 = (1 - ratio) * (2 * y2 - y0) + ratio * (2 * y1 - ya) self.context.set_source_rgb(*color1) self._create_cairo_path([(xa, ya), (xm1, ym1), (xm2, ym2), (2 * x1 - xa, 2 * y1 - ya)], closed=True) self.context.fill() self.context.set_source_rgb(*color2) self._create_cairo_path([(xm1, ym1), (x0, y0), (2 * x2 - x0, 2 * y2 - y0), (xm2, ym2)], closed=True) self.context.fill()
def _draw_edge(self, e): v1, v2 = e.vertices start = self.transformer.transform_xy(v1.x, v1.y) end = self.transformer.transform_xy(v2.x, v2.y) parent = self._create_parent(e, self.top) if e.order == 1: self._draw_line(parent, start, end, line_width=self.line_width) if e.order == 2: side = 0 # find how to center the bonds # rings have higher priority in setting the positioning for ring in self.molecule.get_smallest_independent_cycles(): if v1 in ring and v2 in ring: side += reduce(operator.add, [ geometry.on_which_side_is_point( start + end, (self.transformer.transform_xy(a.x, a.y))) for a in ring if a != v1 and a != v2 ]) # if rings did not decide, use the other neigbors if not side: for v in v1.neighbors + v2.neighbors: if v != v1 and v != v2: side += geometry.on_which_side_is_point( start + end, (self.transformer.transform_xy(v.x, v.y))) if side: self._draw_line(parent, start, end, line_width=self.line_width) x1, y1, x2, y2 = geometry.find_parallel( start[0], start[1], end[0], end[1], self.bond_width * misc.signum(side)) self._draw_line(parent, (x1, y1), (x2, y2), line_width=self.line_width) else: for i in (1, -1): x1, y1, x2, y2 = geometry.find_parallel( start[0], start[1], end[0], end[1], i * self.bond_width * 0.5) self._draw_line(parent, (x1, y1), (x2, y2), line_width=self.line_width) elif e.order == 3: self._draw_line(parent, start, end, line_width=self.line_width) for i in (1, -1): x1, y1, x2, y2 = geometry.find_parallel( start[0], start[1], end[0], end[1], i * self.bond_width * 0.7) self._draw_line(parent, (x1, y1), (x2, y2), line_width=self.line_width)
def draw_plain_or_colored_hatch(_start, _end): x1, y1 = _start x2, y2 = _end # no coloring now x, y, x0, y0 = geometry.find_parallel(x1, y1, x2, y2, self.wedge_width / 2.0) xa, ya, xb, yb = geometry.find_parallel(x1, y1, x2, y2, self.line_width / 2.0) d = math.sqrt((x1 - x2)**2 + (y1 - y2)**2) # length of the bond if d == 0: return # to prevent division by zero dx1 = (x0 - xa) / d dy1 = (y0 - ya) / d dx2 = (2 * x2 - x0 - 2 * x1 + xa) / d dy2 = (2 * y2 - y0 - 2 * y1 + ya) / d # we have to decide if the first line should be at the position of the first atom draw_start = 1 # is index not boolean if not v1 in self._vertex_to_bbox and v1.occupied_valency > 1: draw_start = 1 draw_end = 1 # is added to index not boolean if not v2 in self._vertex_to_bbox and v2.occupied_valency > 1: draw_end = 0 # adjust the step length step_size = 2 * (self.line_width) ns = round(d / step_size) or 1 step_size = d / ns # now we finally draw self.context.set_line_cap(cairo.LINE_CAP_BUTT) self.context.set_source_rgb(*color1) middle = 0.5 * (draw_start + int(round(d / step_size)) + draw_end - 2) for i in range(draw_start, int(round(d / step_size)) + draw_end): coords = [ xa + dx1 * i * step_size, ya + dy1 * i * step_size, 2 * x1 - xa + dx2 * i * step_size, 2 * y1 - ya + dy2 * i * step_size ] if coords[0] == coords[2] and coords[1] == coords[3]: if (dx1 + dx2) > (dy1 + dy2): coords[0] += 1 else: coords[1] += 1 self._create_cairo_path([coords[:2], coords[2:]]) if i >= middle: self.context.stroke() self.context.set_source_rgb(*color2) self.context.stroke()
def draw_plain_or_colored_hatch( _start, _end): x1, y1 = _start x2, y2 = _end # no coloring now x, y, x0, y0 = geometry.find_parallel( x1, y1, x2, y2, self.wedge_width/2.0) xa, ya, xb, yb = geometry.find_parallel( x1, y1, x2, y2, self.line_width/2.0) d = math.sqrt( (x1-x2)**2 + (y1-y2)**2) # length of the bond if d == 0: return # to prevent division by zero dx1 = (x0 - xa)/d dy1 = (y0 - ya)/d dx2 = (2*x2 -x0 -2*x1 +xa)/d dy2 = (2*y2 -y0 -2*y1 +ya)/d # we have to decide if the first line should be at the position of the first atom draw_start = 1 # is index not boolean if not v1 in self._vertex_to_bbox and v1.occupied_valency > 1: draw_start = 1 draw_end = 1 # is added to index not boolean if not v2 in self._vertex_to_bbox and v2.occupied_valency > 1: draw_end = 0 # adjust the step length step_size = 2*(self.line_width) ns = round( d / step_size) or 1 step_size = d / ns # now we finally draw self.context.set_line_cap( cairo.LINE_CAP_BUTT) self.context.set_source_rgb( *color1) middle = 0.5 * (draw_start + int( round( d/ step_size)) + draw_end - 2) for i in range( draw_start, int( round( d/ step_size)) +draw_end): coords = [xa+dx1*i*step_size, ya+dy1*i*step_size, 2*x1-xa+dx2*i*step_size, 2*y1-ya+dy2*i*step_size] if coords[0] == coords[2] and coords[1] == coords[3]: if (dx1+dx2) > (dy1+dy2): coords[0] += 1 else: coords[1] += 1 self._create_cairo_path( [coords[:2],coords[2:]]) if i >= middle: self.context.stroke() self.context.set_source_rgb( *color2) self.context.stroke()
def draw_plain_or_colored_wedge( _start, _end): x1, y1 = _start x2, y2 = _end x, y, x0, y0 = geometry.find_parallel( x1, y1, x2, y2, self.wedge_width/2.0) xa, ya, xb, yb = geometry.find_parallel( x1, y1, x2, y2, self.line_width/2.0) # no coloring now if not has_shown_vertex or not self.color_bonds: self._create_cairo_path( [(xa, ya), (x0, y0), (2*x2-x0, 2*y2-y0), (2*x1-xa, 2*y1-ya)], closed=True) self.context.set_source_rgb( 0,0,0) self.context.fill() else: # ratio 0.4 looks better than 0.5 because the area difference # is percieved more than length difference ratio = 0.4 xm1 = ratio*xa + (1-ratio)*x0 ym1 = ratio*ya + (1-ratio)*y0 xm2 = (1-ratio)*(2*x2-x0) + ratio*(2*x1-xa) ym2 = (1-ratio)*(2*y2-y0) + ratio*(2*y1-ya) self.context.set_source_rgb( *color1) self._create_cairo_path( [(xa,ya), (xm1,ym1), (xm2,ym2), (2*x1-xa, 2*y1-ya)], closed=True) self.context.fill() self.context.set_source_rgb( *color2) self._create_cairo_path( [(xm1,ym1), (x0, y0), (2*x2-x0, 2*y2-y0), (xm2,ym2)], closed=True) self.context.fill()
def _draw_edge( self, e): v1, v2 = e.vertices start = self.transformer.transform_xy( v1.x, v1.y) end = self.transformer.transform_xy( v2.x, v2.y) parent = self._create_parent( e, self.top) if e.order == 1: self._draw_line( parent, start, end, line_width=self.line_width) if e.order == 2: side = 0 # find how to center the bonds # rings have higher priority in setting the positioning for ring in self.molecule.get_smallest_independent_cycles(): if v1 in ring and v2 in ring: side += reduce( operator.add, [geometry.on_which_side_is_point( start+end, (self.transformer.transform_xy( a.x,a.y))) for a in ring if a!=v1 and a!=v2]) # if rings did not decide, use the other neigbors if not side: for v in v1.neighbors + v2.neighbors: if v != v1 and v!= v2: side += geometry.on_which_side_is_point( start+end, (self.transformer.transform_xy( v.x, v.y))) if side: self._draw_line( parent, start, end, line_width=self.line_width) x1, y1, x2, y2 = geometry.find_parallel( start[0], start[1], end[0], end[1], self.bond_width*misc.signum( side)) self._draw_line( parent, (x1, y1), (x2, y2), line_width=self.line_width) else: for i in (1,-1): x1, y1, x2, y2 = geometry.find_parallel( start[0], start[1], end[0], end[1], i*self.bond_width*0.5) self._draw_line( parent, (x1, y1), (x2, y2), line_width=self.line_width) elif e.order == 3: self._draw_line( parent, start, end, line_width=self.line_width) for i in (1,-1): x1, y1, x2, y2 = geometry.find_parallel( start[0], start[1], end[0], end[1], i*self.bond_width*0.7) self._draw_line( parent, (x1, y1), (x2, y2), line_width=self.line_width)
def _draw_edge( self, e): def draw_plain_or_colored_line( _start, _end, second=False): """second means if this is not the main line, drawing might be different""" if not has_shown_vertex or not self.color_bonds: if not second: self._draw_line( _start, _end, line_width=self.line_width, capstyle=cairo.LINE_CAP_ROUND) else: self._draw_line( _start, _end, line_width=self.line_width, capstyle=cairo.LINE_CAP_BUTT) else: self._draw_colored_line( _start, _end, line_width=self.line_width, start_color=color1, end_color=color2) def draw_plain_or_colored_wedge( _start, _end): x1, y1 = _start x2, y2 = _end x, y, x0, y0 = geometry.find_parallel( x1, y1, x2, y2, self.wedge_width/2.0) xa, ya, xb, yb = geometry.find_parallel( x1, y1, x2, y2, self.line_width/2.0) # no coloring now if not has_shown_vertex or not self.color_bonds: self._create_cairo_path( [(xa, ya), (x0, y0), (2*x2-x0, 2*y2-y0), (2*x1-xa, 2*y1-ya)], closed=True) self.context.set_source_rgb( 0,0,0) self.context.fill() else: # ratio 0.4 looks better than 0.5 because the area difference # is percieved more than length difference ratio = 0.4 xm1 = ratio*xa + (1-ratio)*x0 ym1 = ratio*ya + (1-ratio)*y0 xm2 = (1-ratio)*(2*x2-x0) + ratio*(2*x1-xa) ym2 = (1-ratio)*(2*y2-y0) + ratio*(2*y1-ya) self.context.set_source_rgb( *color1) self._create_cairo_path( [(xa,ya), (xm1,ym1), (xm2,ym2), (2*x1-xa, 2*y1-ya)], closed=True) self.context.fill() self.context.set_source_rgb( *color2) self._create_cairo_path( [(xm1,ym1), (x0, y0), (2*x2-x0, 2*y2-y0), (xm2,ym2)], closed=True) self.context.fill() def draw_plain_or_colored_hatch( _start, _end): x1, y1 = _start x2, y2 = _end # no coloring now x, y, x0, y0 = geometry.find_parallel( x1, y1, x2, y2, self.wedge_width/2.0) xa, ya, xb, yb = geometry.find_parallel( x1, y1, x2, y2, self.line_width/2.0) d = math.sqrt( (x1-x2)**2 + (y1-y2)**2) # length of the bond if d == 0: return # to prevent division by zero dx1 = (x0 - xa)/d dy1 = (y0 - ya)/d dx2 = (2*x2 -x0 -2*x1 +xa)/d dy2 = (2*y2 -y0 -2*y1 +ya)/d # we have to decide if the first line should be at the position of the first atom draw_start = 1 # is index not boolean if not v1 in self._vertex_to_bbox and v1.occupied_valency > 1: draw_start = 1 draw_end = 1 # is added to index not boolean if not v2 in self._vertex_to_bbox and v2.occupied_valency > 1: draw_end = 0 # adjust the step length step_size = 2*(self.line_width) ns = round( d / step_size) or 1 step_size = d / ns # now we finally draw self.context.set_line_cap( cairo.LINE_CAP_BUTT) self.context.set_source_rgb( *color1) middle = 0.5 * (draw_start + int( round( d/ step_size)) + draw_end - 2) for i in range( draw_start, int( round( d/ step_size)) +draw_end): coords = [xa+dx1*i*step_size, ya+dy1*i*step_size, 2*x1-xa+dx2*i*step_size, 2*y1-ya+dy2*i*step_size] if coords[0] == coords[2] and coords[1] == coords[3]: if (dx1+dx2) > (dy1+dy2): coords[0] += 1 else: coords[1] += 1 self._create_cairo_path( [coords[:2],coords[2:]]) if i >= middle: self.context.stroke() self.context.set_source_rgb( *color2) self.context.stroke() # code itself # at first detect the need to make 3D adjustments self._transform = transform3d.transform3d() self._invtransform = transform3d.transform3d() transform = None if e.order > 1: atom1,atom2 = e.vertices for n in atom1.neighbors + atom2.neighbors: # e.atom1 and e.atom2 are in this list as well if n.z != 0: # engage 3d transform prior to detection of where to draw transform = self._get_3dtransform_for_drawing( e) #transform = None break if transform: for n in atom1.neighbors + atom2.neighbors: n.coords = transform.transform_xyz( *n.coords) self._transform = transform self._invtransform = transform.get_inverse() # // end of 3D adjustments # now the code itself coords = self._where_to_draw_from_and_to( e) if coords: start = coords[:2] end = coords[2:] v1, v2 = e.vertices if self.color_bonds: color1 = self.atom_colors.get( v1.symbol, (0,0,0)) color2 = self.atom_colors.get( v2.symbol, (0,0,0)) else: color1 = color2 = (0,0,0) has_shown_vertex = bool( [1 for _v in e.vertices if _v in self._vertex_to_bbox]) if e.order == 1: if e.type == 'w': draw_plain_or_colored_wedge( start, end) elif e.type == 'h': draw_plain_or_colored_hatch( start, end) else: draw_plain_or_colored_line( start, end) if e.order == 2: side = 0 # find how to center the bonds # rings have higher priority in setting the positioning in_ring = False for ring in self.molecule.get_smallest_independent_cycles_dangerous_and_cached(): double_bonds = len( [b for b in self.molecule.vertex_subgraph_to_edge_subgraph(ring) if b.order == 2]) if v1 in ring and v2 in ring: in_ring = True side += double_bonds * reduce( operator.add, [geometry.on_which_side_is_point( start+end, (a.x,a.y)) for a in ring if a!=v1 and a!=v2]) # if rings did not decide, use the other neigbors if not side: for v in v1.neighbors + v2.neighbors: if v != v1 and v!= v2: side += geometry.on_which_side_is_point( start+end, (v.x, v.y)) # if neighbors did not decide either if not side and (in_ring or not has_shown_vertex): if in_ring: # we don't want centered bonds inside rings side = 1 # select arbitrary value else: # bond between two unshown atoms - we want to center them only in some cases if len( v1.neighbors) == 1 and len( v2.neighbors) == 1: # both atoms have only one neighbor side = 0 elif len( v1.neighbors) < 3 and len( v2.neighbors) < 3: # try to figure out which side is more towards the center of the molecule side = reduce( operator.add, [geometry.on_which_side_is_point( start+end, (a.x,a.y)) for a in self.molecule.vertices if a!=v1 and a!=v2], 0) if not side: side = 1 # we choose arbitrary value, we don't want centering if side: draw_plain_or_colored_line( start, end) x1, y1, x2, y2 = geometry.find_parallel( start[0], start[1], end[0], end[1], self.bond_width*misc.signum( side)) # shorten the second line length = geometry.point_distance( x1,y1,x2,y2) if v2 not in self._vertex_to_bbox: x2, y2 = geometry.elongate_line( x1, y1, x2, y2, -self.bond_second_line_shortening*length) if v1 not in self._vertex_to_bbox: x1, y1 = geometry.elongate_line( x2, y2, x1, y1, -self.bond_second_line_shortening*length) draw_plain_or_colored_line( (x1, y1), (x2, y2), second=True) else: for i in (1,-1): x1, y1, x2, y2 = geometry.find_parallel( start[0], start[1], end[0], end[1], i*self.bond_width*0.5) draw_plain_or_colored_line( (x1, y1), (x2, y2)) elif e.order == 3: self._draw_line( start, end, line_width=self.line_width) for i in (1,-1): x1, y1, x2, y2 = geometry.find_parallel( start[0], start[1], end[0], end[1], i*self.bond_width*0.7) draw_plain_or_colored_line( (x1, y1), (x2, y2), second=True) if transform: # if transform was used, we need to transform back for n in atom1.neighbors + atom2.neighbors: n.coords = self._invtransform.transform_xyz( *n.coords)
def _draw_edge(self, e): def draw_plain_or_colored_line(_start, _end, second=False): """second means if this is not the main line, drawing might be different""" if not has_shown_vertex or not self.color_bonds: if not second: self._draw_line(_start, _end, line_width=self.line_width, capstyle=cairo.LINE_CAP_ROUND) else: self._draw_line(_start, _end, line_width=self.line_width, capstyle=cairo.LINE_CAP_BUTT) else: self._draw_colored_line(_start, _end, line_width=self.line_width, start_color=color1, end_color=color2) def draw_plain_or_colored_wedge(_start, _end): x1, y1 = _start x2, y2 = _end x, y, x0, y0 = geometry.find_parallel(x1, y1, x2, y2, self.wedge_width / 2.0) xa, ya, xb, yb = geometry.find_parallel(x1, y1, x2, y2, self.line_width / 2.0) # no coloring now if not has_shown_vertex or not self.color_bonds: self._create_cairo_path([(xa, ya), (x0, y0), (2 * x2 - x0, 2 * y2 - y0), (2 * x1 - xa, 2 * y1 - ya)], closed=True) self.context.set_source_rgb(0, 0, 0) self.context.fill() else: # ratio 0.4 looks better than 0.5 because the area difference # is percieved more than length difference ratio = 0.4 xm1 = ratio * xa + (1 - ratio) * x0 ym1 = ratio * ya + (1 - ratio) * y0 xm2 = (1 - ratio) * (2 * x2 - x0) + ratio * (2 * x1 - xa) ym2 = (1 - ratio) * (2 * y2 - y0) + ratio * (2 * y1 - ya) self.context.set_source_rgb(*color1) self._create_cairo_path([(xa, ya), (xm1, ym1), (xm2, ym2), (2 * x1 - xa, 2 * y1 - ya)], closed=True) self.context.fill() self.context.set_source_rgb(*color2) self._create_cairo_path([(xm1, ym1), (x0, y0), (2 * x2 - x0, 2 * y2 - y0), (xm2, ym2)], closed=True) self.context.fill() def draw_plain_or_colored_hatch(_start, _end): x1, y1 = _start x2, y2 = _end # no coloring now x, y, x0, y0 = geometry.find_parallel(x1, y1, x2, y2, self.wedge_width / 2.0) xa, ya, xb, yb = geometry.find_parallel(x1, y1, x2, y2, self.line_width / 2.0) d = math.sqrt((x1 - x2)**2 + (y1 - y2)**2) # length of the bond if d == 0: return # to prevent division by zero dx1 = (x0 - xa) / d dy1 = (y0 - ya) / d dx2 = (2 * x2 - x0 - 2 * x1 + xa) / d dy2 = (2 * y2 - y0 - 2 * y1 + ya) / d # we have to decide if the first line should be at the position of the first atom draw_start = 1 # is index not boolean if not v1 in self._vertex_to_bbox and v1.occupied_valency > 1: draw_start = 1 draw_end = 1 # is added to index not boolean if not v2 in self._vertex_to_bbox and v2.occupied_valency > 1: draw_end = 0 # adjust the step length step_size = 2 * (self.line_width) ns = round(d / step_size) or 1 step_size = d / ns # now we finally draw self.context.set_line_cap(cairo.LINE_CAP_BUTT) self.context.set_source_rgb(*color1) middle = 0.5 * (draw_start + int(round(d / step_size)) + draw_end - 2) for i in range(draw_start, int(round(d / step_size)) + draw_end): coords = [ xa + dx1 * i * step_size, ya + dy1 * i * step_size, 2 * x1 - xa + dx2 * i * step_size, 2 * y1 - ya + dy2 * i * step_size ] if coords[0] == coords[2] and coords[1] == coords[3]: if (dx1 + dx2) > (dy1 + dy2): coords[0] += 1 else: coords[1] += 1 self._create_cairo_path([coords[:2], coords[2:]]) if i >= middle: self.context.stroke() self.context.set_source_rgb(*color2) self.context.stroke() # code itself # at first detect the need to make 3D adjustments self._transform = transform3d.transform3d() self._invtransform = transform3d.transform3d() transform = None if e.order > 1: atom1, atom2 = e.vertices for n in atom1.neighbors + atom2.neighbors: # e.atom1 and e.atom2 are in this list as well if n.z != 0: # engage 3d transform prior to detection of where to draw transform = self._get_3dtransform_for_drawing(e) #transform = None break if transform: for n in atom1.neighbors + atom2.neighbors: n.coords = transform.transform_xyz(*n.coords) self._transform = transform self._invtransform = transform.get_inverse() # // end of 3D adjustments # now the code itself coords = self._where_to_draw_from_and_to(e) if coords: start = coords[:2] end = coords[2:] v1, v2 = e.vertices if self.color_bonds: color1 = self.atom_colors.get(v1.symbol, (0, 0, 0)) color2 = self.atom_colors.get(v2.symbol, (0, 0, 0)) else: color1 = color2 = (0, 0, 0) has_shown_vertex = bool( [1 for _v in e.vertices if _v in self._vertex_to_bbox]) if e.order == 1: if e.type == 'w': draw_plain_or_colored_wedge(start, end) elif e.type == 'h': draw_plain_or_colored_hatch(start, end) else: draw_plain_or_colored_line(start, end) if e.order == 2: side = 0 # find how to center the bonds # rings have higher priority in setting the positioning in_ring = False for ring in self.molecule.get_smallest_independent_cycles_dangerous_and_cached( ): double_bonds = len([ b for b in self.molecule.vertex_subgraph_to_edge_subgraph(ring) if b.order == 2 ]) if v1 in ring and v2 in ring: in_ring = True side += double_bonds * reduce(operator.add, [ geometry.on_which_side_is_point( start + end, (a.x, a.y)) for a in ring if a != v1 and a != v2 ]) # if rings did not decide, use the other neigbors if not side: for v in v1.neighbors + v2.neighbors: if v != v1 and v != v2: side += geometry.on_which_side_is_point( start + end, (v.x, v.y)) # if neighbors did not decide either if not side and (in_ring or not has_shown_vertex): if in_ring: # we don't want centered bonds inside rings side = 1 # select arbitrary value else: # bond between two unshown atoms - we want to center them only in some cases if len(v1.neighbors) == 1 and len(v2.neighbors) == 1: # both atoms have only one neighbor side = 0 elif len(v1.neighbors) < 3 and len(v2.neighbors) < 3: # try to figure out which side is more towards the center of the molecule side = reduce(operator.add, [ geometry.on_which_side_is_point( start + end, (a.x, a.y)) for a in self.molecule.vertices if a != v1 and a != v2 ], 0) if not side: side = 1 # we choose arbitrary value, we don't want centering if side: draw_plain_or_colored_line(start, end) x1, y1, x2, y2 = geometry.find_parallel( start[0], start[1], end[0], end[1], self.bond_width * misc.signum(side)) # shorten the second line length = geometry.point_distance(x1, y1, x2, y2) if v2 not in self._vertex_to_bbox: x2, y2 = geometry.elongate_line( x1, y1, x2, y2, -self.bond_second_line_shortening * length) if v1 not in self._vertex_to_bbox: x1, y1 = geometry.elongate_line( x2, y2, x1, y1, -self.bond_second_line_shortening * length) draw_plain_or_colored_line((x1, y1), (x2, y2), second=True) else: for i in (1, -1): x1, y1, x2, y2 = geometry.find_parallel( start[0], start[1], end[0], end[1], i * self.bond_width * 0.5) draw_plain_or_colored_line((x1, y1), (x2, y2)) elif e.order == 3: self._draw_line(start, end, line_width=self.line_width) for i in (1, -1): x1, y1, x2, y2 = geometry.find_parallel( start[0], start[1], end[0], end[1], i * self.bond_width * 0.7) draw_plain_or_colored_line((x1, y1), (x2, y2), second=True) if transform: # if transform was used, we need to transform back for n in atom1.neighbors + atom2.neighbors: n.coords = self._invtransform.transform_xyz(*n.coords)