docs: def profile_to_cross_section(profile, lefthand=False, start_count=1, min_vertices=20):
      r"""
      Converts a thread profile to it's equivalent cross-section.
  
      **Profile:**
  
      The thread profile contains a single wire along the XZ plane
      (note: wire will be projected onto the XZ plane; Y-coords will be ignored).
      The profile is expected to be of 1 thread rotation, so it's height
      (along the Z-axis) is the thread's "pitch".
      If start_count > 1, then the profile will effectively be duplicated.
      The resulting cross-section is designed to be swept along a helical path
      with a pitch of the thread's "lead" (which is {the height of the given
      profile} * start_count)
  
      **Method:**
  
      Each edge of the profile is converted to a bezier spline, aproximating
      its polar plot equivalent.
  
      **Resolution:** (via `min_vertices` parameter)
  
      Increasing the number of vertices used to define the bezier will
      increase the resulting thread's accuracy, but cost more to render.
  
      min_vertices may also be expressed as a list to set the number of
      vertices to set for each wire.
      where: len(min_vertices) == number of edges in profile
  
      **Example**
  
      .. doctest::
  
          import cadquery
          from cqparts_fasteners.solidtypes.threads.base import profile_to_cross_section
          from Helpers import show  # doctest: +SKIP
  
          profile = cadquery.Workplane("XZ") \
              .moveTo(1, 0) \
              .lineTo(2, 1).lineTo(1, 2) \
              .wire()
          cross_section = profile_to_cross_section(profile)
  
          show(profile)  # doctest: +SKIP
          show(cross_section)  # doctest: +SKIP
  
      Will result in:
  
      .. image:: /_static/img/solidtypes.threads.base.profile_to_cross_section.01.png
  
      :param profile: workplane containing wire of thread profile.
      :type profile: :class:`cadquery.Workplane`
      :param lefthand: if True, cross-section is made backwards.
      :type lefthand: :class:`bool`
      :param start_count: profile is duplicated this many times.
      :type start_count: :class:`int`
      :param min_vertices: int or tuple of the desired resolution.
      :type min_vertices: :class:`int` or :class:`tuple`
      :return: workplane with a face ready to be swept into a thread.
      :rtype: :class:`cadquery.Workplane`
      :raises TypeError: if a problem is found with the given parameters.
      :raises ValueError: if ``min_vertices`` is a list with elements not equal to the numbmer of wire edges.
      """
      # verify parameter(s)
      if not isinstance(profile, cadquery.Workplane):
          raise TypeError("profile %r must be a %s instance" % (profile, cadquery.Workplane))
      if not isinstance(min_vertices, (int, list, tuple)):
          raise TypeError("min_vertices %r must be an int, list, or tuple" % (min_vertices))
  
      # get wire from Workplane
      wire = profile.val()  # cadquery.Wire
      if not isinstance(wire, cadquery.Wire):
          raise TypeError("a valid profile Wire type could not be found in the given Workplane")
  
      profile_bb = wire.BoundingBox()
      pitch = profile_bb.zmax - profile_bb.zmin
      lead = pitch * start_count
  
      # determine vertices count per edge
      edges = wire.Edges()
      vertices_count = None
      if isinstance(min_vertices, int):
          # evenly spread vertices count along profile wire
          # (weighted by the edge's length)
          vertices_count = [
              int(ceil(round(e.Length() / wire.Length(), 7) * min_vertices))
              for e in edges
          ]
          # rounded for desired contrived results
          # (trade-off: an error of 1 is of no great consequence)
      else:
          # min_vertices is defined per edge (already what we want)
          if len(min_vertices) != len(edges):
              raise ValueError(
                  "min_vertices list size does not match number of profile edges: "
                  "len(%r) != %i" % (min_vertices, len(edges))
              )
          vertices_count = min_vertices
  
      # Utilities for building cross-section
      def get_xz(vertex):
          if isinstance(vertex, cadquery.Vector):
              vertex = vertex.wrapped  # TODO: remove this, it's messy
          # where isinstance(vertex, FreeCAD.Base.Vector)
          return (vertex.x, vertex.z)
  
      def cart2polar(x, z, z_offset=0):
          """
          Convert cartesian coordinates to polar coordinates.
          Uses thread's lead height to give full 360deg translation.
          """
          radius = x
          angle = ((z + z_offset) / lead) * (2 * pi)  # radians
          if not lefthand:
              angle = -angle
          return (radius, angle)
  
      def transform(vertex, z_offset=0):
          # where isinstance(vertex, FreeCAD.Base.Vector)
          """
          Transform profile vertex on the XZ plane to it's equivalent on
          the cross-section's XY plane
          """
          (radius, angle) = cart2polar(*get_xz(vertex), z_offset=z_offset)
          return (radius * cos(angle), radius * sin(angle))
  
      # Conversion methods
      def apply_spline(wp, edge, vert_count, z_offset=0):
          """
          Trace along edge and create a spline from the transformed verteces.
          """
          curve = edge.wrapped.Curve  # FreeCADPart.Geom* (depending on type)
          if edge.geomType() == 'CIRCLE':
              iter_dist = edge.wrapped.ParameterRange[1] / vert_count
          else:
              iter_dist = edge.Length() / vert_count
          points = []
          for j in range(vert_count):
              dist = (j + 1) * iter_dist
              vert = curve.value(dist)
              points.append(transform(vert, z_offset))
          return wp.spline(points)
  
      def apply_arc(wp, edge, z_offset=0):
          """
          Create an arc using edge's midpoint and endpoint.
          Only intended for use for vertical lines on the given profile.
          """
          return wp.threePointArc(
              point1=transform(edge.wrapped.valueAt(edge.Length() / 2), z_offset),
              point2=transform(edge.wrapped.valueAt(edge.Length()), z_offset),
          )
  
      def apply_radial_line(wp, edge, z_offset=0):
          """
          Create a straight radial line
          """
          return wp.lineTo(*transform(edge.endPoint(), z_offset))
  
      # Build cross-section
      start_v = edges[0].startPoint().wrapped
      cross_section = cadquery.Workplane("XY") \
          .moveTo(*transform(start_v))
  
      for i in range(start_count):
          z_offset = i * pitch
          for (j, edge) in enumerate(wire.Edges()):
              # where: isinstance(edge, cadquery.Edge)
              if (edge.geomType() == 'LINE') and (edge.startPoint().x == edge.endPoint().x):
                  # edge is a vertical line, plot a circular arc
                  cross_section = apply_arc(cross_section, edge, z_offset)
              elif (edge.geomType() == 'LINE') and (edge.startPoint().z == edge.endPoint().z):
                  # edge is a horizontal line, plot a radial line
                  cross_section = apply_radial_line(cross_section, edge, z_offset)
              else:
                  # create bezier spline along transformed points (default)
                  cross_section = apply_spline(cross_section, edge, vertices_count[j], z_offset)
  
      return cross_section.close()