/*! * \brief Checks all visible lines which belong to the same group as the * passed arc. * * If one of the endpoints of the line lays inside the passed arc, * the scanned line is added to the 'rubberband' list */ static void CheckArcPointForRubberbandConnection (LayerType *Layer, ArcType *Arc, PointType *ArcPoint, bool Exact) { Cardinal group; struct rubber_info info; Coord t = Arc->Thickness / 2; /* lookup layergroup and check all visible lines in this group */ info.radius = Exact ? -1 : MAX(Arc->Thickness / 2, 1); info.box.X1 = ArcPoint->X - t; info.box.X2 = ArcPoint->X + t; info.box.Y1 = ArcPoint->Y - t; info.box.Y2 = ArcPoint->Y + t; info.line = NULL; info.X = ArcPoint->X; info.Y = ArcPoint->Y; group = GetLayerGroupNumberByPointer (Layer); GROUP_LOOP (PCB->Data, group); { /* check all visible lines of the group member */ if (layer->On) { info.layer = layer; r_search (layer->line_tree, &info.box, NULL, rubber_callback, &info); } } END_LOOP; }
/*! * \brief Checks all visible lines which belong to the same layergroup * as the passed pad. * * If one of the endpoints of the line lays inside the pad, the line is * added to the 'rubberband' list. */ static void CheckPadForRubberbandConnection (PadType *Pad) { Coord half = Pad->Thickness / 2; Cardinal group; struct rubber_info info; info.box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - half; info.box.Y1 = MIN (Pad->Point1.Y, Pad->Point2.Y) - half; info.box.X2 = MAX (Pad->Point1.X, Pad->Point2.X) + half; info.box.Y2 = MAX (Pad->Point1.Y, Pad->Point2.Y) + half; info.radius = 0; info.line = NULL; group = GetLayerGroupNumberBySide ( TEST_FLAG (ONSOLDERFLAG, Pad) ? BOTTOM_SIDE : TOP_SIDE); /* check all visible layers in the same group */ GROUP_LOOP (PCB->Data, group); { /* check all visible lines of the group member */ info.layer = layer; if (info.layer->On) { r_search (info.layer->line_tree, &info.box, NULL, rubber_callback, &info); } } END_LOOP; }
/* --------------------------------------------------------------------------- * checks all visible lines which belong to the same layergroup as the * passed pad. If one of the endpoints of the line lays inside the pad, * the line is added to the 'rubberband' list */ static void CheckPadForRubberbandConnection (PadTypePtr Pad) { BDimension half = Pad->Thickness / 2; Cardinal i, group; struct rubber_info info; info.box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - half; info.box.Y1 = MIN (Pad->Point1.Y, Pad->Point2.Y) - half; info.box.X2 = MAX (Pad->Point1.X, Pad->Point2.X) + half; info.box.Y2 = MAX (Pad->Point1.Y, Pad->Point2.Y) + half; info.radius = 0; info.line = NULL; i = TEST_FLAG (ONSOLDERFLAG, Pad) ? solder_silk_layer : component_silk_layer; group = GetLayerGroupNumberByNumber (i); /* check all visible layers in the same group */ GROUP_LOOP (PCB->Data, group); { /* check all visible lines of the group member */ info.layer = layer; if (info.layer->On) { r_search (info.layer->line_tree, &info.box, NULL, rubber_callback, &info); } } END_LOOP; }
/* --------------------------------------------------------------------------- * checks all visible lines which belong to the same group as the passed polygon. * If one of the endpoints of the line lays inside the passed polygon, * the scanned line is added to the 'rubberband' list. */ static void CheckPolygonForRubberbandConnection (LayerType *Layer, PolygonType *Polygon) { Cardinal group; /* lookup layergroup and check all visible lines in this group */ group = GetLayerGroupNumberByPointer (Layer); GROUP_LOOP (PCB->Data, group); { if (layer->On) { Coord thick; /* the following code just stupidly compares the endpoints * of the lines */ LINE_LOOP (layer); { if (TEST_FLAG (LOCKFLAG, line)) continue; if (TEST_FLAG (CLEARLINEFLAG, line)) continue; thick = (line->Thickness + 1) / 2; if (IsPointInPolygon (line->Point1.X, line->Point1.Y, thick, Polygon)) CreateNewRubberbandEntry (layer, line, &line->Point1); if (IsPointInPolygon (line->Point2.X, line->Point2.Y, thick, Polygon)) CreateNewRubberbandEntry (layer, line, &line->Point2); } END_LOOP; } } END_LOOP; }
/* --------------------------------------------------------------------------- * recalculates the passed coordinates to fit the current grid setting */ void FitCrosshairIntoGrid (LocationType X, LocationType Y) { LocationType x2, y2, x0, y0; void *ptr1, *ptr2, *ptr3; float nearest, sq_dist; int ans; x0 = 0; y0 = 0; x2 = PCB->MaxWidth; y2 = PCB->MaxHeight; Crosshair.X = MIN (Crosshair.MaxX, MAX (Crosshair.MinX, X)); Crosshair.Y = MIN (Crosshair.MaxY, MAX (Crosshair.MinY, Y)); if (PCB->RatDraw) { x0 = -600; y0 = -600; } else { /* check if new position is inside the output window * This might not be true after the window has been resized. * In this case we just set it to the center of the window or * with respect to the grid (if possible) */ if (Crosshair.X < x0 || Crosshair.X > x2) { if (x2 + 1 >= PCB->Grid) /* there must be a point that matches the grid * so we just have to look for it with some integer * calculations */ x0 = GRIDFIT_X (PCB->Grid, PCB->Grid); else x0 = (x2) / 2; } else /* check if the new position matches the grid */ x0 = GRIDFIT_X (Crosshair.X, PCB->Grid); /* do the same for the second coordinate */ if (Crosshair.Y < y0 || Crosshair.Y > y2) { if (y2 + 1 >= PCB->Grid) y0 = GRIDFIT_Y (PCB->Grid, PCB->Grid); else y0 = (y2) / 2; } else y0 = GRIDFIT_Y (Crosshair.Y, PCB->Grid); if (Marked.status && TEST_FLAG (ORTHOMOVEFLAG, PCB)) { int dx = Crosshair.X - Marked.X; int dy = Crosshair.Y - Marked.Y; if (ABS (dx) > ABS (dy)) y0 = Marked.Y; else x0 = Marked.X; } } nearest = -1; if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, PAD_TYPE, &ptr1, &ptr2, &ptr3); else ans = NO_TYPE; /* Avoid self-snapping when moving */ if (ans && Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == ELEMENT_TYPE && ptr1 == Crosshair.AttachedObject.Ptr1) ans = NO_TYPE; if (ans && (Settings.Mode == LINE_MODE || (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == LINEPOINT_TYPE))) { PadTypePtr pad = (PadTypePtr) ptr2; LayerType *desired_layer; Cardinal desired_group; Cardinal SLayer, CLayer; int found_our_layer = false; desired_layer = CURRENT; if (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == LINEPOINT_TYPE) { desired_layer = (LayerType *)Crosshair.AttachedObject.Ptr1; } /* find layer groups of the component side and solder side */ SLayer = GetLayerGroupNumberByNumber (solder_silk_layer); CLayer = GetLayerGroupNumberByNumber (component_silk_layer); desired_group = TEST_FLAG (ONSOLDERFLAG, pad) ? SLayer : CLayer; GROUP_LOOP (PCB->Data, desired_group); { if (layer == desired_layer) { found_our_layer = true; break; } } END_LOOP; if (found_our_layer == false) ans = NO_TYPE; } if (ans) { PadTypePtr pad = (PadTypePtr) ptr2; LocationType px, py; px = (pad->Point1.X + pad->Point2.X) / 2; py = (pad->Point1.Y + pad->Point2.Y) / 2; sq_dist = SQUARE (px - Crosshair.X) + SQUARE (py - Crosshair.Y); if (!gui->shift_is_pressed() || SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist) { x0 = px; y0 = py; nearest = sq_dist; } } if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, PIN_TYPE, &ptr1, &ptr2, &ptr3); else ans = NO_TYPE; /* Avoid self-snapping when moving */ if (ans && Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == ELEMENT_TYPE && ptr1 == Crosshair.AttachedObject.Ptr1) ans = NO_TYPE; if (ans) { PinTypePtr pin = (PinTypePtr) ptr2; sq_dist = SQUARE (pin->X - Crosshair.X) + SQUARE (pin->Y - Crosshair.Y); if ((nearest == -1 || sq_dist < nearest) && (!gui->shift_is_pressed() || SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist)) { x0 = pin->X; y0 = pin->Y; nearest = sq_dist; } } if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, VIA_TYPE, &ptr1, &ptr2, &ptr3); else ans = NO_TYPE; /* Avoid snapping vias to any other vias */ if (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == VIA_TYPE) { if (ans & PIN_TYPES) ans = NO_TYPE; } if (ans) { PinTypePtr pin = (PinTypePtr) ptr2; sq_dist = SQUARE (pin->X - Crosshair.X) + SQUARE (pin->Y - Crosshair.Y); if ((nearest == -1 || sq_dist < nearest) && (!gui->shift_is_pressed() || SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist)) { x0 = pin->X; y0 = pin->Y; nearest = sq_dist; } } if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, LINEPOINT_TYPE, &ptr1, &ptr2, &ptr3); else ans = NO_TYPE; if (ans) { PointTypePtr pnt = (PointTypePtr) ptr3; sq_dist = SQUARE (pnt->X - Crosshair.X) + SQUARE (pnt->Y - Crosshair.Y); if ((nearest == -1 || sq_dist < nearest) && (!gui->shift_is_pressed() || SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist)) { x0 = pnt->X; y0 = pnt->Y; nearest = sq_dist; } } if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, POLYGONPOINT_TYPE, &ptr1, &ptr2, &ptr3); else ans = NO_TYPE; if (ans) { PointTypePtr pnt = (PointTypePtr) ptr3; sq_dist = SQUARE (pnt->X - Crosshair.X) + SQUARE (pnt->Y - Crosshair.Y); if ((nearest == -1 || sq_dist < nearest) && (!gui->shift_is_pressed() || SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist)) { x0 = pnt->X; y0 = pnt->Y; nearest = sq_dist; } } if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, ELEMENT_TYPE, &ptr1, &ptr2, &ptr3); else ans = NO_TYPE; if (ans & ELEMENT_TYPE) { ElementTypePtr el = (ElementTypePtr) ptr1; sq_dist = SQUARE (el->MarkX - Crosshair.X) + SQUARE (el->MarkY - Crosshair.Y); if ((nearest == -1 || sq_dist < nearest) && SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist) { x0 = el->MarkX; y0 = el->MarkY; nearest = sq_dist; } } if (x0 >= 0 && y0 >= 0) { Crosshair.X = x0; Crosshair.Y = y0; } if (Settings.Mode == ARROW_MODE) { ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, LINEPOINT_TYPE, &ptr1, &ptr2, &ptr3); if (ans == NO_TYPE) hid_action("PointCursor"); else if (!TEST_FLAG(SELECTEDFLAG, (LineType *)ptr2)) hid_actionl("PointCursor","True", NULL); } if (Settings.Mode == LINE_MODE && Crosshair.AttachedLine.State != STATE_FIRST && TEST_FLAG (AUTODRCFLAG, PCB)) EnforceLineDRC (); gui->set_crosshair (Crosshair.X, Crosshair.Y, HID_SC_DO_NOTHING); }
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; }
/*--------------------------------------------------------------------------- * * 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); }
/* --------------------------------------------------------------------------- * recalculates the passed coordinates to fit the current grid setting */ void FitCrosshairIntoGrid (Coord X, Coord Y) { Coord nearest_grid_x, nearest_grid_y; void *ptr1, *ptr2, *ptr3; struct snap_data snap_data; int ans; Crosshair.X = CLAMP (X, Crosshair.MinX, Crosshair.MaxX); Crosshair.Y = CLAMP (Y, Crosshair.MinY, Crosshair.MaxY); if (PCB->RatDraw) { nearest_grid_x = -MIL_TO_COORD (6); nearest_grid_y = -MIL_TO_COORD (6); } else { nearest_grid_x = GridFit (Crosshair.X, PCB->Grid, PCB->GridOffsetX); nearest_grid_y = GridFit (Crosshair.Y, PCB->Grid, PCB->GridOffsetY); if (Marked.status && TEST_FLAG (ORTHOMOVEFLAG, PCB)) { Coord dx = Crosshair.X - Marked.X; Coord dy = Crosshair.Y - Marked.Y; if (ABS (dx) > ABS (dy)) nearest_grid_y = Marked.Y; else nearest_grid_x = Marked.X; } } snap_data.crosshair = &Crosshair; snap_data.nearest_sq_dist = crosshair_sq_dist (&Crosshair, nearest_grid_x, nearest_grid_y); snap_data.nearest_is_grid = true; snap_data.x = nearest_grid_x; snap_data.y = nearest_grid_y; ans = NO_TYPE; if (!PCB->RatDraw) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, ELEMENT_TYPE, &ptr1, &ptr2, &ptr3); if (ans & ELEMENT_TYPE) { ElementType *el = (ElementType *) ptr1; check_snap_object (&snap_data, el->MarkX, el->MarkY, false); } ans = NO_TYPE; if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, PAD_TYPE, &ptr1, &ptr2, &ptr3); /* Avoid self-snapping when moving */ if (ans != NO_TYPE && Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == ELEMENT_TYPE && ptr1 == Crosshair.AttachedObject.Ptr1) ans = NO_TYPE; if (ans != NO_TYPE && ( Settings.Mode == LINE_MODE || (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == LINEPOINT_TYPE))) { PadTypePtr pad = (PadTypePtr) ptr2; LayerType *desired_layer; Cardinal desired_group; Cardinal SLayer, CLayer; int found_our_layer = false; desired_layer = CURRENT; if (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == LINEPOINT_TYPE) { desired_layer = (LayerType *)Crosshair.AttachedObject.Ptr1; } /* find layer groups of the component side and solder side */ SLayer = GetLayerGroupNumberByNumber (solder_silk_layer); CLayer = GetLayerGroupNumberByNumber (component_silk_layer); desired_group = TEST_FLAG (ONSOLDERFLAG, pad) ? SLayer : CLayer; GROUP_LOOP (PCB->Data, desired_group); { if (layer == desired_layer) { found_our_layer = true; break; } } END_LOOP; if (found_our_layer == false) ans = NO_TYPE; } if (ans != NO_TYPE) { PadType *pad = (PadType *)ptr2; check_snap_object (&snap_data, (pad->Point1.X + pad->Point2.X) / 2, (pad->Point1.Y + pad->Point2.Y) / 2, true); } ans = NO_TYPE; if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, PIN_TYPE, &ptr1, &ptr2, &ptr3); /* Avoid self-snapping when moving */ if (ans != NO_TYPE && Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == ELEMENT_TYPE && ptr1 == Crosshair.AttachedObject.Ptr1) ans = NO_TYPE; if (ans != NO_TYPE) { PinType *pin = (PinType *)ptr2; check_snap_object (&snap_data, pin->X, pin->Y, true); } ans = NO_TYPE; if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, VIA_TYPE, &ptr1, &ptr2, &ptr3); /* Avoid snapping vias to any other vias */ if (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == VIA_TYPE && (ans & PIN_TYPES)) ans = NO_TYPE; if (ans != NO_TYPE) { PinType *pin = (PinType *)ptr2; check_snap_object (&snap_data, pin->X, pin->Y, true); } ans = NO_TYPE; if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, LINEPOINT_TYPE, &ptr1, &ptr2, &ptr3); if (ans != NO_TYPE) { PointType *pnt = (PointType *)ptr3; check_snap_object (&snap_data, pnt->X, pnt->Y, true); } check_snap_offgrid_line (&snap_data, nearest_grid_x, nearest_grid_y); ans = NO_TYPE; if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, POLYGONPOINT_TYPE, &ptr1, &ptr2, &ptr3); if (ans != NO_TYPE) { PointType *pnt = (PointType *)ptr3; check_snap_object (&snap_data, pnt->X, pnt->Y, true); } if (snap_data.x >= 0 && snap_data.y >= 0) { Crosshair.X = snap_data.x; Crosshair.Y = snap_data.y; } if (Settings.Mode == ARROW_MODE) { ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, LINEPOINT_TYPE, &ptr1, &ptr2, &ptr3); if (ans == NO_TYPE) hid_action("PointCursor"); else if (!TEST_FLAG(SELECTEDFLAG, (LineType *)ptr2)) hid_actionl("PointCursor","True", NULL); } if (Settings.Mode == LINE_MODE && Crosshair.AttachedLine.State != STATE_FIRST && TEST_FLAG (AUTODRCFLAG, PCB)) EnforceLineDRC (); gui->set_crosshair (Crosshair.X, Crosshair.Y, HID_SC_DO_NOTHING); }