Example #1
0
File: create.c Project: thequux/pcb
/* ---------------------------------------------------------------------------
 * creates a new line for an element
 */
LineTypePtr
CreateNewLineInElement (ElementTypePtr Element,
			LocationType X1, LocationType Y1,
			LocationType X2, LocationType Y2,
			BDimension Thickness)
{
  LineTypePtr line = Element->Line;

  if (Thickness == 0)
    return (NULL);
  /* realloc new memory if necessary and clear it */
  if (Element->LineN >= Element->LineMax)
    {
      Element->LineMax += STEP_ELEMENTLINE;
      line = (LineTypePtr)realloc (line, Element->LineMax * sizeof (LineType));
      Element->Line = line;
      memset (line + Element->LineN, 0, STEP_ELEMENTLINE * sizeof (LineType));
    }

  /* copy values */
  line = line + Element->LineN++;
  line->Point1.X = X1;
  line->Point1.Y = Y1;
  line->Point2.X = X2;
  line->Point2.Y = Y2;
  line->Thickness = Thickness;
  line->Flags = NoFlags ();
  line->ID = ID++;
  return (line);
}
Example #2
0
/*!
 * \brief Creates a new line for an element.
 */
LineType *
CreateNewLineInElement (ElementType *Element,
			Coord X1, Coord Y1,
			Coord X2, Coord Y2,
			Coord Thickness)
{
  LineType *line;

  if (Thickness == 0)
    return NULL;

  line = g_slice_new0 (LineType);
  Element->Line = g_list_append (Element->Line, line);
  Element->LineN ++;

  /* copy values */
  line->Point1.X = X1;
  line->Point1.Y = Y1;
  line->Point2.X = X2;
  line->Point2.Y = Y2;
  line->Thickness = Thickness;
  line->Flags = NoFlags ();
  line->ID = ID++;
  return line;
}
Example #3
0
/*!
 * \brief Creates a new line on a layer and checks for overlap and
 * extension.
 */
LineType *
CreateDrawnLineOnLayer (LayerType *Layer,
			Coord X1, Coord Y1,
			Coord X2, Coord Y2,
			Coord Thickness, Coord Clearance,
			FlagType Flags)
{
  struct line_info info;
  BoxType search;

  search.X1 = MIN (X1, X2);
  search.X2 = MAX (X1, X2);
  search.Y1 = MIN (Y1, Y2);
  search.Y2 = MAX (Y1, Y2);
  if (search.Y2 == search.Y1)
    search.Y2++;
  if (search.X2 == search.X1)
    search.X2++;
  info.X1 = X1;
  info.X2 = X2;
  info.Y1 = Y1;
  info.Y2 = Y2;
  info.Thickness = Thickness;
  info.Clearance = Clearance;
  info.Flags = Flags;
  info.test.Thickness = 0;
  info.test.Flags = NoFlags ();
  info.ans = NULL;
  /* prevent stacking of duplicate lines
   * and remove needless intermediate points
   * verify that the layer is on the board first!
   */
  if (setjmp (info.env) == 0)
    {
      r_search (Layer->line_tree, &search, NULL, line_callback, &info);
      return CreateNewLineOnLayer (Layer, X1, Y1, X2, Y2,
				   Thickness, Clearance, Flags);
    }

  if ((void *) info.ans == (void *) (-1))
    return NULL;		/* stacked line */
  /* remove unnecessary points */
  if (info.ans)
    {
      /* must do this BEFORE getting new line memory */
      MoveObjectToRemoveUndoList (LINE_TYPE, Layer, info.ans, info.ans);
      X1 = info.test.Point1.X;
      X2 = info.test.Point2.X;
      Y1 = info.test.Point1.Y;
      Y2 = info.test.Point2.Y;
    }
  return CreateNewLineOnLayer (Layer, X1, Y1, X2, Y2,
			       Thickness, Clearance, Flags);
}
Example #4
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 #5
0
static int
moveline_callback (const BoxType * b, void *cl)
{
  struct via_info *i = (struct via_info *) cl;
  PinTypePtr via;

  if ((via =
       CreateNewVia (PCB->Data, i->X, i->Y,
		     Settings.ViaThickness, 2 * Settings.Keepaway,
		     NOFLAG, Settings.ViaDrillingHole, NULL,
		     NoFlags ())) != NULL)
    {
      AddObjectToCreateUndoList (VIA_TYPE, via, via, via);
      DrawVia (via);
    }
  longjmp (i->env, 1);
}
Example #6
0
/* ---------------------------------------------------------------------------
 * checks if a line crosses a rectangle
 */
bool
IsLineInRectangle (Coord X1, Coord Y1, Coord X2, Coord Y2, LineTypePtr Line)
{
  LineType line;

  /* first, see if point 1 is inside the rectangle */
  /* in case the whole line is inside the rectangle */
  if (X1 < Line->Point1.X && X2 > Line->Point1.X &&
      Y1 < Line->Point1.Y && Y2 > Line->Point1.Y)
    return (true);
  /* construct a set of dummy lines and check each of them */
  line.Thickness = 0;
  line.Flags = NoFlags ();

  /* upper-left to upper-right corner */
  line.Point1.Y = line.Point2.Y = Y1;
  line.Point1.X = X1;
  line.Point2.X = X2;
  if (LineLineIntersect (&line, Line))
    return (true);

  /* upper-right to lower-right corner */
  line.Point1.X = X2;
  line.Point1.Y = Y1;
  line.Point2.Y = Y2;
  if (LineLineIntersect (&line, Line))
    return (true);

  /* lower-right to lower-left corner */
  line.Point1.Y = Y2;
  line.Point1.X = X1;
  line.Point2.X = X2;
  if (LineLineIntersect (&line, Line))
    return (true);

  /* lower-left to upper-left corner */
  line.Point2.X = X1;
  line.Point1.Y = Y1;
  line.Point2.Y = Y2;
  if (LineLineIntersect (&line, Line))
    return (true);

  return (false);
}
Example #7
0
static void
draw_pad_name (PadType *pad)
{
  BoxType box;
  bool vert;
  TextType text;

  if (!pad->Name || !pad->Name[0])
    text.TextString = EMPTY (pad->Number);
  else
    text.TextString = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? pad->Number : pad->Name);

  /* should text be vertical ? */
  vert = (pad->Point1.X == pad->Point2.X);

  if (vert)
    {
      box.X1 = pad->Point1.X                      - pad->Thickness / 2;
      box.Y1 = MAX (pad->Point1.Y, pad->Point2.Y) + pad->Thickness / 2;
      box.X1 += Settings.PinoutTextOffsetY;
      box.Y1 -= Settings.PinoutTextOffsetX;
    }
  else
    {
      box.X1 = MIN (pad->Point1.X, pad->Point2.X) - pad->Thickness / 2;
      box.Y1 = pad->Point1.Y                      - pad->Thickness / 2;
      box.X1 += Settings.PinoutTextOffsetX;
      box.Y1 += Settings.PinoutTextOffsetY;
    }

  gui->graphics->set_color (Output.fgGC, PCB->PinNameColor);

  text.Flags = NoFlags ();
  /* Set font height to approx 90% of pin thickness */
  text.Scale = 90 * pad->Thickness / FONT_CAPHEIGHT;
  text.X = box.X1;
  text.Y = box.Y1;
  text.Direction = vert ? 1 : 0;

  gui->graphics->draw_pcb_text (Output.fgGC, &text, 0);
}
Example #8
0
static void
_draw_pv_name (PinType *pv)
{
  BoxType box;
  bool vert;
  TextType text;

  if (!pv->Name || !pv->Name[0])
    text.TextString = EMPTY (pv->Number);
  else
    text.TextString = EMPTY (TEST_FLAG (SHOWNUMBERFLAG, PCB) ? pv->Number : pv->Name);

  vert = TEST_FLAG (EDGE2FLAG, pv);

  if (vert)
    {
      box.X1 = pv->X - pv->Thickness    / 2 + Settings.PinoutTextOffsetY;
      box.Y1 = pv->Y - pv->DrillingHole / 2 - Settings.PinoutTextOffsetX;
    }
  else
    {
      box.X1 = pv->X + pv->DrillingHole / 2 + Settings.PinoutTextOffsetX;
      box.Y1 = pv->Y - pv->Thickness    / 2 + Settings.PinoutTextOffsetY;
    }

  gui->graphics->set_color (Output.fgGC, PCB->PinNameColor);

  text.Flags = NoFlags ();
  /* Set font height to approx 56% of pin thickness */
  text.Scale = 56 * pv->Thickness / FONT_CAPHEIGHT;
  text.X = box.X1;
  text.Y = box.Y1;
  text.Direction = vert ? 1 : 0;

  if (gui->gui)
    doing_pinout++;
  gui->graphics->draw_pcb_text (Output.fgGC, &text, 0);
  if (gui->gui)
    doing_pinout--;
}
Example #9
0
/* ---------------------------------------------------------------------------
 * checks if an arc crosses a square
 */
bool
IsArcInRectangle (Coord X1, Coord Y1, Coord X2, Coord Y2, ArcTypePtr Arc)
{
  LineType line;

  /* construct a set of dummy lines and check each of them */
  line.Thickness = 0;
  line.Flags = NoFlags ();

  /* upper-left to upper-right corner */
  line.Point1.Y = line.Point2.Y = Y1;
  line.Point1.X = X1;
  line.Point2.X = X2;
  if (LineArcIntersect (&line, Arc))
    return (true);

  /* upper-right to lower-right corner */
  line.Point1.X = line.Point2.X = X2;
  line.Point1.Y = Y1;
  line.Point2.Y = Y2;
  if (LineArcIntersect (&line, Arc))
    return (true);

  /* lower-right to lower-left corner */
  line.Point1.Y = line.Point2.Y = Y2;
  line.Point1.X = X1;
  line.Point2.X = X2;
  if (LineArcIntersect (&line, Arc))
    return (true);

  /* lower-left to upper-left corner */
  line.Point1.X = line.Point2.X = X1;
  line.Point1.Y = Y1;
  line.Point2.Y = Y2;
  if (LineArcIntersect (&line, Arc))
    return (true);

  return (false);
}
Example #10
0
/* ---------------------------------------------------------------------------
 * checks if a line crosses a quadrangle: almost copied from IsLineInRectangle()
 * Note: actually this quadrangle is a slanted rectangle
 */
bool
IsLineInQuadrangle (PointType p[4], LineTypePtr Line)
{
  LineType line;

  /* first, see if point 1 is inside the rectangle */
  /* in case the whole line is inside the rectangle */
  if (IsPointInQuadrangle(p,&(Line->Point1)))
    return true;
  if (IsPointInQuadrangle(p,&(Line->Point2)))
    return true;
  /* construct a set of dummy lines and check each of them */
  line.Thickness = 0;
  line.Flags = NoFlags ();

  /* upper-left to upper-right corner */
  line.Point1.X = p[0].X; line.Point1.Y = p[0].Y;
  line.Point2.X = p[1].X; line.Point2.Y = p[1].Y;
  if (LineLineIntersect (&line, Line))
    return (true);

  /* upper-right to lower-right corner */
  line.Point1.X = p[2].X; line.Point1.Y = p[2].Y;
  if (LineLineIntersect (&line, Line))
    return (true);

  /* lower-right to lower-left corner */
  line.Point2.X = p[3].X; line.Point2.Y = p[3].Y;
  if (LineLineIntersect (&line, Line))
    return (true);

  /* lower-left to upper-left corner */
  line.Point1.X = p[0].X; line.Point1.Y = p[0].Y;
  if (LineLineIntersect (&line, Line))
    return (true);

  return (false);
}
Example #11
0
static int
FontEdit (int argc, char **argv, int Ux, int Uy)
{
  FontType *font;
  SymbolType *symbol;
  LayerTypePtr lfont, lorig, lwidth, lgrid;
  int s, l;

  if (hid_actionl ("New", "Font", 0))
    return 1;

  while (PCB->Data->LayerN > 4)
    MoveLayer (4, -1);
  for (l = 0; l < 4; l++)
    {
      MoveLayerToGroup (l, l);
    }
  PCB->MaxWidth = CELL_SIZE * 18;
  PCB->MaxHeight = CELL_SIZE * ((MAX_FONTPOSITION + 15) / 16 + 2);
  PCB->Grid = 500.0;
  PCB->Data->Layer[0].Name = MyStrdup ("Font", "FontEdit");
  PCB->Data->Layer[1].Name = MyStrdup ("OrigFont", "FontEdit");
  PCB->Data->Layer[2].Name = MyStrdup ("Width", "FontEdit");
  PCB->Data->Layer[3].Name = MyStrdup ("Grid", "FontEdit");
  hid_action ("PCBChanged");
  hid_action ("LayersChanged");

  lfont = PCB->Data->Layer + 0;
  lorig = PCB->Data->Layer + 1;
  lwidth = PCB->Data->Layer + 2;
  lgrid = PCB->Data->Layer + 3;

  font = &PCB->Font;
  for (s = 0; s <= MAX_FONTPOSITION; s++)
    {
      int ox = (s % 16 + 1) * CELL_SIZE;
      int oy = (s / 16 + 1) * CELL_SIZE;
      int w, miny, maxy, maxx = 0;

      symbol = &font->Symbol[s];

      miny = 500;
      maxy = font->MaxHeight;

      for (l = 0; l < symbol->LineN; l++)
	{
	  CreateDrawnLineOnLayer (lfont,
				  symbol->Line[l].Point1.X + ox,
				  symbol->Line[l].Point1.Y + oy,
				  symbol->Line[l].Point2.X + ox,
				  symbol->Line[l].Point2.Y + oy,
				  symbol->Line[l].Thickness,
				  symbol->Line[l].Thickness, NoFlags ());
	  CreateDrawnLineOnLayer (lorig, symbol->Line[l].Point1.X + ox,
				  symbol->Line[l].Point1.Y + oy,
				  symbol->Line[l].Point2.X + ox,
				  symbol->Line[l].Point2.Y + oy,
				  symbol->Line[l].Thickness,
				  symbol->Line[l].Thickness, NoFlags ());
	  if (maxx < symbol->Line[l].Point1.X)
	    maxx = symbol->Line[l].Point1.X;
	  if (maxx < symbol->Line[l].Point2.X)
	    maxx = symbol->Line[l].Point2.X;
	}
      w = maxx + symbol->Delta + ox;
      CreateDrawnLineOnLayer (lwidth,
			      w, miny + oy,
			      w, maxy + oy, 100, 100, NoFlags ());
    }

  for (l = 0; l < 16; l++)
    {
      int x = (l + 1) * CELL_SIZE;
      CreateDrawnLineOnLayer (lgrid, x, 0, x, PCB->MaxHeight, 100, 100,
			      NoFlags ());
    }
  for (l = 0; l <= MAX_FONTPOSITION / 16 + 1; l++)
    {
      int y = (l + 1) * CELL_SIZE;
      CreateDrawnLineOnLayer (lgrid, 0, y, PCB->MaxWidth, y, 100, 100,
			      NoFlags ());
    }
  return 0;
}
Example #12
0
static float
drc_lines (PointTypePtr end, bool way)
{
  float f, s, f2, s2, len, best;
  LocationType dx, dy, temp, last, length;
  LocationType temp2, last2, length2;
  LineType line1, line2;
  Cardinal group, comp;
  struct drc_info info;
  bool two_lines, x_is_long, blocker;
  PointType ans;

  f = 1.0;
  s = 0.5;
  last = -1;
  line1.Flags = line2.Flags = NoFlags ();
  line1.Thickness = Settings.LineThickness + 2 * (PCB->Bloat + 1);
  line2.Thickness = line1.Thickness;
  line1.Clearance = line2.Clearance = 0;
  line1.Point1.X = Crosshair.AttachedLine.Point1.X;
  line1.Point1.Y = Crosshair.AttachedLine.Point1.Y;
  dy = end->Y - line1.Point1.Y;
  dx = end->X - line1.Point1.X;
  if (abs (dx) > abs (dy))
    {
      x_is_long = true;
      length = abs (dx);
    }
  else
    {
      x_is_long = false;
      length = abs (dy);
    }
  group = GetGroupOfLayer (INDEXOFCURRENT);
  comp = max_group + 10;	/* this out-of-range group might save a call */
  if (GetLayerGroupNumberByNumber (solder_silk_layer) == group)
    info.solder = true;
  else
    {
      info.solder = false;
      comp = GetLayerGroupNumberByNumber (component_silk_layer);
    }
  temp = length;
  /* assume the worst */
  best = 0.0;
  ans.X = line1.Point1.X;
  ans.Y = line1.Point1.Y;
  while (length != last)
    {
      last = length;
      if (x_is_long)
	{
	  dx = SGN (dx) * length;
	  dy = end->Y - line1.Point1.Y;
	  length2 = abs (dy);
	}
      else
	{
	  dy = SGN (dy) * length;
	  dx = end->X - line1.Point1.X;
	  length2 = abs (dx);
	}
      temp2 = length2;
      f2 = 1.0;
      s2 = 0.5;
      last2 = -1;
      blocker = true;
      while (length2 != last2)
	{
	  if (x_is_long)
	    dy = SGN (dy) * length2;
	  else
	    dx = SGN (dx) * length2;
	  two_lines = true;
	  if (abs (dx) > abs (dy) && x_is_long)
	    {
	      line1.Point2.X = line1.Point1.X +
		(way ? SGN (dx) * abs (dy) : dx - SGN (dx) * abs (dy));
	      line1.Point2.Y = line1.Point1.Y + (way ? dy : 0);
	    }
	  else if (abs (dy) >= abs (dx) && !x_is_long)
	    {
	      line1.Point2.X = line1.Point1.X + (way ? dx : 0);
	      line1.Point2.Y = line1.Point1.Y +
		(way ? SGN (dy) * abs (dx) : dy - SGN (dy) * abs (dx));
	    }
	  else if (x_is_long)
	    {
	      /* we've changed which axis is long, so only do one line */
	      line1.Point2.X = line1.Point1.X + dx;
	      line1.Point2.Y =
		line1.Point1.Y + (way ? SGN (dy) * abs (dx) : 0);
	      two_lines = false;
	    }
	  else
	    {
	      /* we've changed which axis is long, so only do one line */
	      line1.Point2.Y = line1.Point1.Y + dy;
	      line1.Point2.X =
		line1.Point1.X + (way ? SGN (dx) * abs (dy) : 0);
	      two_lines = false;
	    }
	  line2.Point1.X = line1.Point2.X;
	  line2.Point1.Y = line1.Point2.Y;
	  if (!two_lines)
	    {
	      line2.Point2.Y = line1.Point2.Y;
	      line2.Point2.X = line1.Point2.X;
	    }
	  else
	    {
	      line2.Point2.X = line1.Point1.X + dx;
	      line2.Point2.Y = line1.Point1.Y + dy;
	    }
	  SetLineBoundingBox (&line1);
	  SetLineBoundingBox (&line2);
	  last2 = length2;
	  if (setjmp (info.env) == 0)
	    {
	      info.line = &line1;
	      r_search (PCB->Data->via_tree, &line1.BoundingBox, NULL,
			drcVia_callback, &info);
	      r_search (PCB->Data->pin_tree, &line1.BoundingBox, NULL,
			drcVia_callback, &info);
	      if (info.solder || comp == group)
		r_search (PCB->Data->pad_tree, &line1.BoundingBox, NULL,
			  drcPad_callback, &info);
	      if (two_lines)
		{
		  info.line = &line2;
		  r_search (PCB->Data->via_tree, &line2.BoundingBox, NULL,
			    drcVia_callback, &info);
		  r_search (PCB->Data->pin_tree, &line2.BoundingBox, NULL,
			    drcVia_callback, &info);
		  if (info.solder || comp == group)
		    r_search (PCB->Data->pad_tree, &line2.BoundingBox, NULL,
			      drcPad_callback, &info);
		}
	      GROUP_LOOP (PCB->Data, group);
	      {
		info.line = &line1;
		r_search (layer->line_tree, &line1.BoundingBox, NULL,
			  drcLine_callback, &info);
		r_search (layer->arc_tree, &line1.BoundingBox, NULL,
			  drcArc_callback, &info);
		if (two_lines)
		  {
		    info.line = &line2;
		    r_search (layer->line_tree, &line2.BoundingBox,
			      NULL, drcLine_callback, &info);
		    r_search (layer->arc_tree, &line2.BoundingBox,
			      NULL, drcArc_callback, &info);
		  }
	      }
	      END_LOOP;
	      /* no intersector! */
	      blocker = false;
	      f2 += s2;
	      len = (line2.Point2.X - line1.Point1.X);
	      len *= len;
	      len += (float) (line2.Point2.Y - line1.Point1.Y) *
		(line2.Point2.Y - line1.Point1.Y);
	      if (len > best)
		{
		  best = len;
		  ans.X = line2.Point2.X;
		  ans.Y = line2.Point2.Y;
		}
#if 0
	      if (f2 > 1.0)
		f2 = 0.5;
#endif
	    }
	  else
	    {
	      /* bumped into something, back off */
	      f2 -= s2;
	    }
	  s2 *= 0.5;
	  length2 = MIN (f2 * temp2, temp2);
	}
      if (!blocker && ((x_is_long && line2.Point2.X - line1.Point1.X == dx)
		       || (!x_is_long
			   && line2.Point2.Y - line1.Point1.Y == dy)))
	f += s;
      else
	f -= s;
      s *= 0.5;
      length = MIN (f * temp, temp);
    }

  end->X = ans.X;
  end->Y = ans.Y;
  return best;
}
Example #13
0
/* ---------------------------------------------------------------------------
 * draws additional stuff that follows the crosshair
 */
void
DrawAttached (void)
{
    switch (Settings.Mode)
    {
    case VIA_MODE:
    {
        /* Make a dummy via structure to draw from */
        PinType via;
        via.X = Crosshair.X;
        via.Y = Crosshair.Y;
        via.Thickness = Settings.ViaThickness;
        via.Clearance = 2 * Settings.Keepaway;
        via.DrillingHole = Settings.ViaDrillingHole;
        via.Mask = 0;
        via.Flags = NoFlags ();

        gui->thindraw_pcb_pv (Crosshair.GC, Crosshair.GC, &via, true, false);

        if (TEST_FLAG (SHOWDRCFLAG, PCB))
        {
            /* XXX: Naughty cheat - use the mask to draw DRC clearance! */
            via.Mask = Settings.ViaThickness + PCB->Bloat * 2;
            gui->set_color (Crosshair.GC, Settings.CrossColor);
            gui->thindraw_pcb_pv (Crosshair.GC, Crosshair.GC, &via, false, true);
            gui->set_color (Crosshair.GC, Settings.CrosshairColor);
        }
        break;
    }

    /* the attached line is used by both LINEMODE, POLYGON_MODE and POLYGONHOLE_MODE*/
    case POLYGON_MODE:
    case POLYGONHOLE_MODE:
        /* draw only if starting point is set */
        if (Crosshair.AttachedLine.State != STATE_FIRST)
            gui->draw_line (Crosshair.GC,
                            Crosshair.AttachedLine.Point1.X,
                            Crosshair.AttachedLine.Point1.Y,
                            Crosshair.AttachedLine.Point2.X,
                            Crosshair.AttachedLine.Point2.Y);

        /* draw attached polygon only if in POLYGON_MODE or POLYGONHOLE_MODE */
        if (Crosshair.AttachedPolygon.PointN > 1)
        {
            XORPolygon (&Crosshair.AttachedPolygon, 0, 0);
        }
        break;

    case ARC_MODE:
        if (Crosshair.AttachedBox.State != STATE_FIRST)
        {
            XORDrawAttachedArc (Settings.LineThickness);
            if (TEST_FLAG (SHOWDRCFLAG, PCB))
            {
                gui->set_color (Crosshair.GC, Settings.CrossColor);
                XORDrawAttachedArc (Settings.LineThickness +
                                    2 * (PCB->Bloat + 1));
                gui->set_color (Crosshair.GC, Settings.CrosshairColor);
            }

        }
        break;

    case LINE_MODE:
        /* draw only if starting point exists and the line has length */
        if (Crosshair.AttachedLine.State != STATE_FIRST &&
                Crosshair.AttachedLine.draw)
        {
            XORDrawAttachedLine (Crosshair.AttachedLine.Point1.X,
                                 Crosshair.AttachedLine.Point1.Y,
                                 Crosshair.AttachedLine.Point2.X,
                                 Crosshair.AttachedLine.Point2.Y,
                                 PCB->RatDraw ? 10 : Settings.LineThickness);
            /* draw two lines ? */
            if (PCB->Clipping)
                XORDrawAttachedLine (Crosshair.AttachedLine.Point2.X,
                                     Crosshair.AttachedLine.Point2.Y,
                                     Crosshair.X, Crosshair.Y,
                                     PCB->RatDraw ? 10 : Settings.LineThickness);
            if (TEST_FLAG (SHOWDRCFLAG, PCB))
            {
                gui->set_color (Crosshair.GC, Settings.CrossColor);
                XORDrawAttachedLine (Crosshair.AttachedLine.Point1.X,
                                     Crosshair.AttachedLine.Point1.Y,
                                     Crosshair.AttachedLine.Point2.X,
                                     Crosshair.AttachedLine.Point2.Y,
                                     PCB->RatDraw ? 10 : Settings.LineThickness
                                     + 2 * (PCB->Bloat + 1));
                if (PCB->Clipping)
                    XORDrawAttachedLine (Crosshair.AttachedLine.Point2.X,
                                         Crosshair.AttachedLine.Point2.Y,
                                         Crosshair.X, Crosshair.Y,
                                         PCB->RatDraw ? 10 : Settings.
                                         LineThickness + 2 * (PCB->Bloat + 1));
                gui->set_color (Crosshair.GC, Settings.CrosshairColor);
            }
        }
        break;

    case PASTEBUFFER_MODE:
        XORDrawBuffer (PASTEBUFFER);
        break;

    case COPY_MODE:
    case MOVE_MODE:
        XORDrawMoveOrCopyObject ();
        break;

    case INSERTPOINT_MODE:
        XORDrawInsertPointObject ();
        break;
    }

    /* an attached box does not depend on a special mode */
    if (Crosshair.AttachedBox.State == STATE_SECOND ||
            Crosshair.AttachedBox.State == STATE_THIRD)
    {
        Coord x1, y1, x2, y2;

        x1 = Crosshair.AttachedBox.Point1.X;
        y1 = Crosshair.AttachedBox.Point1.Y;
        x2 = Crosshair.AttachedBox.Point2.X;
        y2 = Crosshair.AttachedBox.Point2.Y;
        gui->draw_rect (Crosshair.GC, x1, y1, x2, y2);
    }
}
Example #14
0
/*---------------------------------------------------------------------------
 *
 * break buffer element into pieces
 */
bool
SmashBufferElement (BufferType *Buffer)
{
  ElementType *element;
  Cardinal group;
  LayerType *clayer, *slayer;

  if (Buffer->Data->ElementN != 1)
    {
      Message (_("Error!  Buffer doesn't contain a single element\n"));
      return (false);
    }
  /*
   * At this point the buffer should contain just a single element.
   * Now we detach the single element from the buffer and then clear the
   * buffer, ready to receive the smashed elements.  As a result of detaching
   * it the single element is orphaned from the buffer and thus will not be
   * free()'d by FreeDataMemory (called via ClearBuffer).  This leaves it
   * around for us to smash bits off it.  It then becomes our responsibility,
   * however, to free the single element when we're finished with it.
   */
  element = Buffer->Data->Element->data;
  Buffer->Data->Element = NULL;
  Buffer->Data->ElementN = 0;
  ClearBuffer (Buffer);
  ELEMENTLINE_LOOP (element);
  {
    CreateNewLineOnLayer (&Buffer->Data->SILKLAYER,
			  line->Point1.X, line->Point1.Y,
			  line->Point2.X, line->Point2.Y,
			  line->Thickness, 0, NoFlags ());
    if (line)
      line->Number = STRDUP (NAMEONPCB_NAME (element));
  }
  END_LOOP;
  ARC_LOOP (element);
  {
    CreateNewArcOnLayer (&Buffer->Data->SILKLAYER,
			 arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle,
			 arc->Delta, arc->Thickness, 0, NoFlags ());
  }
  END_LOOP;
  PIN_LOOP (element);
  {
    FlagType f = NoFlags ();
    AddFlags (f, VIAFLAG);
    if (TEST_FLAG (HOLEFLAG, pin))
      AddFlags (f, HOLEFLAG);

    CreateNewVia (Buffer->Data, pin->X, pin->Y,
		  pin->Thickness, pin->Clearance, pin->Mask,
		  pin->DrillingHole, pin->Number, f);
  }
  END_LOOP;
  group =
    GetLayerGroupNumberByNumber (SWAP_IDENT ? solder_silk_layer :
					      component_silk_layer);
  clayer = &Buffer->Data->Layer[PCB->LayerGroups.Entries[group][0]];
  group =
    GetLayerGroupNumberByNumber (SWAP_IDENT ? component_silk_layer :
					      solder_silk_layer);
  slayer = &Buffer->Data->Layer[PCB->LayerGroups.Entries[group][0]];
  PAD_LOOP (element);
  {
    LineType *line;
    line = CreateNewLineOnLayer (TEST_FLAG (ONSOLDERFLAG, pad) ? slayer : clayer,
				 pad->Point1.X, pad->Point1.Y,
				 pad->Point2.X, pad->Point2.Y,
				 pad->Thickness, pad->Clearance, NoFlags ());
    if (line)
      line->Number = STRDUP (pad->Number);
  }
  END_LOOP;
  FreeElementMemory (element);
  g_slice_free (ElementType, element);
  return (true);
}
Example #15
0
/* ThermPoly returns a POLYAREA having all of the clearance that when
 * subtracted from the plane create the desired thermal fingers.
 * Usually this is 4 disjoint regions.
 *
 */
POLYAREA *
ThermPoly (PCBTypePtr p, PinTypePtr pin, Cardinal laynum)
{
  ArcType a;
  POLYAREA *pa, *arc;
  Cardinal style = GET_THERM (laynum, pin);

  if (style == 3)
    return NULL;                /* solid connection no clearance */
  pcb = p;
  if (TEST_FLAG (SQUAREFLAG, pin))
    return square_therm (pin, style);
  if (TEST_FLAG (OCTAGONFLAG, pin))
    return oct_therm (pin, style);
  /* must be circular */
  switch (style)
    {
    case 1:
    case 2:
      {
        POLYAREA *m;
        Coord t = (pin->Thickness + pin->Clearance) / 2;
        Coord w = 0.5 * pcb->ThermScale * pin->Clearance;
        pa = CirclePoly (pin->X, pin->Y, t);
        arc = CirclePoly (pin->X, pin->Y, pin->Thickness / 2);
        /* create a thin ring */
        poly_Boolean_free (pa, arc, &m, PBO_SUB);
        /* fix me needs error checking */
        if (style == 2)
          {
            /* t is the theoretically required length, but we use twice that
             * to avoid descritisation errors in our circle approximation.
             */
            pa = RectPoly (pin->X - t * 2, pin->X + t * 2, pin->Y - w, pin->Y + w);
            poly_Boolean_free (m, pa, &arc, PBO_SUB);
            pa = RectPoly (pin->X - w, pin->X + w, pin->Y - t * 2, pin->Y + t * 2);
          }
        else
          {
            /* t is the theoretically required length, but we use twice that
             * to avoid descritisation errors in our circle approximation.
             */
            pa = diag_line (pin->X, pin->Y, t * 2, w, true);
            poly_Boolean_free (m, pa, &arc, PBO_SUB);
            pa = diag_line (pin->X, pin->Y, t * 2, w, false);
          }
        poly_Boolean_free (arc, pa, &m, PBO_SUB);
        return m;
      }


    default:
      a.X = pin->X;
      a.Y = pin->Y;
      a.Height = a.Width = pin->Thickness / 2 + pin->Clearance / 4;
      a.Thickness = 1;
      a.Clearance = pin->Clearance / 2;
      a.Flags = NoFlags ();
      a.Delta =
        90 -
        (a.Clearance * (1. + 2. * pcb->ThermScale) * 180) / (M_PI * a.Width);
      a.StartAngle = 90 - a.Delta / 2 + (style == 4 ? 0 : 45);
      pa = ArcPoly (&a, a.Clearance);
      if (!pa)
        return NULL;
      a.StartAngle += 90;
      arc = ArcPoly (&a, a.Clearance);
      if (!arc)
        return NULL;
      pa->f = arc;
      arc->b = pa;
      a.StartAngle += 90;
      arc = ArcPoly (&a, a.Clearance);
      if (!arc)
        return NULL;
      pa->f->f = arc;
      arc->b = pa->f;
      a.StartAngle += 90;
      arc = ArcPoly (&a, a.Clearance);
      if (!arc)
        return NULL;
      pa->b = arc;
      pa->f->f->f = arc;
      arc->b = pa->f->f;
      arc->f = pa;
      pa->b = arc;
      return pa;
    }
}
Example #16
0
static POLYAREA *
square_therm (PinTypePtr pin, Cardinal style)
{
  POLYAREA *p, *p2;
  PLINE *c;
  Vector v;
  Coord d, in, out;

  switch (style)
    {
    case 1:
      d = pcb->ThermScale * pin->Clearance * M_SQRT1_2;
      out = (pin->Thickness + pin->Clearance) / 2;
      in = pin->Thickness / 2;
      /* top (actually bottom since +y is down) */
      v[0] = pin->X - in + d;
      v[1] = pin->Y + in;
      if ((c = poly_NewContour (v)) == NULL)
        return NULL;
      v[0] = pin->X + in - d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      v[0] = pin->X + out - d;
      v[1] = pin->Y + out;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      v[0] = pin->X - out + d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      p = ContourToPoly (c);
      /* right */
      v[0] = pin->X + in;
      v[1] = pin->Y + in - d;
      if ((c = poly_NewContour (v)) == NULL)
        return NULL;
      v[1] = pin->Y - in + d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      v[0] = pin->X + out;
      v[1] = pin->Y - out + d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      v[1] = pin->Y + out - d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      p2 = ContourToPoly (c);
      p->f = p2;
      p2->b = p;
      /* left */
      v[0] = pin->X - in;
      v[1] = pin->Y - in + d;
      if ((c = poly_NewContour (v)) == NULL)
        return NULL;
      v[1] = pin->Y + in - d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      v[0] = pin->X - out;
      v[1] = pin->Y + out - d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      v[1] = pin->Y - out + d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      p2 = ContourToPoly (c);
      p->f->f = p2;
      p2->b = p->f;
      /* bottom (actually top since +y is down) */
      v[0] = pin->X + in - d;
      v[1] = pin->Y - in;
      if ((c = poly_NewContour (v)) == NULL)
        return NULL;
      v[0] = pin->X - in + d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      v[0] = pin->X - out + d;
      v[1] = pin->Y - out;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      v[0] = pin->X + out - d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      p2 = ContourToPoly (c);
      p->f->f->f = p2;
      p2->f = p;
      p2->b = p->f->f;
      p->b = p2;
      return p;
    case 4:
      {
        LineType l;
        l.Flags = NoFlags ();
        d = pin->Thickness / 2 - pcb->ThermScale * pin->Clearance;
        out = pin->Thickness / 2 + pin->Clearance / 4;
        in = pin->Clearance / 2;
        /* top */
        l.Point1.X = pin->X - d;
        l.Point2.Y = l.Point1.Y = pin->Y + out;
        l.Point2.X = pin->X + d;
        p = LinePoly (&l, in);
        /* right */
        l.Point1.X = l.Point2.X = pin->X + out;
        l.Point1.Y = pin->Y - d;
        l.Point2.Y = pin->Y + d;
        p2 = LinePoly (&l, in);
        p->f = p2;
        p2->b = p;
        /* bottom */
        l.Point1.X = pin->X - d;
        l.Point2.Y = l.Point1.Y = pin->Y - out;
        l.Point2.X = pin->X + d;
        p2 = LinePoly (&l, in);
        p->f->f = p2;
        p2->b = p->f;
        /* left */
        l.Point1.X = l.Point2.X = pin->X - out;
        l.Point1.Y = pin->Y - d;
        l.Point2.Y = pin->Y + d;
        p2 = LinePoly (&l, in);
        p->f->f->f = p2;
        p2->b = p->f->f;
        p->b = p2;
        p2->f = p;
        return p;
      }
    default:                   /* style 2 and 5 */
      d = 0.5 * pcb->ThermScale * pin->Clearance;
      if (style == 5)
        d += d;
      out = (pin->Thickness + pin->Clearance) / 2;
      in = pin->Thickness / 2;
      /* topright */
      v[0] = pin->X + in;
      v[1] = pin->Y + in;
      if ((c = poly_NewContour (v)) == NULL)
        return NULL;
      v[1] = pin->Y + d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      if (style == 2)
        {
          v[0] = pin->X + out;
          poly_InclVertex (c->head.prev, poly_CreateNode (v));
        }
      else
        frac_circle (c, v[0] + pin->Clearance / 4, v[1], v, 2);
      v[1] = pin->Y + in;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      /* pivot 1/4 circle to next point */
      frac_circle (c, pin->X + in, pin->Y + in, v, 4);
      v[0] = pin->X + d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      if (style == 2)
        {
          poly_InclVertex (c->head.prev, poly_CreateNode (v));
          v[1] = pin->Y + in;
          poly_InclVertex (c->head.prev, poly_CreateNode (v));
        }
      else
        frac_circle (c, v[0], v[1] - pin->Clearance / 4, v, 2);
      p = ContourToPoly (c);
      /* bottom right */
      v[0] = pin->X + in;
      v[1] = pin->Y - d;
      if ((c = poly_NewContour (v)) == NULL)
        return NULL;
      v[1] = pin->Y - in;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      v[0] = pin->X + d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      if (style == 2)
        {
          v[1] = pin->Y - out;
          poly_InclVertex (c->head.prev, poly_CreateNode (v));
        }
      else
        frac_circle (c, v[0], v[1] - pin->Clearance / 4, v, 2);
      v[0] = pin->X + in;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      /* pivot 1/4 circle to next point */
      frac_circle (c, pin->X + in, pin->Y - in, v, 4);
      v[1] = pin->Y - d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      if (style == 5)
        frac_circle (c, v[0] - pin->Clearance / 4, v[1], v, 2);
      p2 = ContourToPoly (c);
      p->f = p2;
      p2->b = p;
      /* bottom left */
      v[0] = pin->X - d;
      v[1] = pin->Y - in;
      if ((c = poly_NewContour (v)) == NULL)
        return NULL;
      v[0] = pin->X - in;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      v[1] = pin->Y - d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      if (style == 2)
        {
          v[0] = pin->X - out;
          poly_InclVertex (c->head.prev, poly_CreateNode (v));
        }
      else
        frac_circle (c, v[0] - pin->Clearance / 4, v[1], v, 2);
      v[1] = pin->Y - in;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      /* pivot 1/4 circle to next point */
      frac_circle (c, pin->X - in, pin->Y - in, v, 4);
      v[0] = pin->X - d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      if (style == 5)
        frac_circle (c, v[0], v[1] + pin->Clearance / 4, v, 2);
      p2 = ContourToPoly (c);
      p->f->f = p2;
      p2->b = p->f;
      /* top left */
      v[0] = pin->X - d;
      v[1] = pin->Y + out;
      if ((c = poly_NewContour (v)) == NULL)
        return NULL;
      v[0] = pin->X - in;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      /* pivot 1/4 circle to next point (x-out, y+in) */
      frac_circle (c, pin->X - in, pin->Y + in, v, 4);
      v[1] = pin->Y + d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      if (style == 2)
        {
          v[0] = pin->X - in;
          poly_InclVertex (c->head.prev, poly_CreateNode (v));
        }
      else
        frac_circle (c, v[0] + pin->Clearance / 4, v[1], v, 2);
      v[1] = pin->Y + in;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      v[0] = pin->X - d;
      poly_InclVertex (c->head.prev, poly_CreateNode (v));
      if (style == 5)
        frac_circle (c, v[0], v[1] + pin->Clearance / 4, v, 2);
      p2 = ContourToPoly (c);
      p->f->f->f = p2;
      p2->f = p;
      p2->b = p->f->f;
      p->b = p2;
      return p;
    }
}
Example #17
0
static int
FontEdit (int argc, char **argv, Coord Ux, Coord Uy) {
    FontType *font;
    SymbolType *symbol;
    LayerType *lfont, *lorig, *lwidth, *lgrid;
    int s, l;

    if (hid_actionl ("New", "Font", 0)) {
        return 1;
    }

    Settings.grid_unit = get_unit_struct("mil");
    Settings.Bloat = PCB->Bloat = 1;
    Settings.Shrink = PCB->Shrink = 1;
    Settings.minWid = PCB->minWid = 1;
    Settings.minSlk = PCB->minSlk = 1;
    MoveLayerToGroup (max_copper_layer + TOP_SILK_LAYER, 0);
    MoveLayerToGroup (max_copper_layer + BOTTOM_SILK_LAYER, 1);

    while (PCB->Data->LayerN > 4) {
        MoveLayer (4, -1);
    }

    for (l = 0; l < 4; l++) {
        MoveLayerToGroup (l, l);
    }

    PCB->MaxWidth = CELL_SIZE * 18;
    PCB->MaxHeight = CELL_SIZE * ((MAX_FONTPOSITION + 15) / 16 + 2);
    PCB->Grid = MIL_TO_COORD (5);
    PCB->Data->Layer[0].Name = strdup ("Font");
    PCB->Data->Layer[1].Name = strdup ("OrigFont");
    PCB->Data->Layer[2].Name = strdup ("Width");
    PCB->Data->Layer[3].Name = strdup ("Grid");
    hid_action ("PCBChanged");
    hid_action ("LayersChanged");
    lfont = PCB->Data->Layer + 0;
    lorig = PCB->Data->Layer + 1;
    lwidth = PCB->Data->Layer + 2;
    lgrid = PCB->Data->Layer + 3;
    font = &PCB->Font;

    for (s = 0; s <= MAX_FONTPOSITION; s++) {
        Coord ox = (s % 16 + 1) * CELL_SIZE;
        Coord oy = (s / 16 + 1) * CELL_SIZE;
        Coord w, miny, maxy, maxx = 0;
        symbol = &font->Symbol[s];
        miny = MIL_TO_COORD (5);
        maxy = font->MaxHeight;

        for (l = 0; l < symbol->LineN; l++) {
            CreateDrawnLineOnLayer (lfont,
                                    symbol->Line[l].Point1.X + ox,
                                    symbol->Line[l].Point1.Y + oy,
                                    symbol->Line[l].Point2.X + ox,
                                    symbol->Line[l].Point2.Y + oy,
                                    symbol->Line[l].Thickness,
                                    symbol->Line[l].Thickness, NoFlags ());
            CreateDrawnLineOnLayer (lorig, symbol->Line[l].Point1.X + ox,
                                    symbol->Line[l].Point1.Y + oy,
                                    symbol->Line[l].Point2.X + ox,
                                    symbol->Line[l].Point2.Y + oy,
                                    symbol->Line[l].Thickness,
                                    symbol->Line[l].Thickness, NoFlags ());

            if (maxx < symbol->Line[l].Point1.X) {
                maxx = symbol->Line[l].Point1.X;
            }

            if (maxx < symbol->Line[l].Point2.X) {
                maxx = symbol->Line[l].Point2.X;
            }
        }

        w = maxx + symbol->Delta + ox;
        CreateDrawnLineOnLayer (lwidth,
                                w, miny + oy,
                                w, maxy + oy, MIL_TO_COORD (1), MIL_TO_COORD (1), NoFlags ());
    }

    for (l = 0; l < 16; l++) {
        int x = (l + 1) * CELL_SIZE;
        CreateDrawnLineOnLayer (lgrid, x, 0, x, PCB->MaxHeight, MIL_TO_COORD (1),
                                MIL_TO_COORD (1), NoFlags ());
    }

    for (l = 0; l <= MAX_FONTPOSITION / 16 + 1; l++) {
        int y = (l + 1) * CELL_SIZE;
        CreateDrawnLineOnLayer (lgrid, 0, y, PCB->MaxWidth, y, MIL_TO_COORD (1),
                                MIL_TO_COORD (1), NoFlags ());
    }

    return 0;
}
Example #18
0
/*---------------------------------------------------------------------------
 *
 * convert buffer contents into an element
 */
bool
ConvertBufferToElement (BufferType *Buffer)
{
  ElementType *Element;
  Cardinal group;
  Cardinal pin_n = 1;
  bool hasParts = false, crooked = false;
  int onsolder;
  bool warned = false;

  if (Buffer->Data->pcb == 0)
    Buffer->Data->pcb = PCB;

  Element = CreateNewElement (PCB->Data, &PCB->Font, NoFlags (),
			      NULL, NULL, NULL, PASTEBUFFER->X,
			      PASTEBUFFER->Y, 0, 100,
			      MakeFlags (SWAP_IDENT ? ONSOLDERFLAG : NOFLAG),
			      false);
  if (!Element)
    return (false);
  VIA_LOOP (Buffer->Data);
  {
    char num[8];
    if (via->Mask < via->Thickness)
      via->Mask = via->Thickness + 2 * MASKFRAME;
    if (via->Name)
      CreateNewPin (Element, via->X, via->Y, via->Thickness,
		    via->Clearance, via->Mask, via->DrillingHole,
		    NULL, via->Name, MaskFlags (via->Flags,
						VIAFLAG | NOCOPY_FLAGS |
						SELECTEDFLAG | WARNFLAG));
    else
      {
	sprintf (num, "%d", pin_n++);
	CreateNewPin (Element, via->X, via->Y, via->Thickness,
		      via->Clearance, via->Mask, via->DrillingHole,
		      NULL, num, MaskFlags (via->Flags,
					    VIAFLAG | NOCOPY_FLAGS | SELECTEDFLAG
					    | WARNFLAG));
      }
    hasParts = true;
  }
  END_LOOP;

  for (onsolder = 0; onsolder < 2; onsolder ++)
    {
      int silk_layer;
      int onsolderflag;

      if ((!onsolder) == (!SWAP_IDENT))
	{
	  silk_layer = component_silk_layer;
	  onsolderflag = NOFLAG;
	}
      else
	{
	  silk_layer = solder_silk_layer;
	  onsolderflag = ONSOLDERFLAG;
	}

#define MAYBE_WARN() \
	  if (onsolder && !hasParts && !warned) \
	    { \
	      warned = true; \
	      Message \
		(_("Warning: All of the pads are on the opposite\n" \
		   "side from the component - that's probably not what\n" \
		   "you wanted\n")); \
	    } \

      /* get the component-side SM pads */
      group = GetLayerGroupNumberByNumber (silk_layer);
      GROUP_LOOP (Buffer->Data, group);
      {
	char num[8];
	LINE_LOOP (layer);
	{
	  sprintf (num, "%d", pin_n++);
	  CreateNewPad (Element, line->Point1.X,
			line->Point1.Y, line->Point2.X,
			line->Point2.Y, line->Thickness,
			line->Clearance,
			line->Thickness + line->Clearance, NULL,
			line->Number ? line->Number : num,
			MakeFlags (onsolderflag));
	  MAYBE_WARN();
	  hasParts = true;
	}
	END_LOOP;
	POLYGON_LOOP (layer);
	{
	  Coord x1, y1, x2, y2, w, h, t;

	  if (! polygon_is_rectangle (polygon))
	    {
	      crooked = true;
	      continue;
	    }

	  w = polygon->Points[2].X - polygon->Points[0].X;
	  h = polygon->Points[1].Y - polygon->Points[0].Y;
	  t = (w < h) ? w : h;
	  x1 = polygon->Points[0].X + t/2;
	  y1 = polygon->Points[0].Y + t/2;
	  x2 = x1 + (w-t);
	  y2 = y1 + (h-t);

	  sprintf (num, "%d", pin_n++);
	  CreateNewPad (Element,
			x1, y1, x2, y2, t,
			2 * Settings.Keepaway,
			t + Settings.Keepaway,
			NULL, num,
			MakeFlags (SQUAREFLAG | onsolderflag));
	  MAYBE_WARN();
	  hasParts = true;
	}
	END_LOOP;
      }
      END_LOOP;
    }

  /* now add the silkscreen. NOTE: elements must have pads or pins too */
  LINE_LOOP (&Buffer->Data->SILKLAYER);
  {
    if (line->Number && !NAMEONPCB_NAME (Element))
      NAMEONPCB_NAME (Element) = strdup (line->Number);
    CreateNewLineInElement (Element, line->Point1.X,
			    line->Point1.Y, line->Point2.X,
			    line->Point2.Y, line->Thickness);
    hasParts = true;
  }
  END_LOOP;
  ARC_LOOP (&Buffer->Data->SILKLAYER);
  {
    CreateNewArcInElement (Element, arc->X, arc->Y, arc->Width,
			   arc->Height, arc->StartAngle, arc->Delta,
			   arc->Thickness);
    hasParts = true;
  }
  END_LOOP;
  if (!hasParts)
    {
      DestroyObject (PCB->Data, ELEMENT_TYPE, Element, Element, Element);
      Message (_("There was nothing to convert!\n"
		 "Elements must have some silk, pads or pins.\n"));
      return (false);
    }
  if (crooked)
     Message (_("There were polygons that can't be made into pins!\n"
                "So they were not included in the element\n"));
  Element->MarkX = Buffer->X;
  Element->MarkY = Buffer->Y;
  if (SWAP_IDENT)
    SET_FLAG (ONSOLDERFLAG, Element);
  SetElementBoundingBox (PCB->Data, Element, &PCB->Font);
  ClearBuffer (Buffer);
  MoveObjectToBuffer (Buffer->Data, PCB->Data, ELEMENT_TYPE, Element, Element,
		      Element);
  SetBufferBoundingBox (Buffer);
  return (true);
}
Example #19
0
File: rats.c Project: rlutz/pcb
/*!
 * \brief This function is moved from the original netlist.c as
 * part of the gui code separation for the Gtk port.
 */
RatType *
AddNet (void)
{
  static int ratDrawn = 0;
  char name1[256], *name2;
  Cardinal group1, group2;
  char ratname[20];
  int found;
  void *ptr1, *ptr2, *ptr3;
  LibraryMenuType *menu;
  LibraryEntryType *entry;

  if (Crosshair.AttachedLine.Point1.X == Crosshair.AttachedLine.Point2.X
      && Crosshair.AttachedLine.Point1.Y == Crosshair.AttachedLine.Point2.Y)
    return (NULL);

  found = SearchObjectByLocation (PAD_TYPE | PIN_TYPE, &ptr1, &ptr2, &ptr3,
				  Crosshair.AttachedLine.Point1.X,
				  Crosshair.AttachedLine.Point1.Y, 5);
  if (found == NO_TYPE)
    {
      Message (_("No pad/pin under rat line\n"));
      return (NULL);
    }
  if (NAMEONPCB_NAME ((ElementType *) ptr1) == NULL
      || *NAMEONPCB_NAME ((ElementType *) ptr1) == 0)
    {
      Message (_("You must name the starting element first\n"));
      return (NULL);
    }

  /* will work for pins to since the FLAG is common */
  group1 = GetLayerGroupNumberBySide (
            TEST_FLAG (ONSOLDERFLAG, (PadType *) ptr2) ? BOTTOM_SIDE : TOP_SIDE);
  strcpy (name1, ConnectionName (found, ptr1, ptr2));
  found = SearchObjectByLocation (PAD_TYPE | PIN_TYPE, &ptr1, &ptr2, &ptr3,
				  Crosshair.AttachedLine.Point2.X,
				  Crosshair.AttachedLine.Point2.Y, 5);
  if (found == NO_TYPE)
    {
      Message (_("No pad/pin under rat line\n"));
      return (NULL);
    }
  if (NAMEONPCB_NAME ((ElementType *) ptr1) == NULL
      || *NAMEONPCB_NAME ((ElementType *) ptr1) == 0)
    {
      Message (_("You must name the ending element first\n"));
      return (NULL);
    }
  group2 = GetLayerGroupNumberBySide (
            TEST_FLAG (ONSOLDERFLAG, (PadType *) ptr2) ? BOTTOM_SIDE : TOP_SIDE);
  name2 = ConnectionName (found, ptr1, ptr2);

  menu = netnode_to_netname (name1);
  if (menu)
    {
      if (netnode_to_netname (name2))
	{
	  Message (_
		   ("Both connections already in netlist - cannot merge nets\n"));
	  return (NULL);
	}
      entry = GetLibraryEntryMemory (menu);
      entry->ListEntry = strdup (name2);
      netnode_to_netname (name2);
      goto ratIt;
    }
  /* ok, the first name did not belong to a net */
  menu = netnode_to_netname (name2);
  if (menu)
    {
      entry = GetLibraryEntryMemory (menu);
      entry->ListEntry = strdup (name1);
      netnode_to_netname (name1);
      goto ratIt;
    }

  /*
   * neither belong to a net, so create a new one.
   *
   * before creating a new rats here, we need to search
   * for a unique name.
   */
  sprintf (ratname, "  ratDrawn%i", ++ratDrawn);
  while (rat_used (ratname))
    {
      sprintf (ratname, "  ratDrawn%i", ++ratDrawn);
    }

  menu = GetLibraryMenuMemory (&PCB->NetlistLib);
  menu->Name = strdup (ratname);
  entry = GetLibraryEntryMemory (menu);
  entry->ListEntry = strdup (name1);
  entry = GetLibraryEntryMemory (menu);
  entry->ListEntry = strdup (name2);
  menu->flag = 1;

ratIt:
  NetlistChanged (0);
  return (CreateNewRat (PCB->Data, Crosshair.AttachedLine.Point1.X,
			Crosshair.AttachedLine.Point1.Y,
			Crosshair.AttachedLine.Point2.X,
			Crosshair.AttachedLine.Point2.Y,
			group1, group2, Settings.RatThickness, NoFlags ()));
}
Example #20
0
File: rats.c Project: rlutz/pcb
/*!
 * \brief Draw a rat net (tree) having the shortest lines.
 *
 * This also frees the subnet memory as they are consumed.
 *
 * \note The \c Netl we are passed is NOT the main netlist - it's the
 * connectivity for ONE net.
 * It represents the CURRENT connectivity state for the net, with each
 * Netl->Net[N] representing one copper-connected subset of the net.
 *
 * Everything inside the NetList Netl should be connected together.
 *
 * Each Net in \c Netl is a group of Connections which are already
 * connected together somehow, either by real wires or by rats we've
 * already drawn.
 *
 * Each Connection is a vertex within that blob of connected items.
 *
 * This loop finds the closest vertex pairs between each blob and draws
 * rats that merge the blobs until there's just one big blob.
 *
 * Just to clarify, with some examples:
 *
 * Each \c Netl is one full net from a netlist, like from gnetlist.
 *
 * Each Netl->Net[N] is a subset of that net that's already
 * physically connected on the pcb.
 *
 * So a new design with no traces yet, would have a huge list of Net[N],
 * each with one pin in it.
 *
 * A fully routed design would have one Net[N] with all the pins
 * (for that net) in it.
 */
static bool
DrawShortestRats (NetListType *Netl, void (*funcp) (register ConnectionType *, register ConnectionType *, register RouteStyleType *))
{
  RatType *line;
  register float distance, temp;
  register ConnectionType *conn1, *conn2, *firstpoint, *secondpoint;
  PolygonType *polygon;
  bool changed = false;
  bool havepoints;
  Cardinal n, m, j;
  NetType *next, *subnet, *theSubnet = NULL;

  /* This is just a sanity check, to make sure we're passed
   * *something*.
   */
  if (!Netl || Netl->NetN < 1)
    return false;

  /*
   * We keep doing this do/while loop until everything's connected.
   * I.e. once per rat we add.
   */
  distance = 0.0;
  havepoints = true; /* so we run the loop at least once */
  while (Netl->NetN > 1 && havepoints)
    {
      /* This is the top of the "find one rat" logic.  */
      havepoints = false;
      firstpoint = secondpoint = NULL;

      /* Test Net[0] vs Net[N] for N=1..max.  Find the shortest
	 distance between any two points in different blobs.  */
      subnet = &Netl->Net[0];
      for (j = 1; j < Netl->NetN; j++)
	{
	  /*
	   * Scan between Net[0] blob (subnet) and Net[N] blob (next).
	   * Note the shortest distance we find.
	   */
	  next = &Netl->Net[j];
	  for (n = subnet->ConnectionN - 1; n != -1; n--)
	    {
	      conn1 = &subnet->Connection[n];
	      for (m = next->ConnectionN - 1; m != -1; m--)
		{
		  conn2 = &next->Connection[m];
		  /*
		   * At this point, conn1 and conn2 are two pins in
		   * different blobs of the same net.  See how far
		   * apart they are, and if they're "closer" than what
		   * we already have.
		   */

		  /*
		   * Prefer to connect Connections over polygons to the
		   * polygons (ie assume the user wants a via to a plane,
		   * not a daisy chain).  Further prefer to pick an existing
		   * via in the Net to make that connection.
		   */
		  if (conn1->type == POLYGON_TYPE &&
		      (polygon = (PolygonType *)conn1->ptr2) &&
		      !(distance == 0 &&
		        firstpoint && firstpoint->type == VIA_TYPE) &&
		      IsPointInPolygonIgnoreHoles (conn2->X, conn2->Y, polygon))
		    {
		      distance = 0;
		      firstpoint = conn2;
		      secondpoint = conn1;
		      theSubnet = next;
		      havepoints = true;
		    }
		  else if (conn2->type == POLYGON_TYPE &&
		      (polygon = (PolygonType *)conn2->ptr2) &&
		      !(distance == 0 &&
		        firstpoint && firstpoint->type == VIA_TYPE) &&
		      IsPointInPolygonIgnoreHoles (conn1->X, conn1->Y, polygon))
		    {
		      distance = 0;
		      firstpoint = conn1;
		      secondpoint = conn2;
		      theSubnet = next;
		      havepoints = true;
		    }
		  else if ((temp = SQUARE (conn1->X - conn2->X) +
		       SQUARE (conn1->Y - conn2->Y)) < distance || !firstpoint)
		    {
		      distance = temp;
		      firstpoint = conn1;
		      secondpoint = conn2;
		      theSubnet = next;
		      havepoints = true;
		    }
		}
	    }
	}

      /*
       * If HAVEPOINTS is true, we've found a pair of points in two
       * separate blobs of the net, and need to connect them together.
       */
      if (havepoints)
	{
	  if (funcp)
	    {
	      (*funcp) (firstpoint, secondpoint, subnet->Style);
	    }
	  else
	    {
	      /* found the shortest distance subnet, draw the rat */
	      if ((line = CreateNewRat (PCB->Data,
					firstpoint->X, firstpoint->Y,
					secondpoint->X, secondpoint->Y,
					firstpoint->group, secondpoint->group,
					Settings.RatThickness,
					NoFlags ())) != NULL)
		{
		  if (distance == 0)
		    SET_FLAG (VIAFLAG, line);
		  AddObjectToCreateUndoList (RATLINE_TYPE, line, line, line);
		  DrawRat (line);
		  changed = true;
		}
	    }

	  /* copy theSubnet into the current subnet */
	  TransferNet (Netl, theSubnet, subnet);
	}
    }

  /* presently nothing to do with the new subnet */
  /* so we throw it away and free the space */
  FreeNetMemory (&Netl->Net[--(Netl->NetN)]);
  /* Sadly adding a rat line messes up the sorted arrays in connection finder */
  /* hace: perhaps not necessarily now that they aren't stored in normal layers */
  if (changed)
    {
      FreeConnectionLookupMemory ();
      InitConnectionLookup ();
    }
  return (changed);
}