27
static char *rcsid = "$Id: rubberband.c,v 1.2 1998/02/21 10:27:14 cad Exp $";
29
30
/* functions used by 'rubberband moves'
32
37
#include <stdlib.h>
33
39
#include <string.h>
34
41
#include <memory.h>
36
44
#include <unistd.h>
38
47
#include "global.h"
40
49
#include "create.h"
43
53
#include "rubberband.h"
44
55
#include "search.h"
57
#ifdef HAVE_LIBDMALLOC
61
RCSID("$Id: rubberband.c,v 1.12 2005/01/03 12:57:00 danmc Exp $");
46
64
/* ---------------------------------------------------------------------------
47
65
* some local prototypes
49
static void CheckPadForRubberbandConnection(PadTypePtr);
50
static void CheckPinForRubberbandConnection(PinTypePtr);
51
static void CheckLinePointForRubberbandConnection(LayerTypePtr,
52
LineTypePtr, PointTypePtr);
53
static void CheckPolygonForRubberbandConnection(LayerTypePtr,
55
static void CheckLinePointForRat(LayerTypePtr, PointTypePtr);
67
static void CheckPadForRubberbandConnection (PadTypePtr);
68
static void CheckPinForRubberbandConnection (PinTypePtr);
69
static void CheckLinePointForRubberbandConnection (LayerTypePtr,
70
LineTypePtr, PointTypePtr);
71
static void CheckPolygonForRubberbandConnection (LayerTypePtr,
73
static void CheckLinePointForRat (LayerTypePtr, PointTypePtr);
74
static int rubber_callback (const BoxType * b, void *cl);
86
rubber_callback (const BoxType * b, void *cl)
88
LineTypePtr line = (LineTypePtr) b;
89
struct rubber_info *i = (struct rubber_info *) cl;
94
t = line->Thickness / 2;
96
if (TEST_FLAG (LOCKFLAG, line))
101
* Check to see if the line touches a rectangular region.
102
* To do this we need to look for the intersection of a circular
103
* region and a rectangular region.
107
if (line->Point1.X + t >= i->box.X1 && line->Point1.X - t <= i->box.X2
108
&& line->Point1.Y + t >= i->box.Y1
109
&& line->Point1.Y - t <= i->box.Y2)
111
if ( ((i->box.X1 <= line->Point1.X) &&
112
(line->Point1.X <= i->box.X2)) ||
113
((i->box.Y1 <= line->Point1.Y) &&
114
(line->Point1.Y <= i->box.Y2)) )
117
* The circle is positioned such that the closest point
118
* on the rectangular region boundary is not at a corner
119
* of the rectangle. i.e. the shortest line from circle
120
* center to rectangle intersects the rectangle at 90
121
* degrees. In this case our first test is sufficient
128
* Now we must check the distance from the center of the
129
* circle to the corners of the rectangle since the
130
* closest part of the rectangular region is the corner.
132
x = MIN (abs(i->box.X1 - line->Point1.X),
133
abs(i->box.X2 - line->Point1.X) );
135
y = MIN (abs(i->box.Y1 - line->Point1.Y),
136
abs(i->box.Y2 - line->Point1.Y));
145
CreateNewRubberbandEntry (i->layer, line, &line->Point1);
149
if (line->Point2.X + t >= i->box.X1 && line->Point2.X - t <= i->box.X2
150
&& line->Point2.Y + t >= i->box.Y1
151
&& line->Point2.Y - t <= i->box.Y2)
153
if ( ((i->box.X1 <= line->Point2.X) &&
154
(line->Point2.X <= i->box.X2)) ||
155
((i->box.Y1 <= line->Point2.Y) &&
156
(line->Point2.Y <= i->box.Y2)) )
162
x = MIN (abs(i->box.X1 - line->Point2.X),
163
abs(i->box.X2 - line->Point2.X) );
165
y = MIN (abs(i->box.Y1 - line->Point2.Y),
166
abs(i->box.Y2 - line->Point2.Y));
175
CreateNewRubberbandEntry (i->layer, line, &line->Point2);
181
/* circular search region */
182
x = (i->X - line->Point1.X);
184
y = (i->Y - line->Point1.Y);
187
if (x < (i->radius * (i->radius + 2 * t)))
189
CreateNewRubberbandEntry (i->layer, line, &line->Point1);
192
x = (i->X - line->Point2.X);
194
y = (i->Y - line->Point2.Y);
197
if (x < (i->radius * (i->radius + 2 * t)))
199
CreateNewRubberbandEntry (i->layer, line, &line->Point2);
57
205
/* ---------------------------------------------------------------------------
58
206
* checks all visible lines which belong to the same layergroup as the
59
207
* passed pad. If one of the endpoints of the line lays inside the pad,
60
208
* the line is added to the 'rubberband' list
62
static void CheckPadForRubberbandConnection(PadTypePtr Pad)
64
Dimension half = Pad->Thickness/2;
65
Position minx = MIN(Pad->Point1.X, Pad->Point2.X) -half,
66
miny = MIN(Pad->Point1.Y, Pad->Point2.Y) -half,
67
maxx = MAX(Pad->Point1.X, Pad->Point2.X) +half,
68
maxy = MAX(Pad->Point1.Y, Pad->Point2.Y) +half;
73
(TEST_FLAG(ONSOLDERFLAG, Pad) ? SOLDER_LAYER : COMPONENT_LAYER);
74
group = GetLayerGroupNumberByNumber(i);
76
/* check all visible layers in the same group */
77
for (i = 0; i < PCB->LayerGroups.Number[group]; i++)
79
Cardinal number = PCB->LayerGroups.Entries[group][i];
82
/* skip solder/component layers */
83
if (number >= MAX_LAYER)
86
/* check all visible lines of the group member */
87
layer = &PCB->Data->Layer[number];
91
if (line->Point1.X >= minx && line->Point1.X <= maxx &&
92
line->Point1.Y >= miny && line->Point1.Y <= maxy)
93
CreateNewRubberbandEntry(layer, line, &line->Point1);
94
else if (line->Point2.X >= minx && line->Point2.X <= maxx &&
95
line->Point2.Y >= miny && line->Point2.Y <= maxy)
96
CreateNewRubberbandEntry(layer, line, &line->Point2);
102
static void CheckPadForRat(PadTypePtr Pad)
108
(TEST_FLAG(ONSOLDERFLAG, Pad) ? SOLDER_LAYER : COMPONENT_LAYER);
109
group = GetLayerGroupNumberByNumber(i);
112
if (line->Point1.X == Pad->Point1.X &&
113
line->Point1.Y == Pad->Point1.Y && line->group1 == group)
114
CreateNewRubberbandEntry(NULL, (LineTypePtr) line, &line->Point1);
116
if (line->Point2.X == Pad->Point1.X &&
117
line->Point2.Y == Pad->Point1.Y &&
118
line->group2 == group)
119
CreateNewRubberbandEntry(NULL, (LineTypePtr) line, &line->Point2);
211
CheckPadForRubberbandConnection (PadTypePtr Pad)
213
BDimension half = Pad->Thickness / 2;
215
struct rubber_info info;
217
info.box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - half;
218
info.box.Y1 = MIN (Pad->Point1.Y, Pad->Point2.Y) - half;
219
info.box.X2 = MAX (Pad->Point1.X, Pad->Point2.X) + half;
220
info.box.Y2 = MAX (Pad->Point1.Y, Pad->Point2.Y) + half;
224
(TEST_FLAG (ONSOLDERFLAG, Pad) ? SOLDER_LAYER : COMPONENT_LAYER);
225
group = GetLayerGroupNumberByNumber (i);
227
/* check all visible layers in the same group */
230
/* check all visible lines of the group member */
234
r_search (info.layer->line_tree, &info.box, NULL, rubber_callback,
251
rat_callback (const BoxType * box, void *cl)
253
RatTypePtr rat = (RatTypePtr) box;
254
struct rinfo *i = (struct rinfo *) cl;
259
if (rat->Point1.X == i->pin->X && rat->Point1.Y == i->pin->Y)
260
CreateNewRubberbandEntry (NULL, (LineTypePtr) rat, &rat->Point1);
261
else if (rat->Point2.X == i->pin->X && rat->Point2.Y == i->pin->Y)
262
CreateNewRubberbandEntry (NULL, (LineTypePtr) rat, &rat->Point2);
265
if (rat->Point1.X == i->pad->Point1.X &&
266
rat->Point1.Y == i->pad->Point1.Y && rat->group1 == i->group)
267
CreateNewRubberbandEntry (NULL, (LineTypePtr) rat, &rat->Point1);
269
if (rat->Point2.X == i->pad->Point1.X &&
270
rat->Point2.Y == i->pad->Point1.Y && rat->group2 == i->group)
271
CreateNewRubberbandEntry (NULL, (LineTypePtr) rat, &rat->Point2);
273
if (rat->Point1.X == i->pad->Point2.X &&
274
rat->Point1.Y == i->pad->Point2.Y && rat->group1 == i->group)
275
CreateNewRubberbandEntry (NULL, (LineTypePtr) rat, &rat->Point1);
277
if (rat->Point2.X == i->pad->Point2.X &&
278
rat->Point2.Y == i->pad->Point2.Y && rat->group2 == i->group)
279
CreateNewRubberbandEntry (NULL, (LineTypePtr) rat, &rat->Point2);
282
if (rat->group1 == i->group &&
283
rat->Point1.X == i->point->X && rat->Point1.Y == i->point->Y)
284
CreateNewRubberbandEntry (NULL, (LineTypePtr) rat, &rat->Point1);
286
if (rat->group2 == i->group &&
287
rat->Point2.X == i->point->X && rat->Point2.Y == i->point->Y)
288
CreateNewRubberbandEntry (NULL, (LineTypePtr) rat, &rat->Point2);
291
Message ("hace: bad rubber-rat lookup callback\n");
297
CheckPadForRat (PadTypePtr Pad)
303
(TEST_FLAG (ONSOLDERFLAG, Pad) ? SOLDER_LAYER : COMPONENT_LAYER);
304
info.group = GetLayerGroupNumberByNumber (i);
306
info.type = PAD_TYPE;
308
r_search (PCB->Data->rat_tree, &Pad->BoundingBox, NULL, rat_callback,
313
CheckPinForRat (PinTypePtr Pin)
317
info.type = PIN_TYPE;
319
r_search (PCB->Data->rat_tree, &Pin->BoundingBox, NULL, rat_callback,
324
CheckLinePointForRat (LayerTypePtr Layer, PointTypePtr Point)
327
info.group = GetLayerGroupNumberByPointer (Layer);
329
info.type = LINEPOINT_TYPE;
331
r_search (PCB->Data->rat_tree, (BoxType *) Point, NULL, rat_callback,
124
335
/* ---------------------------------------------------------------------------
129
340
* and readability is more important then the few %
130
341
* of faiures that are immediately recognized
132
static void CheckPinForRubberbandConnection(PinTypePtr Pin)
134
register float radius,
137
VISIBLELINE_LOOP(PCB->Data,
138
/* save sqrt computation */
139
radius = (float) (Pin->Thickness +line->Thickness) /2.0;
141
dx = line->Point1.X -Pin->X;
142
dy = line->Point1.Y -Pin->Y;
143
if (dx*dx+dy*dy <= radius)
144
CreateNewRubberbandEntry(layer, line, &line->Point1);
147
dx = line->Point2.X -Pin->X;
148
dy = line->Point2.Y -Pin->Y;
149
if (dx*dx+dy*dy <= radius)
150
CreateNewRubberbandEntry(layer, line, &line->Point2);
155
static void CheckPinForRat(PinTypePtr Pin)
158
if (line->Point1.X == Pin->X && line->Point1.Y == Pin->Y)
159
CreateNewRubberbandEntry(NULL, (LineTypePtr) line, &line->Point1);
161
if (line->Point2.X == Pin->X && line->Point2.Y == Pin->Y)
162
CreateNewRubberbandEntry(NULL, (LineTypePtr) line, &line->Point2);
166
static void CheckLinePointForRat(LayerTypePtr Layer, PointTypePtr Point)
168
Cardinal group = GetLayerGroupNumberByPointer(Layer);
171
if (line->group1 == group &&
172
line->Point1.X == Point->X && line->Point1.Y == Point->Y)
173
CreateNewRubberbandEntry(NULL, (LineTypePtr) line, &line->Point1);
175
if (line->group2 == group &&
176
line->Point2.X == Point->X && line->Point2.Y == Point->Y)
177
CreateNewRubberbandEntry(NULL, (LineTypePtr) line, &line->Point2);
183
/* ---------------------------------------------------------------------------
184
* checks all visible lines which belong to the same group as the passed line.
185
* If one of the endpoints of the line lays * inside the passed line,
186
* the scanned line is added to the 'rubberband' list
188
static void CheckLinePointForRubberbandConnection(LayerTypePtr Layer,
189
LineTypePtr Line, PointTypePtr LinePoint)
194
/* lookup layergroup and check all visible lines in this group */
195
group = GetLayerGroupNumberByPointer(Layer);
196
for (entry = 0; entry < PCB->LayerGroups.Number[group]; entry++)
198
Cardinal number = PCB->LayerGroups.Entries[group][entry];
201
/* skip solder/component layers */
202
if (number >= MAX_LAYER)
205
/* check all visible lines of the group member */
206
layer = &PCB->Data->Layer[number];
209
register float radius,
212
/* the following code just compares the endpoints
216
/* skip the original line */
220
/* save sqrt computation */
221
radius = (float) (Line->Thickness +line->Thickness) /2.0;
223
dx = line->Point1.X -LinePoint->X;
224
dy = line->Point1.Y -LinePoint->Y;
225
if (dx*dx+dy*dy <= radius)
227
CreateNewRubberbandEntry(layer, line, &line->Point1);
230
dx = line->Point2.X -LinePoint->X;
231
dy = line->Point2.Y -LinePoint->Y;
232
if (dx*dx+dy*dy <= radius)
234
CreateNewRubberbandEntry(layer, line, &line->Point2);
242
/* ---------------------------------------------------------------------------
243
* checks all visible lines which belong to the same group as the passed line.
244
* If one of the endpoints of the line lays * inside the passed line,
245
* the scanned line is added to the 'rubberband' list
247
static void CheckPolygonForRubberbandConnection(LayerTypePtr Layer,
248
PolygonTypePtr Polygon)
253
/* lookup layergroup and check all visible lines in this group */
254
group = GetLayerGroupNumberByPointer(Layer);
255
for (entry = 0; entry < PCB->LayerGroups.Number[group]; entry++)
257
Cardinal number = PCB->LayerGroups.Entries[group][entry];
260
/* skip solder/component layers */
261
if (number >= MAX_LAYER)
264
/* check all visible lines of the group member */
265
layer = &PCB->Data->Layer[number];
270
/* the following code just stupidly compares the endpoints
274
if (TEST_FLAG(CLEARLINEFLAG, line))
276
thick = (line->Thickness+1)/2;
277
if (IsPointInPolygon(line->Point1.X, line->Point1.Y,
279
CreateNewRubberbandEntry(layer, line, &line->Point1);
280
if (IsPointInPolygon(line->Point2.X, line->Point2.Y,
282
CreateNewRubberbandEntry(layer, line, &line->Point1);
344
CheckPinForRubberbandConnection (PinTypePtr Pin)
346
struct rubber_info info;
348
BDimension t = Pin->Thickness / 2;
350
info.box.X1 = Pin->X - t;
351
info.box.X2 = Pin->X + t;
352
info.box.Y1 = Pin->Y - t;
353
info.box.Y2 = Pin->Y + t;
355
if (TEST_FLAG (SQUAREFLAG, Pin))
364
for (n = 0; n < MAX_LAYER; n++)
366
info.layer = LAYER_PTR (n);
367
r_search (info.layer->line_tree, &info.box, NULL, rubber_callback,
372
/* ---------------------------------------------------------------------------
373
* checks all visible lines which belong to the same group as the passed line.
374
* If one of the endpoints of the line lays * inside the passed line,
375
* the scanned line is added to the 'rubberband' list
378
CheckLinePointForRubberbandConnection (LayerTypePtr Layer,
380
PointTypePtr LinePoint)
383
struct rubber_info info;
384
BDimension t = Line->Thickness / 2;
386
/* lookup layergroup and check all visible lines in this group */
387
info.radius = Line->Thickness / 2;
388
info.box.X1 = LinePoint->X - t;
389
info.box.X2 = LinePoint->X + t;;
390
info.box.Y1 = LinePoint->Y - t;
391
info.box.Y2 = LinePoint->Y + t;
393
info.X = LinePoint->X;
394
info.Y = LinePoint->Y;
395
group = GetLayerGroupNumberByPointer (Layer);
398
/* check all visible lines of the group member */
402
r_search (layer->line_tree, &info.box, NULL, rubber_callback, &info);
408
/* ---------------------------------------------------------------------------
409
* checks all visible lines which belong to the same group as the passed polygon.
410
* If one of the endpoints of the line lays inside the passed polygon,
411
* the scanned line is added to the 'rubberband' list
414
CheckPolygonForRubberbandConnection (LayerTypePtr Layer,
415
PolygonTypePtr Polygon)
419
/* lookup layergroup and check all visible lines in this group */
420
group = GetLayerGroupNumberByPointer (Layer);
427
/* the following code just stupidly compares the endpoints
432
if (TEST_FLAG (LOCKFLAG, line))
434
if (TEST_FLAG (CLEARLINEFLAG, line))
436
thick = (line->Thickness + 1) / 2;
437
if (IsPointInPolygon (line->Point1.X, line->Point1.Y,
439
CreateNewRubberbandEntry (layer, line, &line->Point1);
440
if (IsPointInPolygon (line->Point2.X, line->Point2.Y,
442
CreateNewRubberbandEntry (layer, line, &line->Point1);
288
450
/* ---------------------------------------------------------------------------
290
452
* data to 'Crosshair.AttachedObject.Rubberband'
291
453
* lookup is only done for visible layers
293
void LookupRubberbandLines(int Type, void *Ptr1, void *Ptr2, void *Ptr3)
456
LookupRubberbandLines (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
296
/* the function is only supported for some types
297
* check all visible lines;
298
* it is only necessary to check if one of the endpoints
305
ElementTypePtr element = (ElementTypePtr) Ptr1;
307
/* square pins are handled as if they are round. Speed
308
* and readability is more important then the few %
309
* of faiures that are immediately recognized
312
CheckPinForRubberbandConnection(pin);
315
CheckPadForRubberbandConnection(pad);
322
LayerTypePtr layer = (LayerTypePtr) Ptr1;
323
LineTypePtr line = (LineTypePtr) Ptr2;
324
if (GetLayerNumber(PCB->Data, layer) < MAX_LAYER)
326
CheckLinePointForRubberbandConnection(layer, line, &line->Point1);
327
CheckLinePointForRubberbandConnection(layer, line, &line->Point2);
333
if (GetLayerNumber(PCB->Data, (LayerTypePtr) Ptr1) < MAX_LAYER)
334
CheckLinePointForRubberbandConnection((LayerTypePtr) Ptr1,
335
(LineTypePtr) Ptr2, (PointTypePtr) Ptr3);
339
CheckPinForRubberbandConnection((PinTypePtr) Ptr1);
343
if (GetLayerNumber(PCB->Data, (LayerTypePtr) Ptr1) < MAX_LAYER)
344
CheckPolygonForRubberbandConnection((LayerTypePtr) Ptr1,
345
(PolygonTypePtr) Ptr2);
459
/* the function is only supported for some types
460
* check all visible lines;
461
* it is only necessary to check if one of the endpoints
468
ElementTypePtr element = (ElementTypePtr) Ptr1;
470
/* square pins are handled as if they are round. Speed
471
* and readability is more important then the few %
472
* of faiures that are immediately recognized
476
CheckPinForRubberbandConnection (pin);
481
CheckPadForRubberbandConnection (pad);
489
LayerTypePtr layer = (LayerTypePtr) Ptr1;
490
LineTypePtr line = (LineTypePtr) Ptr2;
491
if (GetLayerNumber (PCB->Data, layer) < MAX_LAYER)
493
CheckLinePointForRubberbandConnection (layer, line,
495
CheckLinePointForRubberbandConnection (layer, line,
502
if (GetLayerNumber (PCB->Data, (LayerTypePtr) Ptr1) < MAX_LAYER)
503
CheckLinePointForRubberbandConnection ((LayerTypePtr) Ptr1,
505
(PointTypePtr) Ptr3);
509
CheckPinForRubberbandConnection ((PinTypePtr) Ptr1);
513
if (GetLayerNumber (PCB->Data, (LayerTypePtr) Ptr1) < MAX_LAYER)
514
CheckPolygonForRubberbandConnection ((LayerTypePtr) Ptr1,
515
(PolygonTypePtr) Ptr2);
350
void LookupRatLines(int Type, void *Ptr1, void *Ptr2, void *Ptr3)
521
LookupRatLines (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
356
ElementTypePtr element = (ElementTypePtr) Ptr1;
359
CheckPinForRat(pin););
361
CheckPadForRat(pad););
367
LayerTypePtr layer = (LayerTypePtr) Ptr1;
368
LineTypePtr line = (LineTypePtr) Ptr2;
370
CheckLinePointForRat(layer, &line->Point1);
371
CheckLinePointForRat(layer, &line->Point2);
376
CheckLinePointForRat((LayerTypePtr) Ptr1,
377
(PointTypePtr) Ptr3);
381
CheckPinForRat((PinTypePtr) Ptr1);
527
ElementTypePtr element = (ElementTypePtr) Ptr1;
531
CheckPinForRat (pin);
536
CheckPadForRat (pad);
544
LayerTypePtr layer = (LayerTypePtr) Ptr1;
545
LineTypePtr line = (LineTypePtr) Ptr2;
547
CheckLinePointForRat (layer, &line->Point1);
548
CheckLinePointForRat (layer, &line->Point2);
553
CheckLinePointForRat ((LayerTypePtr) Ptr1, (PointTypePtr) Ptr3);
557
CheckPinForRat ((PinTypePtr) Ptr1);