private void setEdgeFaces() {
   for (Face face : getFaces()) {
     for (Edge edge : face.getEdges()) {
       edge.getFaces().add(face);
     }
   }
 }
  private boolean isCellOpen(Cell cell) {
    Set<Face> cellFaces = cell.getFaces();

    for (Face face : cellFaces) {
      for (Edge edge : face.getEdges()) {

        Set<Face> faceSiblingsByEdge = new HashSet<Face>(face.getSiblings(edge));
        faceSiblingsByEdge.retainAll(cellFaces);
        if (faceSiblingsByEdge.size() == 0) {
          return true;
        }
      }
    }
    return false;
  }
  private void traverseFaces() {
    Set<Space> uniqueSpaces = new HashSet<Space>();
    Map<Cell, Space> cellToSpaces = new HashMap<Cell, Space>();
    Map<Space, Cell> spaceToCells = new HashMap<Space, Cell>();

    double figurePrecision = getPrecision();

    for (Face currFace : getFaces()) {
      Set<Cell> currCells = currFace.getCells();

      Plane currFacePlane = Util.create2dPlaneFrom(currFace, figurePrecision);

      nextSiblings:
      for (Face siblingFace : currFace.getSiblings()) {
        Set<Cell> siblingCells = siblingFace.getCells();

        // omit faces lying in the same plane as the original face
        if (Util.isLyingOn(siblingFace, currFacePlane)) {
          continue nextSiblings;
        }

        for (Cell currCell : currCells) {
          // omit faces already participated in one of the current cells
          if (currCell.getFaces().contains(siblingFace)) {
            continue nextSiblings;

          } else if (Util.isLyingOn(siblingFace, cellToSpaces.get(currCell))) {

            currCell.addFace(siblingFace);
            continue nextSiblings;
          }
        }

        for (Cell siblingCell : siblingCells) {
          if (Util.isLyingOn(currFace, cellToSpaces.get(siblingCell))) {
            siblingCell.addFace(currFace);

            continue nextSiblings;
          }
        }

        Space newSpace = Util.create3dSpaceFrom(currFace, siblingFace, figurePrecision);
        if (!Util.isLyingOn(currFace, newSpace) || !Util.isLyingOn(siblingFace, newSpace)) {
          throw new RuntimeException("Creation of 3D spaces logic does not work!");
        }

        Cell newCell;
        if (uniqueSpaces.contains(newSpace)) {
          newCell = spaceToCells.get(newSpace);

        } else {
          newCell = new Cell();
          uniqueSpaces.add(newSpace);
          cellToSpaces.put(newCell, newSpace);
          spaceToCells.put(newSpace, newCell);

          getCells().add(newCell);
        }

        newCell.addFace(currFace);
        newCell.addFace(siblingFace);
      }
    }
  }