void QueryTransformationEngine::appendInstancesDstNodeEdges(const std::string& operatorId,
                                                            const std::vector<std::string>& instanceIds,
                                                            Json::Value& query,
                                                            const size_t numberOfInitialEdges) const {
  Json::Value edges = query["edges"];
  for (const auto& instanceId : instanceIds)
    for (unsigned i = 0; i < numberOfInitialEdges; ++i) {
      Json::Value currentEdge = edges[i];
      if (currentEdge[1u].asString() == operatorId)
        appendEdge(currentEdge[0u].asString(), instanceId, query);
    }
}
void QueryTransformationEngine::appendConsolidateSrcNodeEdges(const std::string& operatorId,
                                                              const std::vector<std::string>& instanceIds,
                                                              const std::string& consolidateOperatorId,
                                                              Json::Value& query,
                                                              const size_t numberOfInitialEdges) const {
  Json::Value edges = query["edges"];
  for (const auto& instanceId : instanceIds)
    appendEdge(instanceId, consolidateOperatorId, query);

  for (unsigned i = 0; i < numberOfInitialEdges; ++i) {
    Json::Value currentEdge = edges[i];
    if (currentEdge[0u].asString() == operatorId) {
      query["edges"][i][0u] = consolidateOperatorId;
    }
  }
}
FormatGridHelper::FormatGridHelper(const QList<ViewItem*> &viewItems, bool protectLayout) {
  const double min_size_limit = 0.02;

  double min_height = 100000.0;
  double min_width = 100000.0;

  n_rows = 0;
  n_cols = 0;

  // Find the smallest plots, to determine the grid resolution
  int n_view = viewItems.size();
  for (int i_view = 0; i_view<n_view; i_view++) {
    ViewItem *item = viewItems.at(i_view);

    if ((item->relativeWidth()<min_width) && (item->relativeWidth()>min_size_limit)) {
      min_width = item->relativeWidth();
    }
    if ((item->relativeHeight()<min_height) && (item->relativeHeight()>min_size_limit)) {
      min_height = item->relativeHeight();
    }
  }
  double grid_x_tolerance = min_width*0.3;
  double grid_y_tolerance = min_height*0.3;

  // Find all the edges
  QList<struct AutoFormatEdges> x_edges;
  QList<struct AutoFormatEdges> y_edges;
  for (int i_view = 0; i_view<n_view; i_view++) {
    ViewItem *item = viewItems.at(i_view);

    appendEdge(x_edges, item->relativeCenter().x() - 0.5*item->relativeWidth(), item->relativeWidth(), item);
    appendEdge(y_edges, item->relativeCenter().y() - 0.5*item->relativeHeight(), item->relativeHeight(), item);
  }

  // find edge concentrations
  QList<qreal> x_edge_locations;
  QList<qreal> y_edge_locations;
  while (findNextEdgeLocation(x_edges, x_edge_locations, grid_x_tolerance)) {
  }
  while (findNextEdgeLocation(y_edges, y_edge_locations, grid_y_tolerance)) {
  }

  QList<int> x_edge_grid;
  QList<int> y_edge_grid;
  convertEdgeLocationsToGrid(x_edge_locations, x_edge_grid);
  convertEdgeLocationsToGrid(y_edge_locations, y_edge_grid);
  // x_edges: list of edges, each of which points to a x_edge_location and to a view item
  // x_edge_location: a list of where the edge concentrations are.
  // x_edge_grid: a list of grid indicies; same order as x_edge_location

  foreach (ViewItem *v, viewItems) {
    int left_gpos = 0;
    int right_gpos = 1;
    int top_gpos = 0;
    int bottom_gpos = 1;
    struct AutoFormatRC rc;
    foreach (const AutoFormatEdges &edge, x_edges) {
      if (edge.item == v) {
        if (edge.left_or_top) {
          left_gpos = x_edge_grid.at(edge.edge_number);
        } else {
          right_gpos = x_edge_grid.at(edge.edge_number);
        }
      }
    }
    foreach (const AutoFormatEdges &edge, y_edges) {
      if (edge.item == v) {
        if (edge.left_or_top) {
          top_gpos = y_edge_grid.at(edge.edge_number);
        } else {
          bottom_gpos = y_edge_grid.at(edge.edge_number);
        }
      }
    }
    rc.row = top_gpos;
    rc.col = left_gpos;
    rc.row_span = bottom_gpos - top_gpos;
    rc.col_span = right_gpos - left_gpos;
    rcList.append(rc);

    n_rows = qMax(rc.row + rc.row_span, n_rows);
    n_cols = qMax(rc.col + rc.col_span, n_cols);
  }