예제 #1
0
 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()
예제 #2
0
    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)
예제 #3
0
 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()
예제 #4
0
 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()
예제 #5
0
 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()
예제 #6
0
파일: svg_out.py 프로젝트: Robot-Will/OASA
  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)
예제 #7
0
  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)
예제 #8
0
    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)