Skip to content

Instantly share code, notes, and snippets.

@russdill
Created July 20, 2012 02:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save russdill/3148380 to your computer and use it in GitHub Desktop.
Save russdill/3148380 to your computer and use it in GitHub Desktop.
/* Copyright 2012, Russ.Dill@asu.edu
* Released under LGPLv2 or later */
#include <math.h>
#include "config.h"
#include "data.h"
#include "rtree.h"
#include "mirror.h"
#include "remove.h"
#include "select.h"
#include "draw.h"
#include "undo.h"
#include "move.h"
#include "change.h"
#include "copy.h"
#include "rotate.h"
#include "global.h"
static char *new_footprint;
static int
direction (Coord x1, Coord y1, Coord x2, Coord y2)
{
if (x1 != x2 || y1 != y2)
{
double theta = atan2(y2 - y1, x2 - x1);
theta *= 2.0 / M_PI;
theta += 4.5;
return (int) theta % 4;
}
return -1;
}
static BYTE
_ElementOrientation (ElementType *e)
{
BYTE ret;
PIN_LOOP (e)
{
ret = direction(e->MarkX, e->MarkY, pin->X, pin->Y);
if (ret != -1)
return ret;
}
END_LOOP;
PAD_LOOP (e)
{
ret = direction(e->MarkX, e->MarkY, pad->Point1.X, pad->Point1.Y);
if (ret != -1)
return ret;
ret = direction(e->MarkX, e->MarkY, pad->Point2.X, pad->Point2.Y);
if (ret != -1)
return ret;
}
END_LOOP;
return 0;
}
static void *
ReplaceElement (ElementType *Element)
{
int i;
FlagType flags;
Coord element_x, element_y;
Coord text_x, text_y;
TextType *name;
BYTE element_rotation;
BYTE text_rotation;
BYTE paste_rotation;
BYTE new_rotation;
int scale;
char *refdes;
char *value;
char *old;
ElementType *paste_element = NULL;
ELEMENT_LOOP (PASTEBUFFER->Data)
{
if (paste_element)
{
/* More than one element */
return NULL;
}
paste_element = element;
}
END_LOOP;
if (!paste_element)
{
/* No element to paste */
return NULL;
}
flags = Element->Flags;
element_x = Element->MarkX;
element_y = Element->MarkY;
element_rotation = _ElementOrientation (Element);
name = &Element->Name[NAMEONPCB_INDEX];
text_x = name->X;
text_y = name->Y;
text_rotation = name->Direction;
scale = name->Scale;
refdes = strdup (name->TextString);
name = &Element->Name[VALUE_INDEX];
value = strdup (name->TextString);
paste_element = CopyElementLowLevel(PCB->Data, NULL, paste_element,
TEST_FLAG (UNIQUENAMEFLAG, PCB),
element_x - paste_element->MarkX,
element_y - paste_element->MarkY);
if (!FRONT (Element))
MirrorElementCoordinates (PCB->Data, paste_element,
paste_element->MarkY*2 - PCB->MaxHeight);
// Thermals and polygon zero clearance
PIN_LOOP (Element)
{
PinType *old = pin;
if (pin->Number)
{
PIN_LOOP (paste_element)
{
if (pin->Number && !strcmp (pin->Number, old->Number))
{
if (!old->Clearance)
pin->Clearance = 0;
for (i = 0; i < MAX_LAYER; i++)
ASSIGN_THERM (i, GET_THERM (i, old), pin);
}
}
END_LOOP;
}
}
END_LOOP;
PAD_LOOP (Element)
{
PadType *old = pad;
if (old->Number)
{
PAD_LOOP (paste_element)
{
if (pad->Number && !strcmp (pad->Number, old->Number))
{
if (!old->Clearance)
pad->Clearance = 0;
for (i = 0; i < MAX_LAYER; i++)
ASSIGN_THERM (i, GET_THERM (i, old), pad);
}
}
END_LOOP;
}
}
END_LOOP;
RemoveElement(Element);
paste_element->Flags = flags;
old = ChangeElementText(PCB, PCB->Data, paste_element, NAMEONPCB_INDEX,
refdes);
if (old)
free(old);
old = ChangeElementText(PCB, PCB->Data, paste_element, VALUE_INDEX,
value);
if (old)
free(old);
if (new_footprint)
{
old = ChangeElementText(PCB, PCB->Data, paste_element, DESCRIPTION_INDEX,
strdup (new_footprint));
if (old)
free(old);
}
SaveUndoSerialNumber ();
paste_rotation = _ElementOrientation (paste_element);
new_rotation = (paste_rotation - element_rotation) & 3;
RotateElementLowLevel (PCB->Data, paste_element, paste_element->MarkX,
paste_element->MarkY, new_rotation);
ELEMENTTEXT_LOOP (paste_element);
{
BYTE rot;
if (PCB->Data->name_tree[n])
r_delete_entry (PCB->Data->name_tree[n], (BoxType *)text);
MOVE_TEXT_LOWLEVEL (text, text_x - text->X, text_y - text->Y);
text->Scale = scale;
rot = text_rotation - text->Direction + 4;
RotateTextLowLevel (text, text->X, text->Y, rot & 3);
if (PCB->Data->name_tree[n])
r_insert_entry (PCB->Data->name_tree[n], (BoxType *)text, 0);
}
END_LOOP;
RestoreUndoSerialNumber ();
AddObjectToCreateUndoList (ELEMENT_TYPE, paste_element, paste_element,
paste_element);
if (PCB->ElementOn && (FRONT (paste_element) || PCB->InvisibleObjectsOn))
{
DrawElementName (paste_element);
DrawElementPackage (paste_element);
}
if (PCB->PinOn)
{
DrawElementPinsAndPads (paste_element);
}
return NULL;
}
static ObjectFunctionType ReplaceFunctions = {
NULL,
NULL,
NULL,
NULL,
ReplaceElement,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
static int
replace (int argc, char **argv, Coord x, Coord y)
{
new_footprint = NULL;
if (argc > 0)
{
new_footprint = argv[0];
}
if (SelectedOperation (&ReplaceFunctions, true, ELEMENT_TYPE))
{
IncrementUndoSerialNumber ();
Draw ();
}
else
{
}
return 0;
}
static HID_Action replace_action_list[] = {
{"ReplaceSelected", NULL, replace,
NULL, NULL}
};
REGISTER_ACTIONS (replace_action_list)
void
pcb_plugin_init()
{
register_replace_action_list();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment