00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdio.h>
00019 #include <math.h>
00020
00021 #include "global.h"
00022 #include "data.h"
00023 #include "hid.h"
00024 #include "misc.h"
00025 #include "create.h"
00026 #include "rtree.h"
00027 #include "undo.h"
00028 #include "rats.h"
00029 #include "error.h"
00030 #include "move.h"
00031 #include "draw.h"
00032 #include "set.h"
00033
00034 #define GAP 10000
00035 static LocationType minx;
00036 static LocationType miny;
00037 static LocationType maxx;
00038 static LocationType maxy;
00039
00040
00041
00042
00043
00044
00045
00046 static void
00047 place(ElementTypePtr element)
00048 {
00049 LocationType dx, dy;
00050
00051
00052 dx = minx - element->BoundingBox.X1;
00053 dy = miny - element->BoundingBox.Y1;
00054
00055
00056 dx -= (element->MarkX + dx) % (long) (PCB->Grid);
00057 dx += (long) (PCB->Grid);
00058 dy -= (element->MarkY + dy) % (long) (PCB->Grid);
00059 dy += (long) (PCB->Grid);
00060
00061
00062
00063
00064
00065 dx += (long) (PCB->Grid);
00066
00067
00068 if (minx != GAP && GAP + element->BoundingBox.X2 + dx > PCB->MaxWidth) {
00069 miny = maxy + GAP;
00070 minx = GAP;
00071 place(element);
00072 return;
00073 }
00074
00075
00076 MoveElementLowLevel (PCB->Data, element, dx, dy);
00077
00078
00079 AddObjectToMoveUndoList (ELEMENT_TYPE, NULL, NULL, element, dx, dy);
00080
00081
00082 minx += element->BoundingBox.X2 - element->BoundingBox.X1 + GAP;
00083 if (maxy < element->BoundingBox.Y2) {
00084 maxy = element->BoundingBox.Y2;
00085 }
00086 }
00087
00088
00089
00090
00091 static LocationType
00092 padDX(ConnectionTypePtr conn)
00093 {
00094 ElementTypePtr element = (ElementTypePtr) conn->ptr1;
00095 AnyLineObjectTypePtr line = (AnyLineObjectTypePtr) conn->ptr2;
00096
00097 return line->BoundingBox.X1 -
00098 (element->BoundingBox.X1 + element->BoundingBox.X2) / 2;
00099 }
00100
00101
00102 static int
00103 padorder(ConnectionTypePtr conna, ConnectionTypePtr connb)
00104 {
00105 LocationType dxa, dxb;
00106
00107 dxa = padDX(conna);
00108 dxb = padDX(connb);
00109
00110 if (dxa > 0 && dxb < 0)
00111 return 1;
00112 return 0;
00113 }
00114
00115
00116 #define ELEMENT_N(DATA,ELT) ((ELT) - (DATA)->Element)
00117 #define VISITED(ELT) (visited[ELEMENT_N(PCB->Data, (ELT))])
00118 #define IS_ELEMENT(CONN) ((CONN)->type == PAD_TYPE || (CONN)->type == PIN_TYPE)
00119
00120 #define ARG(n) (argc > (n) ? argv[n] : 0)
00121
00122 static const char smartdisperse_syntax[] = "SmartDisperse([All|Selected])";
00123
00124 static int
00125 smartdisperse (int argc, char **argv, int x, int y)
00126 {
00127 char *function = ARG(0);
00128 NetListTypePtr Nets;
00129 char *visited;
00130
00131 int all;
00132
00133
00134
00135 if (! function) {
00136 all = 1;
00137 } else if (strcmp(function, "All") == 0) {
00138 all = 1;
00139 } else if (strcmp(function, "Selected") == 0) {
00140 all = 0;
00141 } else {
00142 AFAIL(smartdisperse);
00143 }
00144
00145 Nets = ProcNetlist (&PCB->NetlistLib);
00146 if (! Nets) {
00147 Message (_("Can't use SmartDisperse because no netlist is loaded.\n"));
00148 return 0;
00149 }
00150
00151
00152 visited = MyCalloc(PCB->Data->ElementN, sizeof(*visited),
00153 "smartdisperse()");
00154
00155
00156 ELEMENT_LOOP(PCB->Data);
00157 {
00158 if (! (all || TEST_FLAG (SELECTEDFLAG, element))) {
00159 visited[n] = 1;
00160 }
00161 }
00162 END_LOOP;
00163
00164
00165 minx = GAP;
00166 miny = GAP;
00167 maxx = GAP;
00168 maxy = GAP;
00169
00170
00171
00172
00173
00174
00175 NET_LOOP(Nets);
00176 {
00177 ConnectionTypePtr conna, connb;
00178 ElementTypePtr ea, eb;
00179
00180
00181 if (net->ConnectionN != 2)
00182 continue;
00183
00184 conna = &net->Connection[0];
00185 connb = &net->Connection[1];
00186 if (!IS_ELEMENT(conna) || !IS_ELEMENT(conna))
00187 continue;
00188
00189 ea = (ElementTypePtr) conna->ptr1;
00190 eb = (ElementTypePtr) connb->ptr1;
00191
00192
00193 if (VISITED(ea) || VISITED(eb))
00194 continue;
00195 VISITED(ea) = 1;
00196 VISITED(eb) = 1;
00197
00198
00199 if (padorder(conna, connb)) {
00200 place(ea);
00201 place(eb);
00202 } else {
00203 place(eb);
00204 place(ea);
00205 }
00206 }
00207 END_LOOP;
00208
00209
00210 NET_LOOP(Nets);
00211 {
00212 CONNECTION_LOOP(net);
00213 {
00214 ElementTypePtr element;
00215
00216 if (! IS_ELEMENT(connection))
00217 continue;
00218
00219 element = (ElementTypePtr) connection->ptr1;
00220
00221
00222 if (VISITED(element))
00223 continue;
00224 VISITED(element) = 1;
00225 place(element);
00226 }
00227 END_LOOP;
00228 }
00229 END_LOOP;
00230
00231
00232 ELEMENT_LOOP(PCB->Data);
00233 {
00234 if (! visited[n]) {
00235 place(element);
00236 }
00237 }
00238 END_LOOP;
00239
00240 free(visited);
00241
00242 IncrementUndoSerialNumber();
00243 ClearAndRedrawOutput();
00244 SetChangedFlag(1);
00245
00246 return 0;
00247 }
00248
00249 static HID_Action smartdisperse_action_list[] = {
00250 {"smartdisperse", NULL, smartdisperse, NULL, NULL}
00251 };
00252
00253 REGISTER_ACTIONS (smartdisperse_action_list)
00254
00255 void
00256 hid_smartdisperse_init()
00257 {
00258 register_smartdisperse_action_list();
00259 }