~ubuntu-branches/ubuntu/precise/pcb/precise

« back to all changes in this revision

Viewing changes to src/rubberband.c

  • Committer: Bazaar Package Importer
  • Author(s): Hamish Moffatt
  • Date: 2005-02-20 13:14:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050220131400-pfz66g5vhx0azl8f
Tags: 1.99j+20050127-2
* Improved package description: (closes: #295405)
* Fixed dependency: tk84 -> tk8.4 (closes: #295404)
* Updated README.debian (closes: #269578)
* Applied patch to src/djopt.c to allow compilation with gcc-4.0
  (closes: #294319), thanks to Andreas Jochens for the patch.
* Prevent example files from being compressed

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: rubberband.c,v 1.12 2005/01/03 12:57:00 danmc Exp $ */
 
2
 
1
3
/*
2
4
 *                            COPYRIGHT
3
5
 *
24
26
 *
25
27
 */
26
28
 
27
 
static  char    *rcsid = "$Id: rubberband.c,v 1.2 1998/02/21 10:27:14 cad Exp $";
28
29
 
29
30
/* functions used by 'rubberband moves'
30
31
 */
31
32
 
 
33
#ifdef HAVE_CONFIG_H
 
34
#include "config.h"
 
35
#endif
 
36
 
32
37
#include <stdlib.h>
 
38
#ifdef HAVE_STRING_H
33
39
#include <string.h>
 
40
#endif
34
41
#include <memory.h>
35
42
#include <math.h>
 
43
#ifdef HAVE_UNISTD_H
36
44
#include <unistd.h>
 
45
#endif
37
46
 
38
47
#include "global.h"
39
48
 
40
49
#include "create.h"
41
50
#include "data.h"
 
51
#include "error.h"
42
52
#include "misc.h"
43
53
#include "rubberband.h"
 
54
#include "rtree.h"
44
55
#include "search.h"
45
56
 
 
57
#ifdef HAVE_LIBDMALLOC
 
58
#include <dmalloc.h>
 
59
#endif
 
60
 
 
61
RCSID("$Id: rubberband.c,v 1.12 2005/01/03 12:57:00 danmc Exp $");
 
62
 
 
63
 
46
64
/* ---------------------------------------------------------------------------
47
65
 * some local prototypes
48
66
 */
49
 
static  void    CheckPadForRubberbandConnection(PadTypePtr);
50
 
static  void    CheckPinForRubberbandConnection(PinTypePtr);
51
 
static  void    CheckLinePointForRubberbandConnection(LayerTypePtr,
52
 
                                        LineTypePtr, PointTypePtr);
53
 
static  void    CheckPolygonForRubberbandConnection(LayerTypePtr,
54
 
                                        PolygonTypePtr);
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,
 
72
                                                 PolygonTypePtr);
 
73
static void CheckLinePointForRat (LayerTypePtr, PointTypePtr);
 
74
static int rubber_callback (const BoxType * b, void *cl);
 
75
 
 
76
struct rubber_info
 
77
{
 
78
  int radius;
 
79
  LocationType X, Y;
 
80
  LineTypePtr line;
 
81
  BoxType box;
 
82
  LayerTypePtr layer;
 
83
};
 
84
 
 
85
static int
 
86
rubber_callback (const BoxType * b, void *cl)
 
87
{
 
88
  LineTypePtr line = (LineTypePtr) b;
 
89
  struct rubber_info *i = (struct rubber_info *) cl;
 
90
  float x, y;
 
91
  BDimension t;
 
92
  int touches = 0;
 
93
 
 
94
  t = line->Thickness / 2;
 
95
 
 
96
  if (TEST_FLAG (LOCKFLAG, line))
 
97
    return 0;
 
98
  if (line == i->line)
 
99
    return 0;
 
100
  /* 
 
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.
 
104
   */
 
105
  if (i->radius == 0)
 
106
    {
 
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)
 
110
        {
 
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)) )
 
115
            {
 
116
              /* 
 
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
 
122
               */
 
123
              touches = 1;
 
124
            }
 
125
          else
 
126
            {
 
127
              /* 
 
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.
 
131
               */
 
132
              x = MIN (abs(i->box.X1 - line->Point1.X),
 
133
                       abs(i->box.X2 - line->Point1.X) );
 
134
              x *= x;
 
135
              y = MIN (abs(i->box.Y1 - line->Point1.Y),
 
136
                       abs(i->box.Y2 - line->Point1.Y));
 
137
              y *= y;
 
138
              x = x + y - (t * t);
 
139
 
 
140
              if ( x <= 0 )
 
141
                touches = 1;
 
142
            }
 
143
          if (touches)
 
144
            {
 
145
              CreateNewRubberbandEntry (i->layer, line, &line->Point1);
 
146
              return 1;
 
147
            }
 
148
        }
 
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)
 
152
        {
 
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)) )
 
157
            {
 
158
              touches = 1;
 
159
            }
 
160
          else
 
161
            {
 
162
              x = MIN (abs(i->box.X1 - line->Point2.X),
 
163
                       abs(i->box.X2 - line->Point2.X) );
 
164
              x *= x;
 
165
              y = MIN (abs(i->box.Y1 - line->Point2.Y),
 
166
                       abs(i->box.Y2 - line->Point2.Y));
 
167
              y *= y;
 
168
              x = x + y - (t * t);
 
169
 
 
170
              if ( x <= 0 )
 
171
                touches = 1;
 
172
            }
 
173
          if (touches)
 
174
            {
 
175
              CreateNewRubberbandEntry (i->layer, line, &line->Point2);
 
176
              return 1;
 
177
            }
 
178
        }
 
179
      return 0;
 
180
    }
 
181
  /* circular search region */
 
182
  x = (i->X - line->Point1.X);
 
183
  x *= x;
 
184
  y = (i->Y - line->Point1.Y);
 
185
  y *= y;
 
186
  x = x + y - (t * t);
 
187
  if (x < (i->radius * (i->radius + 2 * t)))
 
188
    {
 
189
      CreateNewRubberbandEntry (i->layer, line, &line->Point1);
 
190
      return 1;
 
191
    }
 
192
  x = (i->X - line->Point2.X);
 
193
  x *= x;
 
194
  y = (i->Y - line->Point2.Y);
 
195
  y *= y;
 
196
  x = x + y - (t * t);
 
197
  if (x < (i->radius * (i->radius + 2 * t)))
 
198
    {
 
199
      CreateNewRubberbandEntry (i->layer, line, &line->Point2);
 
200
      return 1;
 
201
    }
 
202
  return 0;
 
203
}
56
204
 
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
61
209
 */
62
 
static void CheckPadForRubberbandConnection(PadTypePtr Pad)
63
 
{
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;
69
 
        Cardinal        i,
70
 
                        group;
71
 
 
72
 
        i = MAX_LAYER +
73
 
                (TEST_FLAG(ONSOLDERFLAG, Pad) ? SOLDER_LAYER : COMPONENT_LAYER);
74
 
        group = GetLayerGroupNumberByNumber(i);
75
 
 
76
 
                /* check all visible layers in the same group */
77
 
        for (i = 0; i < PCB->LayerGroups.Number[group]; i++)
78
 
        {
79
 
                Cardinal        number = PCB->LayerGroups.Entries[group][i];
80
 
                LayerTypePtr    layer;
81
 
 
82
 
                        /* skip solder/component layers */
83
 
                if (number >= MAX_LAYER)
84
 
                        continue;
85
 
 
86
 
                        /* check all visible lines of the group member */
87
 
                layer = &PCB->Data->Layer[number];
88
 
                if (layer->On)
89
 
                {
90
 
                        LINE_LOOP(layer,
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);
97
 
                        );
98
 
                }
99
 
        }
100
 
}
101
 
 
102
 
static void CheckPadForRat(PadTypePtr Pad)
103
 
{
104
 
        Cardinal        i,
105
 
                        group;
106
 
 
107
 
        i = MAX_LAYER +
108
 
                (TEST_FLAG(ONSOLDERFLAG, Pad) ? SOLDER_LAYER : COMPONENT_LAYER);
109
 
        group = GetLayerGroupNumberByNumber(i);
110
 
 
111
 
        RAT_LOOP(PCB->Data,
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);
115
 
                else
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);
120
 
                
121
 
        );
 
210
static void
 
211
CheckPadForRubberbandConnection (PadTypePtr Pad)
 
212
{
 
213
  BDimension half = Pad->Thickness / 2;
 
214
  Cardinal i, group;
 
215
  struct rubber_info info;
 
216
 
 
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;
 
221
  info.radius = 0;
 
222
  info.line = NULL;
 
223
  i = MAX_LAYER +
 
224
    (TEST_FLAG (ONSOLDERFLAG, Pad) ? SOLDER_LAYER : COMPONENT_LAYER);
 
225
  group = GetLayerGroupNumberByNumber (i);
 
226
 
 
227
  /* check all visible layers in the same group */
 
228
  GROUP_LOOP (group);
 
229
  {
 
230
    /* check all visible lines of the group member */
 
231
    info.layer = layer;
 
232
    if (info.layer->On)
 
233
      {
 
234
        r_search (info.layer->line_tree, &info.box, NULL, rubber_callback,
 
235
                  &info);
 
236
      }
 
237
  }
 
238
  END_LOOP;
 
239
}
 
240
 
 
241
struct rinfo
 
242
{
 
243
  int type;
 
244
  Cardinal group;
 
245
  PinTypePtr pin;
 
246
  PadTypePtr pad;
 
247
  PointTypePtr point;
 
248
};
 
249
 
 
250
static int
 
251
rat_callback (const BoxType * box, void *cl)
 
252
{
 
253
  RatTypePtr rat = (RatTypePtr) box;
 
254
  struct rinfo *i = (struct rinfo *) cl;
 
255
 
 
256
  switch (i->type)
 
257
    {
 
258
    case PIN_TYPE:
 
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);
 
263
      break;
 
264
    case PAD_TYPE:
 
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);
 
268
      else
 
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);
 
272
      else
 
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);
 
276
      else
 
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);
 
280
      break;
 
281
    case LINEPOINT_TYPE:
 
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);
 
285
      else
 
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);
 
289
      break;
 
290
    default:
 
291
      Message ("hace: bad rubber-rat lookup callback\n");
 
292
    }
 
293
  return 0;
 
294
}
 
295
 
 
296
static void
 
297
CheckPadForRat (PadTypePtr Pad)
 
298
{
 
299
  struct rinfo info;
 
300
  Cardinal i;
 
301
 
 
302
  i = MAX_LAYER +
 
303
    (TEST_FLAG (ONSOLDERFLAG, Pad) ? SOLDER_LAYER : COMPONENT_LAYER);
 
304
  info.group = GetLayerGroupNumberByNumber (i);
 
305
  info.pad = Pad;
 
306
  info.type = PAD_TYPE;
 
307
 
 
308
  r_search (PCB->Data->rat_tree, &Pad->BoundingBox, NULL, rat_callback,
 
309
            &info);
 
310
}
 
311
 
 
312
static void
 
313
CheckPinForRat (PinTypePtr Pin)
 
314
{
 
315
  struct rinfo info;
 
316
 
 
317
  info.type = PIN_TYPE;
 
318
  info.pin = Pin;
 
319
  r_search (PCB->Data->rat_tree, &Pin->BoundingBox, NULL, rat_callback,
 
320
            &info);
 
321
}
 
322
 
 
323
static void
 
324
CheckLinePointForRat (LayerTypePtr Layer, PointTypePtr Point)
 
325
{
 
326
  struct rinfo info;
 
327
  info.group = GetLayerGroupNumberByPointer (Layer);
 
328
  info.point = Point;
 
329
  info.type = LINEPOINT_TYPE;
 
330
 
 
331
  r_search (PCB->Data->rat_tree, (BoxType *) Point, NULL, rat_callback,
 
332
            &info);
122
333
}
123
334
 
124
335
/* ---------------------------------------------------------------------------
129
340
 * and readability is more important then the few %
130
341
 * of faiures that are immediately recognized
131
342
 */
132
 
static void CheckPinForRubberbandConnection(PinTypePtr Pin)
133
 
{
134
 
        register        float   radius,
135
 
                        dx, dy;
136
 
 
137
 
        VISIBLELINE_LOOP(PCB->Data,
138
 
                        /* save sqrt computation */
139
 
                radius = (float) (Pin->Thickness +line->Thickness) /2.0;
140
 
                radius *= radius;
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);
145
 
                else
146
 
                {
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);
151
 
                }
152
 
        );
153
 
}
154
 
 
155
 
static void CheckPinForRat(PinTypePtr Pin)
156
 
{
157
 
        RAT_LOOP(PCB->Data,
158
 
                if (line->Point1.X == Pin->X && line->Point1.Y == Pin->Y)
159
 
                        CreateNewRubberbandEntry(NULL, (LineTypePtr) line, &line->Point1);
160
 
                else
161
 
                        if (line->Point2.X == Pin->X && line->Point2.Y == Pin->Y)
162
 
                                CreateNewRubberbandEntry(NULL, (LineTypePtr) line, &line->Point2);
163
 
        );
164
 
}
165
 
 
166
 
static void CheckLinePointForRat(LayerTypePtr Layer, PointTypePtr Point)
167
 
{
168
 
        Cardinal        group = GetLayerGroupNumberByPointer(Layer);
169
 
 
170
 
        RAT_LOOP(PCB->Data,
171
 
                if (line->group1 == group &&
172
 
                    line->Point1.X == Point->X && line->Point1.Y == Point->Y)
173
 
                        CreateNewRubberbandEntry(NULL, (LineTypePtr) line, &line->Point1);
174
 
                else
175
 
                        if (line->group2 == group &&
176
 
                            line->Point2.X == Point->X && line->Point2.Y == Point->Y)
177
 
                                CreateNewRubberbandEntry(NULL, (LineTypePtr) line, &line->Point2);
178
 
        );
179
 
}
180
 
 
181
 
 
182
 
 
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
187
 
 */
188
 
static void CheckLinePointForRubberbandConnection(LayerTypePtr Layer,
189
 
        LineTypePtr Line, PointTypePtr LinePoint)
190
 
{
191
 
        Cardinal        group,
192
 
                        entry;
193
 
 
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++)
197
 
        {
198
 
                Cardinal        number = PCB->LayerGroups.Entries[group][entry];
199
 
                LayerTypePtr    layer;
200
 
 
201
 
                        /* skip solder/component layers */
202
 
                if (number >= MAX_LAYER)
203
 
                        continue;
204
 
 
205
 
                        /* check all visible lines of the group member */
206
 
                layer = &PCB->Data->Layer[number];
207
 
                if (layer->On)
208
 
                {
209
 
                        register        float   radius,
210
 
                                                dx, dy;
211
 
 
212
 
                                /* the following code just compares the endpoints
213
 
                                 * of the lines
214
 
                                 */
215
 
                        LINE_LOOP(layer,
216
 
                                        /* skip the original line */
217
 
                                if (line == Line)
218
 
                                        continue;
219
 
 
220
 
                                        /* save sqrt computation */
221
 
                                radius = (float) (Line->Thickness +line->Thickness) /2.0;
222
 
                                radius *= radius;
223
 
                                dx = line->Point1.X -LinePoint->X;
224
 
                                dy = line->Point1.Y -LinePoint->Y;
225
 
                                if (dx*dx+dy*dy <= radius)
226
 
                                {
227
 
                                        CreateNewRubberbandEntry(layer, line, &line->Point1);
228
 
                                        continue;
229
 
                                }
230
 
                                dx = line->Point2.X -LinePoint->X;
231
 
                                dy = line->Point2.Y -LinePoint->Y;
232
 
                                if (dx*dx+dy*dy <= radius)
233
 
                                {
234
 
                                        CreateNewRubberbandEntry(layer, line, &line->Point2);
235
 
                                        continue;
236
 
                                }
237
 
                        );
238
 
                }
239
 
        }
240
 
}
241
 
 
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
246
 
 */
247
 
static void CheckPolygonForRubberbandConnection(LayerTypePtr Layer,
248
 
        PolygonTypePtr Polygon)
249
 
{
250
 
        Cardinal        group,
251
 
                        entry;
252
 
 
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++)
256
 
        {
257
 
                Cardinal        number = PCB->LayerGroups.Entries[group][entry];
258
 
                LayerTypePtr    layer;
259
 
 
260
 
                        /* skip solder/component layers */
261
 
                if (number >= MAX_LAYER)
262
 
                        continue;
263
 
 
264
 
                        /* check all visible lines of the group member */
265
 
                layer = &PCB->Data->Layer[number];
266
 
                if (layer->On)
267
 
                {
268
 
                        Dimension       thick;
269
 
 
270
 
                                /* the following code just stupidly compares the endpoints
271
 
                                 * of the lines
272
 
                                 */
273
 
                        LINE_LOOP(layer,
274
 
                                if (TEST_FLAG(CLEARLINEFLAG, line))
275
 
                                        continue;
276
 
                                thick = (line->Thickness+1)/2;
277
 
                                if (IsPointInPolygon(line->Point1.X, line->Point1.Y,
278
 
                                        thick, Polygon))
279
 
                                        CreateNewRubberbandEntry(layer, line, &line->Point1);
280
 
                                if (IsPointInPolygon(line->Point2.X, line->Point2.Y,
281
 
                                        thick, Polygon))
282
 
                                        CreateNewRubberbandEntry(layer, line, &line->Point1);
283
 
                        );
284
 
                }
285
 
        }
 
343
static void
 
344
CheckPinForRubberbandConnection (PinTypePtr Pin)
 
345
{
 
346
  struct rubber_info info;
 
347
  Cardinal n;
 
348
  BDimension t = Pin->Thickness / 2;
 
349
 
 
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;
 
354
  info.line = NULL;
 
355
  if (TEST_FLAG (SQUAREFLAG, Pin))
 
356
    info.radius = 0;
 
357
  else
 
358
    {
 
359
      info.radius = t;
 
360
      info.X = Pin->X;
 
361
      info.Y = Pin->Y;
 
362
    }
 
363
 
 
364
  for (n = 0; n < MAX_LAYER; n++)
 
365
    {
 
366
      info.layer = LAYER_PTR (n);
 
367
      r_search (info.layer->line_tree, &info.box, NULL, rubber_callback,
 
368
                &info);
 
369
    }
 
370
}
 
371
 
 
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
 
376
 */
 
377
static void
 
378
CheckLinePointForRubberbandConnection (LayerTypePtr Layer,
 
379
                                       LineTypePtr Line,
 
380
                                       PointTypePtr LinePoint)
 
381
{
 
382
  Cardinal group;
 
383
  struct rubber_info info;
 
384
  BDimension t = Line->Thickness / 2;
 
385
 
 
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;
 
392
  info.line = Line;
 
393
  info.X = LinePoint->X;
 
394
  info.Y = LinePoint->Y;
 
395
  group = GetLayerGroupNumberByPointer (Layer);
 
396
  GROUP_LOOP (group);
 
397
  {
 
398
    /* check all visible lines of the group member */
 
399
    if (layer->On)
 
400
      {
 
401
        info.layer = layer;
 
402
        r_search (layer->line_tree, &info.box, NULL, rubber_callback, &info);
 
403
      }
 
404
  }
 
405
  END_LOOP;
 
406
}
 
407
 
 
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
 
412
 */
 
413
static void
 
414
CheckPolygonForRubberbandConnection (LayerTypePtr Layer,
 
415
                                     PolygonTypePtr Polygon)
 
416
{
 
417
  Cardinal group;
 
418
 
 
419
  /* lookup layergroup and check all visible lines in this group */
 
420
  group = GetLayerGroupNumberByPointer (Layer);
 
421
  GROUP_LOOP (group);
 
422
  {
 
423
    if (layer->On)
 
424
      {
 
425
        BDimension thick;
 
426
 
 
427
        /* the following code just stupidly compares the endpoints
 
428
         * of the lines
 
429
         */
 
430
        LINE_LOOP (layer);
 
431
        {
 
432
          if (TEST_FLAG (LOCKFLAG, line))
 
433
            continue;
 
434
          if (TEST_FLAG (CLEARLINEFLAG, line))
 
435
            continue;
 
436
          thick = (line->Thickness + 1) / 2;
 
437
          if (IsPointInPolygon (line->Point1.X, line->Point1.Y,
 
438
                                thick, Polygon))
 
439
            CreateNewRubberbandEntry (layer, line, &line->Point1);
 
440
          if (IsPointInPolygon (line->Point2.X, line->Point2.Y,
 
441
                                thick, Polygon))
 
442
            CreateNewRubberbandEntry (layer, line, &line->Point1);
 
443
        }
 
444
        END_LOOP;
 
445
      }
 
446
  }
 
447
  END_LOOP;
286
448
}
287
449
 
288
450
/* ---------------------------------------------------------------------------
290
452
 * data to 'Crosshair.AttachedObject.Rubberband'
291
453
 * lookup is only done for visible layers
292
454
 */
293
 
void LookupRubberbandLines(int Type, void *Ptr1, void *Ptr2, void *Ptr3)
 
455
void
 
456
LookupRubberbandLines (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
294
457
{
295
458
 
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
299
 
                 * is connected
300
 
                 */
301
 
        switch(Type)
302
 
        {
303
 
                case ELEMENT_TYPE:
304
 
                {
305
 
                        ElementTypePtr  element = (ElementTypePtr) Ptr1;
306
 
 
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
310
 
                                 */
311
 
                        PIN_LOOP(element,
312
 
                                CheckPinForRubberbandConnection(pin);
313
 
                        );
314
 
                        PAD_LOOP(element,
315
 
                                CheckPadForRubberbandConnection(pad);
316
 
                        );
317
 
                        break;
318
 
                }
319
 
 
320
 
                case LINE_TYPE:
321
 
                {
322
 
                        LayerTypePtr    layer = (LayerTypePtr) Ptr1;
323
 
                        LineTypePtr     line = (LineTypePtr) Ptr2;
324
 
                        if (GetLayerNumber(PCB->Data, layer) < MAX_LAYER)
325
 
                        {
326
 
                                CheckLinePointForRubberbandConnection(layer, line, &line->Point1);
327
 
                                CheckLinePointForRubberbandConnection(layer, line, &line->Point2);
328
 
                        }
329
 
                        break;
330
 
                }
331
 
 
332
 
                case LINEPOINT_TYPE:
333
 
                        if (GetLayerNumber(PCB->Data, (LayerTypePtr) Ptr1) < MAX_LAYER)
334
 
                                CheckLinePointForRubberbandConnection((LayerTypePtr) Ptr1,
335
 
                                        (LineTypePtr) Ptr2, (PointTypePtr) Ptr3);
336
 
                        break;
337
 
 
338
 
                case VIA_TYPE:
339
 
                        CheckPinForRubberbandConnection((PinTypePtr) Ptr1);
340
 
                        break;
341
 
 
342
 
                case POLYGON_TYPE:
343
 
                        if (GetLayerNumber(PCB->Data, (LayerTypePtr) Ptr1) < MAX_LAYER)
344
 
                                CheckPolygonForRubberbandConnection((LayerTypePtr) Ptr1,
345
 
                                        (PolygonTypePtr) Ptr2);
346
 
                        break;
347
 
        }
 
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
 
462
   * is connected
 
463
   */
 
464
  switch (Type)
 
465
    {
 
466
    case ELEMENT_TYPE:
 
467
      {
 
468
        ElementTypePtr element = (ElementTypePtr) Ptr1;
 
469
 
 
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
 
473
         */
 
474
        PIN_LOOP (element);
 
475
        {
 
476
          CheckPinForRubberbandConnection (pin);
 
477
        }
 
478
        END_LOOP;
 
479
        PAD_LOOP (element);
 
480
        {
 
481
          CheckPadForRubberbandConnection (pad);
 
482
        }
 
483
        END_LOOP;
 
484
        break;
 
485
      }
 
486
 
 
487
    case LINE_TYPE:
 
488
      {
 
489
        LayerTypePtr layer = (LayerTypePtr) Ptr1;
 
490
        LineTypePtr line = (LineTypePtr) Ptr2;
 
491
        if (GetLayerNumber (PCB->Data, layer) < MAX_LAYER)
 
492
          {
 
493
            CheckLinePointForRubberbandConnection (layer, line,
 
494
                                                   &line->Point1);
 
495
            CheckLinePointForRubberbandConnection (layer, line,
 
496
                                                   &line->Point2);
 
497
          }
 
498
        break;
 
499
      }
 
500
 
 
501
    case LINEPOINT_TYPE:
 
502
      if (GetLayerNumber (PCB->Data, (LayerTypePtr) Ptr1) < MAX_LAYER)
 
503
        CheckLinePointForRubberbandConnection ((LayerTypePtr) Ptr1,
 
504
                                               (LineTypePtr) Ptr2,
 
505
                                               (PointTypePtr) Ptr3);
 
506
      break;
 
507
 
 
508
    case VIA_TYPE:
 
509
      CheckPinForRubberbandConnection ((PinTypePtr) Ptr1);
 
510
      break;
 
511
 
 
512
    case POLYGON_TYPE:
 
513
      if (GetLayerNumber (PCB->Data, (LayerTypePtr) Ptr1) < MAX_LAYER)
 
514
        CheckPolygonForRubberbandConnection ((LayerTypePtr) Ptr1,
 
515
                                             (PolygonTypePtr) Ptr2);
 
516
      break;
 
517
    }
348
518
}
349
519
 
350
 
void LookupRatLines(int Type, void *Ptr1, void *Ptr2, void *Ptr3)
 
520
void
 
521
LookupRatLines (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
351
522
{
352
 
        switch(Type)
353
 
        {
354
 
                case ELEMENT_TYPE:
355
 
                {
356
 
                        ElementTypePtr  element = (ElementTypePtr) Ptr1;
357
 
 
358
 
                        PIN_LOOP(element,
359
 
                                CheckPinForRat(pin););
360
 
                        PAD_LOOP(element,
361
 
                                CheckPadForRat(pad););
362
 
                        break;
363
 
                }
364
 
 
365
 
                case LINE_TYPE:
366
 
                {
367
 
                        LayerTypePtr    layer = (LayerTypePtr) Ptr1;
368
 
                        LineTypePtr     line = (LineTypePtr) Ptr2;
369
 
 
370
 
                        CheckLinePointForRat(layer, &line->Point1);
371
 
                        CheckLinePointForRat(layer, &line->Point2);
372
 
                        break;
373
 
                }
374
 
 
375
 
                case LINEPOINT_TYPE:
376
 
                        CheckLinePointForRat((LayerTypePtr) Ptr1,
377
 
                                (PointTypePtr) Ptr3);
378
 
                        break;
379
 
 
380
 
                case VIA_TYPE:
381
 
                        CheckPinForRat((PinTypePtr) Ptr1);
382
 
                        break;
383
 
        }
 
523
  switch (Type)
 
524
    {
 
525
    case ELEMENT_TYPE:
 
526
      {
 
527
        ElementTypePtr element = (ElementTypePtr) Ptr1;
 
528
 
 
529
        PIN_LOOP (element);
 
530
        {
 
531
          CheckPinForRat (pin);
 
532
        }
 
533
        END_LOOP;
 
534
        PAD_LOOP (element);
 
535
        {
 
536
          CheckPadForRat (pad);
 
537
        }
 
538
        END_LOOP;
 
539
        break;
 
540
      }
 
541
 
 
542
    case LINE_TYPE:
 
543
      {
 
544
        LayerTypePtr layer = (LayerTypePtr) Ptr1;
 
545
        LineTypePtr line = (LineTypePtr) Ptr2;
 
546
 
 
547
        CheckLinePointForRat (layer, &line->Point1);
 
548
        CheckLinePointForRat (layer, &line->Point2);
 
549
        break;
 
550
      }
 
551
 
 
552
    case LINEPOINT_TYPE:
 
553
      CheckLinePointForRat ((LayerTypePtr) Ptr1, (PointTypePtr) Ptr3);
 
554
      break;
 
555
 
 
556
    case VIA_TYPE:
 
557
      CheckPinForRat ((PinTypePtr) Ptr1);
 
558
      break;
 
559
    }
384
560
}