class_docstr: Cairo-specific abstract edge drawer object.
class_docstr_tok: ["Cairo-specific","abstract","edge","drawer","object","."]
docstr: Draws an undirected edge.
  
  The default implementation of this method draws undirected edges
  as straight lines. Loop edges are drawn as small circles.
  
  @param edge: the edge to be drawn. Visual properties of the edge
    are defined by the attributes of this object.
  @param src_vertex: the source vertex. Visual properties are given
    again as attributes.
  @param dest_vertex: the target vertex. Visual properties are given
    again as attributes.
docstr_tok: ["Draws","an","undirected","edge",".","The","default","implementation","of","this","method","draws","undirected","edges","as","straight","lines",".","Loop","edges","are","drawn","as","small","circles",".","@","param","edge",":","the","edge","to","be","drawn",".","Visual","properties","of","the","edge","are","defined","by","the","attributes","of","this","object",".","@","param","src_vertex",":","the","source","vertex",".","Visual","properties","are","given","again","as","attributes",".","@","param","dest_vertex",":","the","target","vertex",".","Visual","properties","are","given","again","as","attributes","."]
code: def draw_undirected_edge(self, edge, src_vertex, dest_vertex):
      """Draws an undirected edge.
  
      The default implementation of this method draws undirected edges
      as straight lines. Loop edges are drawn as small circles.
  
      @param edge: the edge to be drawn. Visual properties of the edge
        are defined by the attributes of this object.
      @param src_vertex: the source vertex. Visual properties are given
        again as attributes.
      @param dest_vertex: the target vertex. Visual properties are given
        again as attributes.
      """
      if src_vertex == dest_vertex:  # TODO
          return self.draw_loop_edge(edge, src_vertex)
  
      ctx = self.context
      ctx.set_source_rgba(*edge.color)
      ctx.set_line_width(edge.width)
      ctx.move_to(*src_vertex.position)
  
      if edge.curved:
          (x1, y1), (x2, y2) = src_vertex.position, dest_vertex.position
          aux1, aux2 = get_bezier_control_points_for_curved_edge(
              x1,
              y1,
              x2,
              y2,
              edge.curved,
          )
          ctx.curve_to(
              aux1[0], aux1[1], aux2[0], aux2[1], *dest_vertex.position
          )
      else:
          ctx.line_to(*dest_vertex.position)
  
      ctx.stroke()
  
imports: from math import atan2, cos, pi, sin
  from igraph.drawing.baseclasses import AbstractEdgeDrawer
  from igraph.drawing.colors import clamp
  from igraph.drawing.metamagic import AttributeCollectorBase
  from igraph.drawing.utils import euclidean_distance, get_bezier_control_points_for_curved_edge, intersect_bezier_curve_and_circle
  from .utils import find_cairo
label_desc: Use image node_id 4 for calling the AbstractCairoEdgeDrawer obj's underlying member method code with example usage: obj.draw_undirected_edge(edge, src_vertex, dest_vertex) and returns: self