text: from __future__ import absolute_import
  from __future__ import print_function
  from __future__ import division
  
  from compas.geometry import convex_hull
  from compas.geometry import add_vectors
  from compas.geometry import scale_vector
  from compas.geometry import subtract_vectors
  
  from compas.utilities import geometric_key
  
  
  __all__ = ['volmesh_ud',
             'cellnetwork_ud']
  
  
  def volmesh_ud(volmesh,
                 network,
                 scale=0.5):
      """Computes temporary vertex coordinates for every halfface of a volmesh, for the visualisation of the unified diagram.
  
      Parameters
      ----------
      volmesh : VolMesh
          A volmesh object representing a polyhedral force diagram.
      network : Network
          A network object representing a polyhedral form diagram.
      scale : float
          Unified diagram scale factor,
  
      Returns
      -------
      halffaces : dictionary
          A dictionary of dictionaries: hfkey-{vkey: (x, y, z)}.
      prisms : dictionary
          A dictinoary of dictinoaries: uv - [face coordinates]
  
      Raises
      ------
      Exception
          If scale is 0, which means the unified diagram is equivalent to the polyhedral force diagram.
      Exception
          If scale is 0, which means the unified diagram is equivalent to the polyhedral form diagram.
  
      Notes
      -----
      - The prisms are implemented as convex hull of two halffaces for simplicity and to resolve any small geometric errors.
      - Unified diagram with a scale of 0 is equivalent to the polyhedral force diagram, while a scale of 1 is equivalent to the polyhedral form diagram.
  
      """
  
      # --------------------------------------------------------------------------
      #   0. evaluate unified diagram scale
      # --------------------------------------------------------------------------
      if scale == 0:
          raise Exception("A unified diagram with a scale of 0 is equivalent to the polyhedral force diagram.")
  
      if scale == 1:
          raise Exception("A unified diagram with a scale of 1 is equivalent to the polyhedral form diagram.")
  
      assert 0 < scale and scale < 1, "Scale needs to be between 0 and 1."
  
      # --------------------------------------------------------------------------
      #   1. current positions of diagrams
      # --------------------------------------------------------------------------
      volmesh_center = volmesh.centroid()
      network_center = network.datastructure_centroid()
      translation = subtract_vectors(volmesh_center, network_center)
  
      # --------------------------------------------------------------------------
      #   2. get base points
      # --------------------------------------------------------------------------
      base_xyz = {}
  
      for vkey in network.nodes():
          init_xyz = network.node_coordinates(vkey)
          base_xyz[vkey] = add_vectors(init_xyz, translation)
  
      # --------------------------------------------------------------------------
      #   3. compute scaled halffaces
      # --------------------------------------------------------------------------
      # halffaces = {}
  
      # for ckey in volmesh.cells():
      #     cell_hfs = volmesh.cell_faces(ckey)
      #     for hfkey in cell_hfs:
      #         hf_vertices = {}
      #         for vkey in volmesh.halfface_vertices(hfkey):
      #             xyz = volmesh.vertex_coordinates(vkey)
      #             arm = scale_vector(subtract_vectors(xyz, base_xyz[ckey]), scale)
      #             hf_vertices[vkey] = add_vectors(base_xyz[ckey], arm)
      #         halffaces[hfkey] = hf_vertices
  
      scaled_halffaces = {}
      cells = {}
  
      for cell in volmesh.cells():
          gkey_xyz = {}
          faces = []
  
          for face in volmesh.cell_faces(cell):
              new_face = []
              scaled_face_xyz = []
              for vertex in volmesh.face_vertices(face):
                  xyz = volmesh.vertex_coordinates(vertex)
                  arm = scale_vector(subtract_vectors(xyz, base_xyz[cell]), scale)
                  scaled_xyz = add_vectors(base_xyz[cell], arm)
                  gkey = geometric_key(scaled_xyz)
                  gkey_xyz[gkey] = scaled_xyz
                  new_face.append(gkey)
                  scaled_face_xyz.append(scaled_xyz)
              scaled_halffaces[face] = scaled_face_xyz
              faces.append(new_face)
  
          gkey_index = dict((gkey, index) for index, gkey in enumerate(gkey_xyz))
          vertices = [list(xyz) for gkey, xyz in gkey_xyz.items()]
          scaled_faces = [[gkey_index[gkey] for gkey in face] for face in faces]
  
          cells[cell] = {'vertices': vertices, 'faces': scaled_faces}
  
      # cells = {}
      # for cell in volmesh.cells():
      #     vertices = volmesh.cell_vertices(cell)
      #     faces = volmesh.cell_faces(cell)
      #     vertex_index = dict((vertex, index) for index, vertex in enumerate(vertices))
      #     scaled_vertices = []
      #     for vertex in vertices:
      #         xyz = volmesh.vertex_coordinates(vertex)
      #         arm = scale_vector(subtract_vectors(xyz, base_xyz[cell]), scale)
      #         scaled_vertices.append(add_vectors(base_xyz[cell], arm))
      #     faces = [[vertex_index[vertex] for vertex in volmesh.halfface_vertices(face)] for face in faces]
      #     cells[cell] = {'vertices': scaled_vertices, 'faces': faces}
  
      # --------------------------------------------------------------------------
      #   4. compute prism faces
      # --------------------------------------------------------------------------
      # prism_faces = {}
  
      prism_cells = {}
  
      for u, v in network.edges():
          u_hfkey, v_hfkey = volmesh.cell_pair_halffaces(u, v)
          u_pts = scaled_halffaces[u_hfkey]
          v_pts = scaled_halffaces[v_hfkey]
          pts = u_pts + v_pts
          prism = convex_hull(pts)  # face as indices of pt_list
          prism_cells[(u, v)] = {'vertices': pts, 'faces': prism}
  
      # for u, v in network.edges():
      #     u_hfkey, v_hfkey = volmesh.cell_pair_halffaces(u, v)
      #     u_pts = halffaces[u_hfkey].values()
      #     v_pts = halffaces[v_hfkey].values()
      #     pt_list = u_pts + v_pts
      #     prism = convex_hull(u_pts + v_pts)  # face as indices of pt_list
      #     face_list = []
      #     for face in prism:
      #         face_xyz = [pt_list[i] for i in face]  # get face xyz in order
      #         face_list.append(face_xyz)
      #     prism_faces[(u, v)] = face_list
      #     prism_cells[(u, v)] = {'vertices': pt_list, 'faces': face_list}
  
      # --------------------------------------------------------------------------
  
      # return halffaces, prism_faces
      return cells, prism_cells
  
  
  def cellnetwork_ud(cellnetwork):
      raise NotImplementedError
  
  
  # ******************************************************************************
  # ******************************************************************************
  # ******************************************************************************
  #
  #   Main
  #
  # ******************************************************************************
  # ******************************************************************************
  # ******************************************************************************
  
  
  if __name__ == '__main__':
      pass
  