Exemple #1
0
EXP_ARRAY *qcad_layer_selection_get_object_array (QCADLayer *layer, EXP_ARRAY *ar)
  {
  GList *llItr = NULL ;

  for (llItr = layer->lstSelObjs ; llItr != NULL ; llItr = llItr->next)
    {
    if (NULL == ar)
      ar = exp_array_new (sizeof (QCADDesignObject *), 1) ;
    exp_array_insert_vals (ar, &(llItr->data), 1, 1, -1) ;
    }
  return ar ;
  }
void push_transformation ()
  {
  TRANSFORMATION xform = {-1} ;

  xform.subs_top_x = subs_top_x ;
  xform.subs_top_y = subs_top_y ;
  xform.cxClientArea = cxClientArea ;
  xform.cyClientArea = cyClientArea ;
  xform.scale = scale ;

  if (NULL == transformation_stack)
    transformation_stack = exp_array_new (sizeof (TRANSFORMATION), 1) ;

  exp_array_insert_vals (transformation_stack, &xform, 1, 1, -1) ;
  }
static QCADLabel *get_label_from_array (EXP_ARRAY *ar, int idx, double dCurrentGrad, GdkColor *clr)
  {
  GRADUATION grad = {NULL, 0.0} ;
  GRADUATION *ar_grad = NULL ;

  if (idx == ar->icUsed)
    {
    grad.lbl = qcad_label_new ("%.2lf", dCurrentGrad) ;
    grad.dVal = dCurrentGrad ;
    exp_array_insert_vals (ar, &grad, 1, 1, -1) ;
    ar_grad = &grad ;
    }
  else
  if ((ar_grad = &exp_array_index_1d (ar, GRADUATION, idx))->dVal != dCurrentGrad)
    {
    qcad_label_set_text (QCAD_LABEL (ar_grad->lbl), "%.2lf", dCurrentGrad) ;
    ar_grad->dVal = dCurrentGrad ;
    }

  memcpy (&(QCAD_DESIGN_OBJECT (ar_grad->lbl)->clr), clr, sizeof (GdkColor)) ;

  return ar_grad->lbl ;
  }
static void precompute (QCADElectrode *electrode)
  {
  int Nix, Nix1 ;
  WorldPoint ptSrcLine, ptDstLine ;
  double factor1, factor2, dstx_minus_srcx, dsty_minus_srcy ;
  double pt1x_minus_pt0x, pt1y_minus_pt0y, pt3x_minus_pt2x, pt3y_minus_pt2y ;
  double reciprocal_of_x_divisions, reciprocal_of_y_divisions ;
  QCADRectangleElectrode *rc_electrode = QCAD_RECTANGLE_ELECTRODE (electrode) ;
  QCADDesignObject *obj = QCAD_DESIGN_OBJECT (electrode) ;
  double 
    kose =  cos (rc_electrode->angle),
    msin = -sin (rc_electrode->angle),
    sine =  sin (rc_electrode->angle),
    half_cx = rc_electrode->cxWorld / 2.0,
    half_cy = rc_electrode->cyWorld / 2.0,
    xMin, yMin, xMax, yMax ;
  WorldPoint pt[4] = {{0,0},{0,0},{0,0},{0,0}}, ptCenter = {0,0} ;

  // Call parent precompute function
  QCAD_ELECTRODE_CLASS (g_type_class_peek (g_type_parent (QCAD_TYPE_RECTANGLE_ELECTRODE)))->precompute (electrode) ;

  ptCenter.xWorld = obj->bounding_box.xWorld + obj->bounding_box.cxWorld / 2.0 ;
  ptCenter.yWorld = obj->bounding_box.yWorld + obj->bounding_box.cyWorld / 2.0 ;

  // Create corner points
  pt[0].xWorld = ptCenter.xWorld - half_cx ;
  pt[0].yWorld = ptCenter.yWorld - half_cy ;
  pt[1].xWorld = ptCenter.xWorld + half_cx ;
  pt[1].yWorld = ptCenter.yWorld - half_cy ;
  pt[2].xWorld = ptCenter.xWorld + half_cx ;
  pt[2].yWorld = ptCenter.yWorld + half_cy ;
  pt[3].xWorld = ptCenter.xWorld - half_cx ;
  pt[3].yWorld = ptCenter.yWorld + half_cy ;

  if (0 != rc_electrode->angle)
    {
    // rotate corner points
    rc_electrode->precompute_params.pt[0].xWorld = kose * pt[0].xWorld + sine * pt[0].yWorld ;
    rc_electrode->precompute_params.pt[0].yWorld = msin * pt[0].xWorld + kose * pt[0].yWorld ;
    rc_electrode->precompute_params.pt[1].xWorld = kose * pt[1].xWorld + sine * pt[1].yWorld ;
    rc_electrode->precompute_params.pt[1].yWorld = msin * pt[1].xWorld + kose * pt[1].yWorld ;
    rc_electrode->precompute_params.pt[2].xWorld = kose * pt[2].xWorld + sine * pt[2].yWorld ;
    rc_electrode->precompute_params.pt[2].yWorld = msin * pt[2].xWorld + kose * pt[2].yWorld ;
    rc_electrode->precompute_params.pt[3].xWorld = kose * pt[3].xWorld + sine * pt[3].yWorld ;
    rc_electrode->precompute_params.pt[3].yWorld = msin * pt[3].xWorld + kose * pt[3].yWorld ;

    // Find binding box
    xMin = MIN (rc_electrode->precompute_params.pt[0].xWorld, MIN (rc_electrode->precompute_params.pt[1].xWorld, MIN (rc_electrode->precompute_params.pt[2].xWorld, rc_electrode->precompute_params.pt[3].xWorld))) ;
    xMax = MAX (rc_electrode->precompute_params.pt[0].xWorld, MAX (rc_electrode->precompute_params.pt[1].xWorld, MAX (rc_electrode->precompute_params.pt[2].xWorld, rc_electrode->precompute_params.pt[3].xWorld))) ;
    yMin = MIN (rc_electrode->precompute_params.pt[0].yWorld, MIN (rc_electrode->precompute_params.pt[1].yWorld, MIN (rc_electrode->precompute_params.pt[2].yWorld, rc_electrode->precompute_params.pt[3].yWorld))) ;
    yMax = MAX (rc_electrode->precompute_params.pt[0].yWorld, MAX (rc_electrode->precompute_params.pt[1].yWorld, MAX (rc_electrode->precompute_params.pt[2].yWorld, rc_electrode->precompute_params.pt[3].yWorld))) ;

    obj->bounding_box.xWorld = xMin ;
    obj->bounding_box.yWorld = yMin ;
    obj->bounding_box.cxWorld = xMax - xMin ;
    obj->bounding_box.cyWorld = yMax - yMin ;
    obj->x = obj->bounding_box.xWorld + obj->bounding_box.cxWorld / 2.0 ;
    obj->y = obj->bounding_box.yWorld + obj->bounding_box.cyWorld / 2.0 ;

    // move points back
    rc_electrode->precompute_params.pt[0].xWorld += ptCenter.xWorld - obj->x ;
    rc_electrode->precompute_params.pt[0].yWorld += ptCenter.yWorld - obj->y ;
    rc_electrode->precompute_params.pt[1].xWorld += ptCenter.xWorld - obj->x ;
    rc_electrode->precompute_params.pt[1].yWorld += ptCenter.yWorld - obj->y ;
    rc_electrode->precompute_params.pt[2].xWorld += ptCenter.xWorld - obj->x ;
    rc_electrode->precompute_params.pt[2].yWorld += ptCenter.yWorld - obj->y ;
    rc_electrode->precompute_params.pt[3].xWorld += ptCenter.xWorld - obj->x ;
    rc_electrode->precompute_params.pt[3].yWorld += ptCenter.yWorld - obj->y ;
    obj->bounding_box.xWorld += ptCenter.xWorld - obj->x ;
    obj->bounding_box.yWorld += ptCenter.yWorld - obj->y ;
    obj->x = ptCenter.xWorld ;
    obj->y = ptCenter.yWorld ;
    }
  else
    {
    rc_electrode->precompute_params.pt[0] = pt[0] ;
    rc_electrode->precompute_params.pt[1] = pt[1] ;
    rc_electrode->precompute_params.pt[2] = pt[2] ;
    rc_electrode->precompute_params.pt[3] = pt[3] ;
    obj->bounding_box.xWorld = pt[0].xWorld ;
    obj->bounding_box.yWorld = pt[0].yWorld ;
    obj->bounding_box.cxWorld = rc_electrode->cxWorld ;
    obj->bounding_box.cyWorld = rc_electrode->cyWorld ;
    obj->x = obj->bounding_box.xWorld + obj->bounding_box.cxWorld / 2.0 ;
    obj->y = obj->bounding_box.yWorld + obj->bounding_box.cyWorld / 2.0 ;
    }

  if (NULL != rc_electrode->precompute_params.pts)
    exp_array_free (rc_electrode->precompute_params.pts) ;

  rc_electrode->precompute_params.pts = exp_array_new (sizeof (WorldPoint), 2) ;

  for (Nix = 0 ; Nix < rc_electrode->n_y_divisions ; Nix++)
    exp_array_insert_vals (rc_electrode->precompute_params.pts, NULL, rc_electrode->n_x_divisions, 2, -1, TRUE, 0, TRUE) ;

  // This is a faaar better place to multiply by 1e9 than get_potential
  rc_electrode->precompute_params.rho_factor = 1e9 * QCAD_ELECTRODE (rc_electrode)->precompute_params.capacitance / (rc_electrode->n_x_divisions * rc_electrode->n_y_divisions) ;
  pt1x_minus_pt0x = rc_electrode->precompute_params.pt[1].xWorld - rc_electrode->precompute_params.pt[0].xWorld ;
  pt1y_minus_pt0y = rc_electrode->precompute_params.pt[1].yWorld - rc_electrode->precompute_params.pt[0].yWorld ;
  pt3x_minus_pt2x = rc_electrode->precompute_params.pt[3].xWorld - rc_electrode->precompute_params.pt[2].xWorld ;
  pt3y_minus_pt2y = rc_electrode->precompute_params.pt[3].yWorld - rc_electrode->precompute_params.pt[2].yWorld ;
  reciprocal_of_x_divisions = 1.0 / rc_electrode->n_x_divisions ;
  reciprocal_of_y_divisions = 1.0 / rc_electrode->n_y_divisions ;
  
  for (Nix = 0 ; Nix < rc_electrode->n_x_divisions ; Nix++)
    {
    factor1 = reciprocal_of_x_divisions * (Nix + 0.5) ;
    factor2 = reciprocal_of_x_divisions * ((rc_electrode->n_x_divisions - Nix) - 0.5) ;

    ptSrcLine.xWorld = rc_electrode->precompute_params.pt[0].xWorld + pt1x_minus_pt0x * factor1 ;
    ptSrcLine.yWorld = rc_electrode->precompute_params.pt[0].yWorld + pt1y_minus_pt0y * factor1 ;
    ptDstLine.xWorld = rc_electrode->precompute_params.pt[2].xWorld + pt3x_minus_pt2x * factor2 ;
    ptDstLine.yWorld = rc_electrode->precompute_params.pt[2].yWorld + pt3y_minus_pt2y * factor2 ;

    dstx_minus_srcx = ptDstLine.xWorld - ptSrcLine.xWorld ;
    dsty_minus_srcy = ptDstLine.yWorld - ptSrcLine.yWorld ;
    for (Nix1 = 0 ; Nix1 < rc_electrode->n_y_divisions ; Nix1++)
      {
      exp_array_index_2d (rc_electrode->precompute_params.pts, WorldPoint, Nix1, Nix).xWorld = 
        ptSrcLine.xWorld + dstx_minus_srcx * reciprocal_of_y_divisions * (Nix1 + 0.5) ;
      exp_array_index_2d (rc_electrode->precompute_params.pts, WorldPoint, Nix1, Nix).yWorld = 
        ptSrcLine.yWorld + dsty_minus_srcy * reciprocal_of_y_divisions * (Nix1 + 0.5) ;
      }
    }
  }
// start helpers
static void swap_buses (GtkTreeModel *tm, GtkTreeSelection *sel, bus_layout_D *dialog, GtkTreePath *tpSrc, GtkTreePath *tpDst)
  {
  int Nix ;
  GtkTreeIter itr ;
  SWAP_BUSES_STRUCT src, dst ;
  SWAP_BUSES_STRUCT *min = NULL, *max = NULL ;
  EXP_ARRAY *ar_bSelSrc = NULL, *ar_bSelDst = NULL ;
  gboolean bDstExpanded = TRUE ;

  src.tp = gtk_tree_path_copy (tpSrc) ;
  gtk_tree_model_get_iter (tm, &(src.itr), tpSrc) ;
  src.icChildren = gtk_tree_model_iter_n_children (tm, &(src.itr)) ;

  dst.tp = gtk_tree_path_copy (tpDst) ;
  gtk_tree_model_get_iter (tm, &(dst.itr), tpDst) ;
  dst.icChildren = gtk_tree_model_iter_n_children (tm, &(dst.itr)) ;

  if (dst.icChildren < src.icChildren)
    {
    min = &dst ;
    max = &src ;
    }
  else
    {
    min = &src ;
    max = &dst ;
    }

  bDstExpanded = gtk_tree_view_row_expanded (gtk_tree_selection_get_tree_view (sel), dst.tp) ;

  g_signal_handlers_block_matched (G_OBJECT (sel), G_SIGNAL_MATCH_FUNC, 0, 0, NULL, (gpointer)tree_view_selection_changed, NULL) ;

  for (Nix = 0 ; Nix < max->icChildren - min->icChildren ; Nix++)
    gtk_tree_store_append (GTK_TREE_STORE (tm), &itr, &(min->itr)) ;

  gtk_tree_path_down (src.tp) ;
  gtk_tree_path_down (dst.tp) ;

  ar_bSelSrc = exp_array_new (sizeof (gboolean), 1) ;
  ar_bSelDst = exp_array_new (sizeof (gboolean), 1) ;
  exp_array_insert_vals (ar_bSelSrc, NULL, max->icChildren, 1, 0) ;
  exp_array_insert_vals (ar_bSelDst, NULL, max->icChildren, 1, 0) ;

  for (Nix = 0 ; Nix < max->icChildren ; Nix++)
    {
    exp_array_index_1d (ar_bSelSrc, gboolean, Nix) =
      gtk_tree_selection_path_is_selected (sel, src.tp) ;
    exp_array_index_1d (ar_bSelDst, gboolean, Nix) =
      gtk_tree_selection_path_is_selected (sel, dst.tp) ;

    gtk_tree_path_next (src.tp) ;
    gtk_tree_path_next (dst.tp) ;
    }

  gtk_tree_path_up (src.tp) ;
  gtk_tree_path_up (dst.tp) ;
  gtk_tree_path_down (src.tp) ;
  gtk_tree_path_down (dst.tp) ;

  for (Nix = 0 ; Nix < max->icChildren ; Nix++)
    {
    if (exp_array_index_1d (ar_bSelDst, gboolean, Nix))
      gtk_tree_view_expand_to_path (gtk_tree_selection_get_tree_view (sel), src.tp) ;

    if (exp_array_index_1d (ar_bSelSrc, gboolean, Nix))
      gtk_tree_view_expand_to_path (gtk_tree_selection_get_tree_view (sel), dst.tp) ;

    gtk_tree_path_next (src.tp) ;
    gtk_tree_path_next (dst.tp) ;
    }

  gtk_tree_path_up (src.tp) ;
  gtk_tree_path_up (dst.tp) ;
  gtk_tree_path_down (src.tp) ;
  gtk_tree_path_down (dst.tp) ;

  for (Nix = 0 ; Nix < max->icChildren ; Nix++)
    {
    swap_model_paths_contents (tm, src.tp, dst.tp) ;
    gtk_tree_path_next (src.tp) ;
    gtk_tree_path_next (dst.tp) ;
    }

  gtk_tree_path_up (src.tp) ;
  gtk_tree_path_up (dst.tp) ;
  gtk_tree_path_down (src.tp) ;
  gtk_tree_path_down (dst.tp) ;

  for (Nix = 0 ; Nix < max->icChildren ; Nix++)
    {
    GTK_TREE_SELECTION_SET_PATH_SELECTED (sel, src.tp, exp_array_index_1d (ar_bSelDst, gboolean, Nix)) ;
    GTK_TREE_SELECTION_SET_PATH_SELECTED (sel, dst.tp, exp_array_index_1d (ar_bSelSrc, gboolean, Nix)) ;
    gtk_tree_path_next (src.tp) ;
    gtk_tree_path_next (dst.tp) ;
    }

  gtk_tree_path_up (src.tp) ;
  gtk_tree_path_up (dst.tp) ;
  swap_model_paths_contents (tm, src.tp, dst.tp) ;

  gtk_tree_path_down (src.tp) ;
  gtk_tree_path_down (dst.tp) ;

  for (Nix = 0 ; Nix < min->icChildren ; Nix++)
    gtk_tree_path_next (max->tp) ;
  if (gtk_tree_model_get_iter (tm, &itr, max->tp))
    while (gtk_tree_store_remove (GTK_TREE_STORE (tm), &itr)) ;

  if (!bDstExpanded)
    {
    for (Nix = 0 ; Nix < ar_bSelDst->icUsed ; Nix++)
      if (exp_array_index_1d (ar_bSelDst, gboolean, Nix))
        break ;

    if (Nix == ar_bSelDst->icUsed)
      {
      gtk_tree_path_up (src.tp) ;
      gtk_tree_view_collapse_row (gtk_tree_selection_get_tree_view (sel), src.tp) ;
      }
    }

  exp_array_free (ar_bSelSrc) ;
  exp_array_free (ar_bSelDst) ;
  gtk_tree_path_free (src.tp) ;
  gtk_tree_path_free (dst.tp) ;
  g_signal_handlers_unblock_matched (G_OBJECT (sel), G_SIGNAL_MATCH_FUNC, 0, 0, NULL, (gpointer)tree_view_selection_changed, NULL) ;
  tree_view_selection_changed (sel, dialog) ;
  }
static void DialogToBusLayout (bus_layout_D *dialog, BUS_LAYOUT *bus_layout)
  {
  GtkTreeModel *tm = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->tview)) ;
  int Nix ;
  int icTopLevel = gtk_tree_model_iter_n_children (tm, NULL), icCells = -1 ;
  GtkTreePath *tp = NULL, *tpCells = NULL ;
  GtkTreeIter itr ;
  int Nix1, idxCell = -1 ;
  int row_type ;
  EXP_ARRAY *cell_list = NULL ;
  BUS *bus ;

  // destroy all buses before adding the new ones
  for (Nix = bus_layout->buses->icUsed - 1 ; Nix > -1 ; Nix--)
    {
    exp_array_free (exp_array_index_1d (bus_layout->buses, BUS, Nix).cell_indices) ;
    g_free (exp_array_index_1d (bus_layout->buses, BUS, Nix).pszName) ;
    }
  exp_array_remove_vals (bus_layout->buses, 1, 0, bus_layout->buses->icUsed) ;

  // Since we've destroyed all buses, no cells are members of any bus any longer
  for (Nix = 0 ; Nix < bus_layout->inputs->icUsed ; Nix++)
    exp_array_index_1d (bus_layout->inputs, BUS_LAYOUT_CELL, Nix).bIsInBus = FALSE ;
  for (Nix = 0 ; Nix < bus_layout->outputs->icUsed ; Nix++)
    exp_array_index_1d (bus_layout->outputs, BUS_LAYOUT_CELL, Nix).bIsInBus = FALSE ;

  if (icTopLevel > 0)
    {
    tp = gtk_tree_path_new_first () ;
    for (Nix = 0 ; Nix < icTopLevel ; Nix++, gtk_tree_path_next (tp))
      {
      gtk_tree_model_get_iter (tm, &itr, tp) ;
      gtk_tree_model_get (tm, &itr, BUS_LAYOUT_MODEL_COLUMN_TYPE, &row_type, -1) ;
      if (ROW_TYPE_BUS & row_type)
        {
        exp_array_insert_vals (bus_layout->buses, NULL, 1, 1, -1) ;
        bus = &(exp_array_index_1d (bus_layout->buses, BUS, bus_layout->buses->icUsed - 1)) ;
        gtk_tree_model_get (tm, &itr, BUS_LAYOUT_MODEL_COLUMN_NAME, &(bus->pszName), -1) ;
	if (ROW_TYPE_INPUT & row_type)
	  {
	  bus->bus_function = QCAD_CELL_INPUT ;
	  cell_list = bus_layout->inputs ;
	  }
	else
	  {
	  bus->bus_function = QCAD_CELL_OUTPUT ;
	  cell_list = bus_layout->outputs ;
	  }
        bus->cell_indices = exp_array_new (sizeof (int), 1) ;
        if ((icCells = gtk_tree_model_iter_n_children (tm, &itr)) > 0)
          {
          gtk_tree_path_down (tpCells = gtk_tree_path_copy (tp)) ;

          for (Nix1 = 0 ; Nix1 < icCells ; Nix1++, gtk_tree_path_next (tpCells))
            {
            gtk_tree_model_get_iter (tm, &itr, tpCells) ;
            gtk_tree_model_get (tm, &itr, BUS_LAYOUT_MODEL_COLUMN_INDEX, &idxCell, -1) ;
            exp_array_insert_vals (bus->cell_indices, &idxCell, 1, 1, -1) ;
            // Flag this cell in the master cell list as a member of some bus
            exp_array_index_1d (cell_list, BUS_LAYOUT_CELL, idxCell).bIsInBus = TRUE ;
            }
          gtk_tree_path_free (tpCells) ;
          }
        }
      }
    gtk_tree_path_free (tp) ;
    }
  }