Example #1
0
/* create an "empty space" representation */
mtspace_t *
mtspace_create (void)
{
  mtspace_t *mtspace;

  /* create mtspace data structure */
  mtspace = (mtspace_t *)malloc (sizeof (*mtspace));
  mtspace->ftree = r_create_tree (NULL, 0, 0);
  mtspace->etree = r_create_tree (NULL, 0, 0);
  mtspace->otree = r_create_tree (NULL, 0, 0);
  /* done! */
  return mtspace;
}
Example #2
0
/* ---------------------------------------------------------------------------
 * get next slot for an element, allocates memory if necessary
 */
ElementTypePtr
GetElementMemory (DataTypePtr Data)
{
  ElementTypePtr element = Data->Element;
  int i;

  /* realloc new memory if necessary and clear it */
  if (Data->ElementN >= Data->ElementMax)
    {
      Data->ElementMax += STEP_ELEMENT;
      if (Data->element_tree)
	r_destroy_tree (&Data->element_tree);
      element = MyRealloc (element, Data->ElementMax * sizeof (ElementType),
			   "GetElementMemory()");
      Data->Element = element;
      memset (element + Data->ElementN, 0,
	      STEP_ELEMENT * sizeof (ElementType));
      Data->element_tree = r_create_tree (NULL, 0, 0);
      for (i = 0; i < MAX_ELEMENTNAMES; i++)
	{
	  if (Data->name_tree[i])
	    r_destroy_tree (&Data->name_tree[i]);
	  Data->name_tree[i] = r_create_tree (NULL, 0, 0);
	}

      ELEMENT_LOOP (Data);
      {
	r_insert_entry (Data->element_tree, (BoxType *) element, 0);
	PIN_LOOP (element);
	{
	  pin->Element = element;
	}
	END_LOOP;
	PAD_LOOP (element);
	{
	  pad->Element = element;
	}
	END_LOOP;
	ELEMENTTEXT_LOOP (element);
	{
	  text->Element = element;
	  r_insert_entry (Data->name_tree[n], (BoxType *) text, 0);
	}
	END_LOOP;
      }
      END_LOOP;
    }
  return (element + Data->ElementN++);
}
Example #3
0
File: create.c Project: thequux/pcb
LineTypePtr
CreateNewLineOnLayer (LayerTypePtr Layer,
		      LocationType X1, LocationType Y1,
		      LocationType X2, LocationType Y2,
		      BDimension Thickness, BDimension Clearance,
		      FlagType Flags)
{
  LineTypePtr Line;

  Line = GetLineMemory (Layer);
  if (!Line)
    return (Line);
  Line->ID = ID++;
  Line->Flags = Flags;
  CLEAR_FLAG (RATFLAG, Line);
  Line->Thickness = Thickness;
  Line->Clearance = Clearance;
  Line->Point1.X = X1;
  Line->Point1.Y = Y1;
  Line->Point1.ID = ID++;
  Line->Point2.X = X2;
  Line->Point2.Y = Y2;
  Line->Point2.ID = ID++;
  SetLineBoundingBox (Line);
  if (!Layer->line_tree)
    Layer->line_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (Layer->line_tree, (BoxTypePtr) Line, 0);
  return (Line);
}
Example #4
0
File: create.c Project: thequux/pcb
/* ---------------------------------------------------------------------------
 * creates a new rat-line
 */
RatTypePtr
CreateNewRat (DataTypePtr Data, LocationType X1, LocationType Y1,
	      LocationType X2, LocationType Y2, Cardinal group1,
	      Cardinal group2, BDimension Thickness, FlagType Flags)
{
  RatTypePtr Line = GetRatMemory (Data);

  if (!Line)
    return (Line);

  Line->ID = ID++;
  Line->Flags = Flags;
  SET_FLAG (RATFLAG, Line);
  Line->Thickness = Thickness;
  Line->Point1.X = X1;
  Line->Point1.Y = Y1;
  Line->Point1.ID = ID++;
  Line->Point2.X = X2;
  Line->Point2.Y = Y2;
  Line->Point2.ID = ID++;
  Line->group1 = group1;
  Line->group2 = group2;
  SetLineBoundingBox ((LineTypePtr) Line);
  if (!Data->rat_tree)
    Data->rat_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (Data->rat_tree, &Line->BoundingBox, 0);
  return (Line);
}
Example #5
0
/* ---------------------------------------------------------------------------
 * get next slot for a polygon object, allocates memory if necessary
 */
PolygonTypePtr
GetPolygonMemory (LayerTypePtr Layer)
{
  PolygonTypePtr polygon = Layer->Polygon;

  /* realloc new memory if necessary and clear it */
  if (Layer->PolygonN >= Layer->PolygonMax)
    {
      Layer->PolygonMax += STEP_POLYGON;
      if (Layer->polygon_tree)
	r_destroy_tree (&Layer->polygon_tree);
      polygon = MyRealloc (polygon, Layer->PolygonMax * sizeof (PolygonType),
			   "GetPolygonMemory()");
      Layer->Polygon = polygon;
      memset (polygon + Layer->PolygonN, 0,
	      STEP_POLYGON * sizeof (PolygonType));
      Layer->polygon_tree = r_create_tree (NULL, 0, 0);
      POLYGON_LOOP (Layer);
      {
	r_insert_entry (Layer->polygon_tree, (BoxType *) polygon, 0);
      }
      END_LOOP;
    }
  return (polygon + Layer->PolygonN++);
}
Example #6
0
/* ---------------------------------------------------------------------------
 * get next slot for a line, allocates memory if necessary
 */
LineTypePtr
GetLineMemory (LayerTypePtr Layer)
{
  LineTypePtr line = Layer->Line;

  /* realloc new memory if necessary and clear it */
  if (Layer->LineN >= Layer->LineMax)
    {
      Layer->LineMax += STEP_LINE;
      /* all of the pointers move, so rebuild the whole tree */
      if (Layer->line_tree)
	r_destroy_tree (&Layer->line_tree);
      line = MyRealloc (line, Layer->LineMax * sizeof (LineType),
			"GetLineMemory()");
      Layer->Line = line;
      memset (line + Layer->LineN, 0, STEP_LINE * sizeof (LineType));
      Layer->line_tree = r_create_tree (NULL, 0, 0);
      LINE_LOOP (Layer);
      {
	r_insert_entry (Layer->line_tree, (BoxTypePtr) line, 0);
      }
      END_LOOP;
    }
  return (line + Layer->LineN++);
}
Example #7
0
/* ---------------------------------------------------------------------------
 * get next slot for a Rat, allocates memory if necessary
 */
RatTypePtr
GetRatMemory (DataTypePtr Data)
{
  RatTypePtr rat = Data->Rat;

  /* realloc new memory if necessary and clear it */
  if (Data->RatN >= Data->RatMax)
    {
      Data->RatMax += STEP_RAT;
      /* all of the pointers move, so rebuild the whole tree */
      if (Data->rat_tree)
        r_destroy_tree (&Data->rat_tree);
      rat = MyRealloc (rat, Data->RatMax * sizeof (RatType),
		       "GetRatMemory()");
      Data->Rat = rat;
      memset (rat + Data->RatN, 0, STEP_RAT * sizeof (RatType));
      Data->rat_tree = r_create_tree (NULL, 0, 0);
      RAT_LOOP (Data);
      {
        r_insert_entry (Data->rat_tree, (BoxTypePtr) line, 0);
      }
      END_LOOP;
    }
  return (rat + Data->RatN++);
}
Example #8
0
/* ---------------------------------------------------------------------------
 * moves a text object between layers; lowlevel routines
 */
static void *
MoveTextToLayerLowLevel (LayerType *Source, TextType *text,
			 LayerType *Destination)
{
  RestoreToPolygon (PCB->Data, TEXT_TYPE, Source, text);
  r_delete_entry (Source->text_tree, (BoxType *)text);

  Source->Text = g_list_remove (Source->Text, text);
  Source->TextN --;
  Destination->Text = g_list_append (Destination->Text, text);
  Destination->TextN ++;

  if (GetLayerGroupNumberByNumber (solder_silk_layer) ==
      GetLayerGroupNumberByPointer (Destination))
    SET_FLAG (ONSOLDERFLAG, text);
  else
    CLEAR_FLAG (ONSOLDERFLAG, text);

  /* re-calculate the bounding box (it could be mirrored now) */
  SetTextBoundingBox (&PCB->Font, text);
  if (!Destination->text_tree)
    Destination->text_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (Destination->text_tree, (BoxType *)text, 0);
  ClearFromPolygon (PCB->Data, TEXT_TYPE, Destination, text);

  return text;
}
Example #9
0
LineType *
CreateNewLineOnLayer (LayerType *Layer,
		      Coord X1, Coord Y1,
		      Coord X2, Coord Y2,
		      Coord Thickness, Coord Clearance,
		      FlagType Flags)
{
  LineType *Line;

  Line = GetLineMemory (Layer);
  if (!Line)
    return (Line);
  Line->ID = ID++;
  Line->Flags = Flags;
  CLEAR_FLAG (RATFLAG, Line);
  Line->Thickness = Thickness;
  Line->Clearance = Clearance;
  Line->Point1.X = X1;
  Line->Point1.Y = Y1;
  Line->Point1.ID = ID++;
  Line->Point2.X = X2;
  Line->Point2.Y = Y2;
  Line->Point2.ID = ID++;
  SetLineBoundingBox (Line);
  if (!Layer->line_tree)
    Layer->line_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (Layer->line_tree, (BoxType *) Line, 0);
  return (Line);
}
Example #10
0
File: create.c Project: thequux/pcb
/* ---------------------------------------------------------------------------
 * creates a new text on a layer
 */
TextTypePtr
CreateNewText (LayerTypePtr Layer, FontTypePtr PCBFont,
	       LocationType X, LocationType Y,
	       BYTE Direction, int Scale, char *TextString, FlagType Flags)
{
  TextType *text;

  if (TextString == NULL)
    return NULL;

  text = GetTextMemory (Layer);
  if (text == NULL)
    return NULL;

  /* copy values, width and height are set by drawing routine
   * because at this point we don't know which symbols are available
   */
  text->X = X;
  text->Y = Y;
  text->Direction = Direction;
  text->Flags = Flags;
  text->Scale = Scale;
  text->TextString = strdup (TextString);

  /* calculate size of the bounding box */
  SetTextBoundingBox (PCBFont, text);
  text->ID = ID++;
  if (!Layer->text_tree)
    Layer->text_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (Layer->text_tree, (BoxTypePtr) text, 0);
  return (text);
}
Example #11
0
/* ---------------------------------------------------------------------------
 * moves an arc between layers; lowlevel routines
 */
static void *
MoveArcToLayerLowLevel (LayerType *Source, ArcType *arc,
			LayerType *Destination)
{
  r_delete_entry (Source->arc_tree, (BoxType *)arc);

  Source->Arc = g_list_remove (Source->Arc, arc);
  Source->ArcN --;
  Destination->Arc = g_list_append (Destination->Arc, arc);
  Destination->ArcN ++;

  if (!Destination->arc_tree)
    Destination->arc_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (Destination->arc_tree, (BoxType *)arc, 0);
  return arc;
}
Example #12
0
/* ---------------------------------------------------------------------------
 * copies a polygon 
 */
static void *
CopyPolygon (LayerType *Layer, PolygonType *Polygon)
{
  PolygonType *polygon;

  polygon = CreateNewPolygon (Layer, NoFlags ());
  CopyPolygonLowLevel (polygon, Polygon);
  MovePolygonLowLevel (polygon, DeltaX, DeltaY);
  if (!Layer->polygon_tree)
    Layer->polygon_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (Layer->polygon_tree, (BoxType *) polygon, 0);
  InitClip (PCB->Data, Layer, polygon);
  DrawPolygon (Layer, polygon);
  AddObjectToCreateUndoList (POLYGON_TYPE, Layer, polygon, polygon);
  return (polygon);
}
Example #13
0
/* ---------------------------------------------------------------------------
 * moves a line between layers; lowlevel routines
 */
static void *
MoveLineToLayerLowLevel (LayerType *Source, LineType *line,
			 LayerType *Destination)
{
  r_delete_entry (Source->line_tree, (BoxType *)line);

  Source->Line = g_list_remove (Source->Line, line);
  Source->LineN --;
  Destination->Line = g_list_append (Destination->Line, line);
  Destination->LineN ++;

  if (!Destination->line_tree)
    Destination->line_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (Destination->line_tree, (BoxType *)line, 0);
  return line;
}
Example #14
0
/* ---------------------------------------------------------------------------
 * moves a rat-line to paste buffer
 */
static void *
MoveRatToBuffer (RatType *rat)
{
  r_delete_entry (Source->rat_tree, (BoxType *)rat);

  Source->Rat = g_list_remove (Source->Rat, rat);
  Source->RatN --;
  Dest->Rat = g_list_append (Dest->Rat, rat);
  Dest->RatN ++;

  CLEAR_FLAG (NOCOPY_FLAGS, rat);

  if (!Dest->rat_tree)
    Dest->rat_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (Dest->rat_tree, (BoxType *)rat, 0);
  return rat;
}
Example #15
0
/* ---------------------------------------------------------------------------
 * moves a polygon between layers; lowlevel routines
 */
static void *
MovePolygonToLayerLowLevel (LayerType *Source, PolygonType *polygon,
			    LayerType *Destination)
{
  r_delete_entry (Source->polygon_tree, (BoxType *)polygon);

  Source->Polygon = g_list_remove (Source->Polygon, polygon);
  Source->PolygonN --;
  Destination->Polygon = g_list_append (Destination->Polygon, polygon);
  Destination->PolygonN ++;

  if (!Destination->polygon_tree)
    Destination->polygon_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (Destination->polygon_tree, (BoxType *)polygon, 0);

  return polygon;
}
Example #16
0
/* ---------------------------------------------------------------------------
 * moves a via to paste buffer without allocating memory for the name
 */
static void *
MoveViaToBuffer (PinType *via)
{
  RestoreToPolygon (Source, VIA_TYPE, via, via);

  r_delete_entry (Source->via_tree, (BoxType *) via);
  Source->Via = g_list_remove (Source->Via, via);
  Source->ViaN --;
  Dest->Via = g_list_append (Dest->Via, via);
  Dest->ViaN ++;

  CLEAR_FLAG (WARNFLAG | NOCOPY_FLAGS, via);

  if (!Dest->via_tree)
    Dest->via_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (Dest->via_tree, (BoxType *)via, 0);
  ClearFromPolygon (Dest, VIA_TYPE, via, via);
  return via;
}
Example #17
0
/* ---------------------------------------------------------------------------
 * moves a text to buffer without allocating memory for the name
 */
static void *
MoveTextToBuffer (LayerType *layer, TextType *text)
{
  LayerType *lay = &Dest->Layer[GetLayerNumber (Source, layer)];

  r_delete_entry (layer->text_tree, (BoxType *)text);
  RestoreToPolygon (Source, TEXT_TYPE, layer, text);

  layer->Text = g_list_remove (layer->Text, text);
  layer->TextN --;
  lay->Text = g_list_append (lay->Text, text);
  lay->TextN ++;

  if (!lay->text_tree)
    lay->text_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (lay->text_tree, (BoxType *)text, 0);
  ClearFromPolygon (Dest, TEXT_TYPE, lay, text);
  return (text);
}
Example #18
0
/* ---------------------------------------------------------------------------
 * moves a polygon to buffer. Doesn't allocate memory for the points
 */
static void *
MovePolygonToBuffer (LayerType *layer, PolygonType *polygon)
{
  LayerType *lay = &Dest->Layer[GetLayerNumber (Source, layer)];

  r_delete_entry (layer->polygon_tree, (BoxType *)polygon);

  layer->Polygon = g_list_remove (layer->Polygon, polygon);
  layer->PolygonN --;
  lay->Polygon = g_list_append (lay->Polygon, polygon);
  lay->PolygonN ++;

  CLEAR_FLAG (NOCOPY_FLAGS, polygon);

  if (!lay->polygon_tree)
    lay->polygon_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (lay->polygon_tree, (BoxType *)polygon, 0);
  return (polygon);
}
Example #19
0
File: create.c Project: thequux/pcb
/* ---------------------------------------------------------------------------
 * creates a new polygon from the old formats rectangle data
 */
PolygonTypePtr
CreateNewPolygonFromRectangle (LayerTypePtr Layer,
			       LocationType X1, LocationType Y1,
			       LocationType X2, LocationType Y2,
			       FlagType Flags)
{
  PolygonTypePtr polygon = CreateNewPolygon (Layer, Flags);
  if (!polygon)
    return (polygon);

  CreateNewPointInPolygon (polygon, X1, Y1);
  CreateNewPointInPolygon (polygon, X2, Y1);
  CreateNewPointInPolygon (polygon, X2, Y2);
  CreateNewPointInPolygon (polygon, X1, Y2);
  SetPolygonBoundingBox (polygon);
  if (!Layer->polygon_tree)
    Layer->polygon_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (Layer->polygon_tree, (BoxTypePtr) polygon, 0);
  return (polygon);
}
Example #20
0
/* ---------------------------------------------------------------------------
 * copies a polygon to buffer
 */
static void *
AddPolygonToBuffer (LayerType *Layer, PolygonType *Polygon)
{
  LayerType *layer = &Dest->Layer[GetLayerNumber (Source, Layer)];
  PolygonType *polygon;

  polygon = CreateNewPolygon (layer, Polygon->Flags);
  CopyPolygonLowLevel (polygon, Polygon);

  /* Update the polygon r-tree. Unlike similarly named functions for
   * other objects, CreateNewPolygon does not do this as it creates a
   * skeleton polygon object, which won't have correct bounds.
   */
  if (!layer->polygon_tree)
    layer->polygon_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (layer->polygon_tree, (BoxType *)polygon, 0);

  CLEAR_FLAG (NOCOPY_FLAGS | ExtraFlag, polygon);
  return (polygon);
}
Example #21
0
/*!
 * \brief Creates a new polygon from the old formats rectangle data.
 */
PolygonType *
CreateNewPolygonFromRectangle (LayerType *Layer,
			       Coord X1, Coord Y1,
			       Coord X2, Coord Y2,
			       FlagType Flags)
{
  PolygonType *polygon = CreateNewPolygon (Layer, Flags);
  if (!polygon)
    return (polygon);

  CreateNewPointInPolygon (polygon, X1, Y1);
  CreateNewPointInPolygon (polygon, X2, Y1);
  CreateNewPointInPolygon (polygon, X2, Y2);
  CreateNewPointInPolygon (polygon, X1, Y2);
  SetPolygonBoundingBox (polygon);
  if (!Layer->polygon_tree)
    Layer->polygon_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (Layer->polygon_tree, (BoxType *) polygon, 0);
  return (polygon);
}
Example #22
0
/* ---------------------------------------------------------------------------
 * moves a line to buffer  
 */
static void *
MoveLineToBuffer (LayerType *layer, LineType *line)
{
  LayerType *lay = &Dest->Layer[GetLayerNumber (Source, layer)];

  RestoreToPolygon (Source, LINE_TYPE, layer, line);
  r_delete_entry (layer->line_tree, (BoxType *)line);

  layer->Line = g_list_remove (layer->Line, line);
  layer->LineN --;
  lay->Line = g_list_append (lay->Line, line);
  lay->LineN ++;

  CLEAR_FLAG (NOCOPY_FLAGS, line);

  if (!lay->line_tree)
    lay->line_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (lay->line_tree, (BoxType *)line, 0);
  ClearFromPolygon (Dest, LINE_TYPE, lay, line);
  return (line);
}
Example #23
0
/* ---------------------------------------------------------------------------
 * moves an arc to buffer  
 */
static void *
MoveArcToBuffer (LayerType *layer, ArcType *arc)
{
  LayerType *lay = &Dest->Layer[GetLayerNumber (Source, layer)];

  RestoreToPolygon (Source, ARC_TYPE, layer, arc);
  r_delete_entry (layer->arc_tree, (BoxType *)arc);

  layer->Arc = g_list_remove (layer->Arc, arc);
  layer->ArcN --;
  lay->Arc = g_list_append (lay->Arc, arc);
  lay->ArcN ++;

  CLEAR_FLAG (NOCOPY_FLAGS, arc);

  if (!lay->arc_tree)
    lay->arc_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (lay->arc_tree, (BoxType *)arc, 0);
  ClearFromPolygon (Dest, ARC_TYPE, lay, arc);
  return (arc);
}
Example #24
0
File: create.c Project: thequux/pcb
/* ---------------------------------------------------------------------------
 * creates a new arc on a layer
 */
ArcTypePtr
CreateNewArcOnLayer (LayerTypePtr Layer,
		     LocationType X1, LocationType Y1,
		     BDimension width,
		     BDimension height,
		     int sa,
		     int dir, BDimension Thickness,
		     BDimension Clearance, FlagType Flags)
{
  ArcTypePtr Arc;

  ARC_LOOP (Layer);
  {
    if (arc->X == X1 && arc->Y == Y1 && arc->Width == width &&
	(arc->StartAngle + 360) % 360 == (sa + 360) % 360 &&
	arc->Delta == dir)
      return (NULL);		/* prevent stacked arcs */
  }
  END_LOOP;
  Arc = GetArcMemory (Layer);
  if (!Arc)
    return (Arc);

  Arc->ID = ID++;
  Arc->Flags = Flags;
  Arc->Thickness = Thickness;
  Arc->Clearance = Clearance;
  Arc->X = X1;
  Arc->Y = Y1;
  Arc->Width = width;
  Arc->Height = height;
  Arc->StartAngle = sa;
  Arc->Delta = dir;
  SetArcBoundingBox (Arc);
  if (!Layer->arc_tree)
    Layer->arc_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (Layer->arc_tree, (BoxTypePtr) Arc, 0);
  return (Arc);
}
Example #25
0
/*!
 * \brief Creates a new arc on a layer.
 */
ArcType *
CreateNewArcOnLayer (LayerType *Layer,
		     Coord X1, Coord Y1,
		     Coord width,
		     Coord height,
		     Angle sa,
		     Angle dir, Coord Thickness,
		     Coord Clearance, FlagType Flags)
{
  ArcType *Arc;

  ARC_LOOP (Layer);
  {
    if (arc->X == X1 && arc->Y == Y1 && arc->Width == width &&
	NormalizeAngle (arc->StartAngle) == NormalizeAngle (sa) &&
	arc->Delta == dir)
      return (NULL);		/* prevent stacked arcs */
  }
  END_LOOP;
  Arc = GetArcMemory (Layer);
  if (!Arc)
    return (Arc);

  Arc->ID = ID++;
  Arc->Flags = Flags;
  Arc->Thickness = Thickness;
  Arc->Clearance = Clearance;
  Arc->X = X1;
  Arc->Y = Y1;
  Arc->Width = width;
  Arc->Height = height;
  Arc->StartAngle = sa;
  Arc->Delta = dir;
  SetArcBoundingBox (Arc);
  if (!Layer->arc_tree)
    Layer->arc_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (Layer->arc_tree, (BoxType *) Arc, 0);
  return (Arc);
}
Example #26
0
File: mymem.c Project: thequux/pcb
/* ---------------------------------------------------------------------------
 * get next slot for a via, allocates memory if necessary
 */
PinTypePtr
GetViaMemory (DataTypePtr Data)
{
  PinTypePtr via = Data->Via;

  /* realloc new memory if necessary and clear it */
  if (Data->ViaN >= Data->ViaMax)
    {
      Data->ViaMax += STEP_VIA;
      if (Data->via_tree)
	r_destroy_tree (&Data->via_tree);
      via = (PinTypePtr)realloc (via, Data->ViaMax * sizeof (PinType));
      Data->Via = via;
      memset (via + Data->ViaN, 0, STEP_VIA * sizeof (PinType));
      Data->via_tree = r_create_tree (NULL, 0, 0);
      VIA_LOOP (Data);
      {
	r_insert_entry (Data->via_tree, (BoxType *) via, 0);
      }
      END_LOOP;
    }
  return (via + Data->ViaN++);
}
Example #27
0
File: mymem.c Project: thequux/pcb
/* ---------------------------------------------------------------------------
 * get next slot for a text object, allocates memory if necessary
 */
TextTypePtr
GetTextMemory (LayerTypePtr Layer)
{
  TextTypePtr text = Layer->Text;

  /* realloc new memory if necessary and clear it */
  if (Layer->TextN >= Layer->TextMax)
    {
      Layer->TextMax += STEP_TEXT;
      if (Layer->text_tree)
	r_destroy_tree (&Layer->text_tree);
      text = (TextTypePtr)realloc (text, Layer->TextMax * sizeof (TextType));
      Layer->Text = text;
      memset (text + Layer->TextN, 0, STEP_TEXT * sizeof (TextType));
      Layer->text_tree = r_create_tree (NULL, 0, 0);
      TEXT_LOOP (Layer);
      {
	r_insert_entry (Layer->text_tree, (BoxTypePtr) text, 0);
      }
      END_LOOP;
    }
  return (text + Layer->TextN++);
}
Example #28
0
File: mymem.c Project: thequux/pcb
/* ---------------------------------------------------------------------------
 * get next slot for an arc, allocates memory if necessary
 */
ArcTypePtr
GetArcMemory (LayerTypePtr Layer)
{
  ArcTypePtr arc = Layer->Arc;

  /* realloc new memory if necessary and clear it */
  if (Layer->ArcN >= Layer->ArcMax)
    {
      Layer->ArcMax += STEP_ARC;
      if (Layer->arc_tree)
	r_destroy_tree (&Layer->arc_tree);
      arc = (ArcTypePtr)realloc (arc, Layer->ArcMax * sizeof (ArcType));
      Layer->Arc = arc;
      memset (arc + Layer->ArcN, 0, STEP_ARC * sizeof (ArcType));
      Layer->arc_tree = r_create_tree (NULL, 0, 0);
      ARC_LOOP (Layer);
      {
	r_insert_entry (Layer->arc_tree, (BoxTypePtr) arc, 0);
      }
      END_LOOP;
    }
  return (arc + Layer->ArcN++);
}
Example #29
0
File: create.c Project: thequux/pcb
/* ---------------------------------------------------------------------------
 * creates a new via
 */
PinTypePtr
CreateNewVia (DataTypePtr Data,
	      LocationType X, LocationType Y,
	      BDimension Thickness, BDimension Clearance, BDimension Mask,
	      BDimension DrillingHole, char *Name, FlagType Flags)
{
  PinTypePtr Via;

  if (!be_lenient)
    {
      VIA_LOOP (Data);
      {
	if (SQUARE (via->X - X) + SQUARE (via->Y - Y) <=
	    SQUARE (via->DrillingHole / 2 + DrillingHole / 2)) 
	  {
	    Message (_("Dropping via at (%d, %d) because it's hole would overlap with the via "
		       "at (%d, %d)\n"), X/100, Y/100, via->X/100, via->Y/100);
	    return (NULL);		/* don't allow via stacking */
	  }
      }
      END_LOOP;
    }

  Via = GetViaMemory (Data);

  if (!Via)
    return (Via);
  /* copy values */
  Via->X = X;
  Via->Y = Y;
  Via->Thickness = Thickness;
  Via->Clearance = Clearance;
  Via->Mask = Mask;
  Via->DrillingHole = vendorDrillMap (DrillingHole);
  if (Via->DrillingHole != DrillingHole)
    {
      Message (_
	       ("Mapped via drill hole to %.2f mils from %.2f mils per vendor table\n"),
	       0.01 * Via->DrillingHole, 0.01 * DrillingHole);
    }

  Via->Name = STRDUP (Name);
  Via->Flags = Flags;
  CLEAR_FLAG (WARNFLAG, Via);
  SET_FLAG (VIAFLAG, Via);
  Via->ID = ID++;

  /* 
   * don't complain about MIN_PINORVIACOPPER on a mounting hole (pure
   * hole)
   */
  if (!TEST_FLAG (HOLEFLAG, Via) &&
      (Via->Thickness < Via->DrillingHole + MIN_PINORVIACOPPER))
    {
      Via->Thickness = Via->DrillingHole + MIN_PINORVIACOPPER;
      Message (_("Increased via thickness to %.2f mils to allow enough copper"
		 " at (%.2f,%.2f).\n"),
	       0.01 * Via->Thickness, 0.01 * Via->X, 0.01 * Via->Y);
    }

  SetPinBoundingBox (Via);
  if (!Data->via_tree)
    Data->via_tree = r_create_tree (NULL, 0, 0);
  r_insert_entry (Data->via_tree, (BoxTypePtr) Via, 0);
  return (Via);
}
Example #30
0
/* ---------------------------------------------------------------------------
 * Compute cost function.
 *  note that area overlap cost is correct for SMD devices: SMD devices on
 *  opposite sides of the board don't overlap.
 *
 * Algorithms follow those described in sections 4.1 of
 *  "Placement and Routing of Electronic Modules" edited by Michael Pecht
 *  Marcel Dekker, Inc. 1993.  ISBN: 0-8247-8916-4 TK7868.P7.P57 1993
 */
static double
ComputeCost (NetListTypePtr Nets, double T0, double T)
{
  double W = 0;			/* wire cost */
  double delta1 = 0;		/* wire congestion penalty function */
  double delta2 = 0;		/* module overlap penalty function */
  double delta3 = 0;		/* out of bounds penalty */
  double delta4 = 0;		/* alignment bonus */
  double delta5 = 0;		/* total area penalty */
  Cardinal i, j;
  LocationType minx, maxx, miny, maxy;
  bool allpads, allsameside;
  Cardinal thegroup;
  BoxListType bounds = { 0, 0, NULL };	/* save bounding rectangles here */
  BoxListType solderside = { 0, 0, NULL };	/* solder side component bounds */
  BoxListType componentside = { 0, 0, NULL };	/* component side bounds */
  /* make sure the NetList have the proper updated X and Y coords */
  UpdateXY (Nets);
  /* wire length term.  approximated by half-perimeter of minimum
   * rectangle enclosing the net.  Note that we penalize vias in
   * all-SMD nets by making the rectangle a cube and weighting
   * the "layer height" of the net. */
  for (i = 0; i < Nets->NetN; i++)
    {
      NetTypePtr n = &Nets->Net[i];
      if (n->ConnectionN < 2)
	continue;		/* no cost to go nowhere */
      minx = maxx = n->Connection[0].X;
      miny = maxy = n->Connection[0].Y;
      thegroup = n->Connection[0].group;
      allpads = (n->Connection[0].type == PAD_TYPE);
      allsameside = true;
      for (j = 1; j < n->ConnectionN; j++)
	{
	  ConnectionTypePtr c = &(n->Connection[j]);
	  MAKEMIN (minx, c->X);
	  MAKEMAX (maxx, c->X);
	  MAKEMIN (miny, c->Y);
	  MAKEMAX (maxy, c->Y);
	  if (c->type != PAD_TYPE)
	    allpads = false;
	  if (c->group != thegroup)
	    allsameside = false;
	}
      /* save bounding rectangle */
      {
	BoxTypePtr box = GetBoxMemory (&bounds);
	box->X1 = minx;
	box->Y1 = miny;
	box->X2 = maxx;
	box->Y2 = maxy;
      }
      /* okay, add half-perimeter to cost! */
      W += (maxx - minx) / 100 + (maxy - miny) / 100 +
	((allpads && !allsameside) ? CostParameter.via_cost : 0);
    }
  /* now compute penalty function Wc which is proportional to
   * amount of overlap and congestion. */
  /* delta1 is congestion penalty function */
  delta1 = CostParameter.congestion_penalty *
    sqrt (fabs (ComputeIntersectionArea (&bounds)));
#if 0
  printf ("Wire Congestion Area: %f\n", ComputeIntersectionArea (&bounds));
#endif
  /* free bounding rectangles */
  FreeBoxListMemory (&bounds);
  /* now collect module areas (bounding rect of pins/pads) */
  /* two lists for solder side / component side. */

  ELEMENT_LOOP (PCB->Data);
  {
    BoxListTypePtr thisside;
    BoxListTypePtr otherside;
    BoxTypePtr box;
    BoxTypePtr lastbox = NULL;
    BDimension thickness;
    BDimension clearance;
    if (TEST_FLAG (ONSOLDERFLAG, element))
      {
	thisside = &solderside;
	otherside = &componentside;
      }
    else
      {
	thisside = &componentside;
	otherside = &solderside;
      }
    box = GetBoxMemory (thisside);
    /* protect against elements with no pins/pads */
    if (element->PinN == 0 && element->PadN == 0)
      continue;
    /* initialize box so that it will take the dimensions of
     * the first pin/pad */
    box->X1 = MAX_COORD;
    box->Y1 = MAX_COORD;
    box->X2 = -MAX_COORD;
    box->Y2 = -MAX_COORD;
    PIN_LOOP (element);
    {
      thickness = pin->Thickness / 2;
      clearance = pin->Clearance * 2;
    EXPANDRECTXY (box,
		    pin->X - (thickness + clearance),
		    pin->Y - (thickness + clearance),
		    pin->X + (thickness + clearance),
		    pin->Y + (thickness + clearance))}
    END_LOOP;
    PAD_LOOP (element);
    {
      thickness = pad->Thickness / 2;
      clearance = pad->Clearance * 2;
    EXPANDRECTXY (box,
		    MIN (pad->Point1.X,
			   pad->Point2.X) - (thickness +
					       clearance),
		    MIN (pad->Point1.Y,
			   pad->Point2.Y) - (thickness +
					       clearance),
		    MAX (pad->Point1.X,
			   pad->Point2.X) + (thickness +
					       clearance),
		    MAX (pad->Point1.Y,
			   pad->Point2.Y) + (thickness + clearance))}
    END_LOOP;
    /* add a box for each pin to the "opposite side":
     * surface mount components can't sit on top of pins */
    if (!CostParameter.fast)
      PIN_LOOP (element);
    {
      box = GetBoxMemory (otherside);
      thickness = pin->Thickness / 2;
      clearance = pin->Clearance * 2;
      /* we ignore clearance here */
      /* (otherwise pins don't fit next to each other) */
      box->X1 = pin->X - thickness;
      box->Y1 = pin->Y - thickness;
      box->X2 = pin->X + thickness;
      box->Y2 = pin->Y + thickness;
      /* speed hack! coalesce with last box if we can */
      if (lastbox != NULL &&
	  ((lastbox->X1 == box->X1 &&
	    lastbox->X2 == box->X2 &&
	    MIN (abs (lastbox->Y1 - box->Y2),
		 abs (box->Y1 - lastbox->Y2)) <
	    clearance) || (lastbox->Y1 == box->Y1
			   && lastbox->Y2 == box->Y2
			   &&
			   MIN (abs
				(lastbox->X1 -
				 box->X2),
				abs (box->X1 - lastbox->X2)) < clearance)))
	{
	  EXPANDRECT (lastbox, box);
	  otherside->BoxN--;
	}
      else
	lastbox = box;
    }
    END_LOOP;
    /* assess out of bounds penalty */
    if (element->VBox.X1 < 0 ||
	element->VBox.Y1 < 0 ||
	element->VBox.X2 > PCB->MaxWidth || element->VBox.Y2 > PCB->MaxHeight)
      delta3 += CostParameter.out_of_bounds_penalty;
  }
  END_LOOP;
  /* compute intersection area of module areas box list */
  delta2 = sqrt (fabs (ComputeIntersectionArea (&solderside) +
		       ComputeIntersectionArea (&componentside))) *
    (CostParameter.overlap_penalty_min +
     (1 - (T / T0)) * CostParameter.overlap_penalty_max);
#if 0
  printf ("Module Overlap Area (solder): %f\n",
	  ComputeIntersectionArea (&solderside));
  printf ("Module Overlap Area (component): %f\n",
	  ComputeIntersectionArea (&componentside));
#endif
  FreeBoxListMemory (&solderside);
  FreeBoxListMemory (&componentside);
  /* reward pin/pad x/y alignment */
  /* score higher if pins/pads belong to same *type* of component */
  /* XXX: subkey should be *distance* from thing aligned with, so that
   * aligning to something far away isn't profitable */
  {
    /* create r tree */
    PointerListType seboxes = { 0, 0, NULL }
    , ceboxes =
    {
    0, 0, NULL};
    struct ebox
    {
      BoxType box;
      ElementTypePtr element;
    };
    direction_t dir[4] = { NORTH, EAST, SOUTH, WEST };
    struct ebox **boxpp, *boxp;
    rtree_t *rt_s, *rt_c;
    int factor;
    ELEMENT_LOOP (PCB->Data);
    {
      boxpp = (struct ebox **)
	GetPointerMemory (TEST_FLAG (ONSOLDERFLAG, element) ?
			  &seboxes : &ceboxes);
      *boxpp = malloc (sizeof (**boxpp));
      if (*boxpp == NULL ) 
	{
	  fprintf (stderr, "malloc() failed in %s\n", __FUNCTION__);
	  exit (1);
	}

      (*boxpp)->box = element->VBox;
      (*boxpp)->element = element;
    }
    END_LOOP;
    rt_s = r_create_tree ((const BoxType **) seboxes.Ptr, seboxes.PtrN, 1);
    rt_c = r_create_tree ((const BoxType **) ceboxes.Ptr, ceboxes.PtrN, 1);
    FreePointerListMemory (&seboxes);
    FreePointerListMemory (&ceboxes);
    /* now, for each element, find its neighbor on all four sides */
    delta4 = 0;
    for (i = 0; i < 4; i++)
      ELEMENT_LOOP (PCB->Data);
    {
      boxp = (struct ebox *)
	r_find_neighbor (TEST_FLAG (ONSOLDERFLAG, element) ?
			 rt_s : rt_c, &element->VBox, dir[i]);
      /* score bounding box alignments */
      if (!boxp)
	continue;
      factor = 1;
      if (element->Name[0].TextString &&
	  boxp->element->Name[0].TextString &&
	  0 == NSTRCMP (element->Name[0].TextString,
			boxp->element->Name[0].TextString))
	{
	  delta4 += CostParameter.matching_neighbor_bonus;
	  factor++;
	}
      if (element->Name[0].Direction == boxp->element->Name[0].Direction)
	delta4 += factor * CostParameter.oriented_neighbor_bonus;
      if (element->VBox.X1 ==
	  boxp->element->VBox.X1 ||
	  element->VBox.X1 ==
	  boxp->element->VBox.X2 ||
	  element->VBox.X2 ==
	  boxp->element->VBox.X1 ||
	  element->VBox.X2 ==
	  boxp->element->VBox.X2 ||
	  element->VBox.Y1 ==
	  boxp->element->VBox.Y1 ||
	  element->VBox.Y1 ==
	  boxp->element->VBox.Y2 ||
	  element->VBox.Y2 ==
	  boxp->element->VBox.Y1 ||
	  element->VBox.Y2 == boxp->element->VBox.Y2)
	delta4 += factor * CostParameter.aligned_neighbor_bonus;
    }
    END_LOOP;
    /* free k-d tree memory */
    r_destroy_tree (&rt_s);
    r_destroy_tree (&rt_c);
  }
  /* penalize total area used by this layout */
  {
    LocationType minX = MAX_COORD, minY = MAX_COORD;
    LocationType maxX = -MAX_COORD, maxY = -MAX_COORD;
    ELEMENT_LOOP (PCB->Data);
    {
      MAKEMIN (minX, element->VBox.X1);
      MAKEMIN (minY, element->VBox.Y1);
      MAKEMAX (maxX, element->VBox.X2);
      MAKEMAX (maxY, element->VBox.Y2);
    }
    END_LOOP;
    if (minX < maxX && minY < maxY)
      delta5 = CostParameter.overall_area_penalty *
	sqrt ((double) (maxX - minX) * (maxY - minY) * 0.0001);
  }
  if (T == 5)
    {
      T = W + delta1 + delta2 + delta3 - delta4 + delta5;
      printf ("cost components are %.3f %.3f %.3f %.3f %.3f %.3f\n",
	      W / T, delta1 / T, delta2 / T, delta3 / T, -delta4 / T,
	      delta5 / T);
    }
  /* done! */
  return W + (delta1 + delta2 + delta3 - delta4 + delta5);
}