/* --------------------------------------------------------------------------- * inserts a point into a rat-line */ static void * InsertPointIntoRat (RatTypePtr Rat) { LineTypePtr newone; newone = CreateDrawnLineOnLayer (CURRENT, Rat->Point1.X, Rat->Point1.Y, InsertX, InsertY, Settings.LineThickness, 2 * Settings.Keepaway, Rat->Flags); if (!newone) return newone; AddObjectToCreateUndoList (LINE_TYPE, CURRENT, newone, newone); EraseRat (Rat); DrawLine (CURRENT, newone, 0); newone = CreateDrawnLineOnLayer (CURRENT, Rat->Point2.X, Rat->Point2.Y, InsertX, InsertY, Settings.LineThickness, 2 * Settings.Keepaway, Rat->Flags); if (newone) { AddObjectToCreateUndoList (LINE_TYPE, CURRENT, newone, newone); DrawLine (CURRENT, newone, 0); } MoveObjectToRemoveUndoList (RATLINE_TYPE, Rat, Rat, Rat); Draw (); return (newone); }
/* --------------------------------------------------------------------------- * moves a line between layers */ static void * MoveRatToLayer (RatType *Rat) { LineTypePtr newone; //Coord X1 = Rat->Point1.X, Y1 = Rat->Point1.Y; //Coord X1 = Rat->Point1.X, Y1 = Rat->Point1.Y; // if VIAFLAG // if we're on a pin, add a thermal // else make a via and a wire, but 0-length wire not good // else as before newone = CreateNewLineOnLayer (Dest, Rat->Point1.X, Rat->Point1.Y, Rat->Point2.X, Rat->Point2.Y, Settings.LineThickness, 2 * Settings.Keepaway, Rat->Flags); if (TEST_FLAG (CLEARNEWFLAG, PCB)) SET_FLAG (CLEARLINEFLAG, newone); if (!newone) return (NULL); AddObjectToCreateUndoList (LINE_TYPE, Dest, newone, newone); if (PCB->RatOn) EraseRat (Rat); MoveObjectToRemoveUndoList (RATLINE_TYPE, Rat, Rat, Rat); DrawLine (Dest, newone); Draw (); return (newone); }
/* --------------------------------------------------------------------------- * copies an element onto the PCB. Then does a draw. */ static void * CopyElement (ElementType *Element) { #ifdef DEBUG printf("Entered CopyElement, trying to copy element %s\n", Element->Name[1].TextString); #endif ElementType *element = CopyElementLowLevel (PCB->Data, Element, TEST_FLAG (UNIQUENAMEFLAG, PCB), DeltaX, DeltaY, NOCOPY_FLAGS); /* this call clears the polygons */ AddObjectToCreateUndoList (ELEMENT_TYPE, element, element, element); if (PCB->ElementOn && (FRONT (element) || PCB->InvisibleObjectsOn)) { DrawElementName (element); DrawElementPackage (element); } if (PCB->PinOn) { DrawElementPinsAndPads (element); } #ifdef DEBUG printf(" ... Leaving CopyElement.\n"); #endif return (element); }
/* --------------------------------------------------------------------------- * inserts a point into a line */ static void * InsertPointIntoLine (LayerTypePtr Layer, LineTypePtr Line) { LineTypePtr line; LocationType X, Y; if (((Line->Point1.X == InsertX) && (Line->Point1.Y == InsertY)) || ((Line->Point2.X == InsertX) && (Line->Point2.Y == InsertY))) return (NULL); X = Line->Point2.X; Y = Line->Point2.Y; AddObjectToMoveUndoList (LINEPOINT_TYPE, Layer, Line, &Line->Point2, InsertX - X, InsertY - Y); EraseLine (Line); r_delete_entry (Layer->line_tree, (BoxTypePtr) Line); Line->Point2.X = InsertX; Line->Point2.Y = InsertY; SetLineBoundingBox (Line); r_insert_entry (Layer->line_tree, (BoxTypePtr) Line, 0); DrawLine (Layer, Line, 0); /* we must create after playing with Line since creation may * invalidate the line pointer */ if ((line = CreateDrawnLineOnLayer (Layer, InsertX, InsertY, X, Y, Line->Thickness, Line->Clearance, Line->Flags))) { AddObjectToCreateUndoList (LINE_TYPE, Layer, line, line); DrawLine (Layer, line, 0); /* creation call adds it to the rtree */ } Draw (); return (line); }
/* * Wrapper for CreateNewLineOnLayer that takes vectors and deals with Undo */ static LineType * CreateVectorLineOnLayer(LayerType *layer, Vector a, Vector b, int thickness, int clearance, FlagType flags) { LineType *line; line = CreateNewLineOnLayer(layer, a[0], a[1], b[0], b[1], thickness, clearance, flags); if (line) { AddObjectToCreateUndoList (LINE_TYPE, layer, line, line); } return line; }
/* --------------------------------------------------------------------------- * copies a text */ static void * CopyText (LayerType *Layer, TextType *Text) { TextType *text; text = CreateNewText (Layer, &PCB->Font, Text->X + DeltaX, Text->Y + DeltaY, Text->Direction, Text->Scale, Text->TextString, MaskFlags (Text->Flags, NOCOPY_FLAGS)); DrawText (Layer, text); AddObjectToCreateUndoList (TEXT_TYPE, Layer, text, text); return (text); }
static void replace_one_footprint_aux(ElementTypePtr old_element, PadOrPinType* old1_pp, PadOrPinType* old2_pp, ElementTypePtr copy_element, PadOrPinType* copy1_pp, PadOrPinType* copy2_pp) { Boolean two_points = (old2_pp && copy2_pp); Boolean reflect = IS_REFLECTED(copy_element, old_element); debug_log("Reflect?: %s\n", (reflect ? "yes" : "no")); if (reflect) { /* Change side of board */ ChangeElementSide(copy_element, 0); } CheapPointType copy1_pt = pad_or_pin_center(copy1_pp); CheapPointType old1_pt = pad_or_pin_center(old1_pp); BYTE rot_steps = 0; if (two_points) { /* Calculate nearest rotation steps */ CheapPointType copy2_pt = pad_or_pin_center(copy2_pp); CheapPointType old2_pt = pad_or_pin_center(old2_pp); rot_steps = calculate_rotation_steps(copy1_pt, copy2_pt, old1_pt, old2_pt); } if (rot_steps) { /* Rotate copy */ RotateElementLowLevel(PCB->Data, copy_element, 0, 0, rot_steps); /* Recalculate since copy_element has changed. */ copy1_pt = pad_or_pin_center(copy1_pp); } /* Calculate translation */ LocationType dx = old1_pt.X - copy1_pt.X; LocationType dy = old1_pt.Y - copy1_pt.Y; /* Move element */ MoveElementLowLevel(PCB->Data, copy_element, dx, dy); /* Transfer pad/pin text and names. */ transfer_text(old_element, copy_element); transfer_names(old_element, copy_element); transfer_flags(old_element, copy_element); SetElementBoundingBox(PCB->Data, copy_element, &PCB->Font); AddObjectToCreateUndoList(ELEMENT_TYPE, copy_element, copy_element, copy_element); /* Remove old element. */ MoveObjectToRemoveUndoList(ELEMENT_TYPE, old_element, old_element, old_element); }
/* --------------------------------------------------------------------------- * copies an arc */ static void * CopyArc (LayerType *Layer, ArcType *Arc) { ArcType *arc; arc = CreateNewArcOnLayer (Layer, Arc->X + DeltaX, Arc->Y + DeltaY, Arc->Width, Arc->Height, Arc->StartAngle, Arc->Delta, Arc->Thickness, Arc->Clearance, MaskFlags (Arc->Flags, NOCOPY_FLAGS)); if (!arc) return (arc); DrawArc (Layer, arc); AddObjectToCreateUndoList (ARC_TYPE, Layer, arc, arc); return (arc); }
/* --------------------------------------------------------------------------- * copies a via */ static void * CopyVia (PinType *Via) { PinType *via; via = CreateNewVia (PCB->Data, Via->X + DeltaX, Via->Y + DeltaY, Via->Thickness, Via->Clearance, Via->Mask, Via->DrillingHole, Via->Name, MaskFlags (Via->Flags, NOCOPY_FLAGS)); if (!via) return (via); DrawVia (via); AddObjectToCreateUndoList (VIA_TYPE, via, via, via); return (via); }
/* --------------------------------------------------------------------------- * copies a polygon */ static void * CopyPolygon (LayerType *Layer, PolygonType *Polygon) { PolygonType *polygon; polygon = CreateNewPolygon (Layer, NoFlags ()); CopyPolygonLowLevel (polygon, Polygon); MovePolygonLowLevel (polygon, DeltaX, DeltaY); if (!Layer->polygon_tree) Layer->polygon_tree = r_create_tree (NULL, 0, 0); r_insert_entry (Layer->polygon_tree, (BoxType *) polygon, 0); InitClip (PCB->Data, Layer, polygon); DrawPolygon (Layer, polygon); AddObjectToCreateUndoList (POLYGON_TYPE, Layer, polygon, polygon); return (polygon); }
static int moveline_callback (const BoxType * b, void *cl) { struct via_info *i = (struct via_info *) cl; PinTypePtr via; if ((via = CreateNewVia (PCB->Data, i->X, i->Y, Settings.ViaThickness, 2 * Settings.Keepaway, NOFLAG, Settings.ViaDrillingHole, NULL, NoFlags ())) != NULL) { AddObjectToCreateUndoList (VIA_TYPE, via, via, via); DrawVia (via); } longjmp (i->env, 1); }
/* --------------------------------------------------------------------------- * copies a line */ static void * CopyLine (LayerType *Layer, LineType *Line) { LineType *line; line = CreateDrawnLineOnLayer (Layer, Line->Point1.X + DeltaX, Line->Point1.Y + DeltaY, Line->Point2.X + DeltaX, Line->Point2.Y + DeltaY, Line->Thickness, Line->Clearance, MaskFlags (Line->Flags, NOCOPY_FLAGS)); if (!line) return (line); if (Line->Number) line->Number = strdup (Line->Number); DrawLine (Layer, line); AddObjectToCreateUndoList (LINE_TYPE, Layer, line, line); return (line); }
/* --------------------------------------------------------------------------- * copies a line */ static void * CopyLine (LayerTypePtr Layer, LineTypePtr Line) { LineTypePtr line; line = CreateDrawnLineOnLayer (Layer, Line->Point1.X + DeltaX, Line->Point1.Y + DeltaY, Line->Point2.X + DeltaX, Line->Point2.Y + DeltaY, Line->Thickness, Line->Clearance, MaskFlags (Line->Flags, FOUNDFLAG)); if (!line) return (line); if (Line->Number) line->Number = MyStrdup (Line->Number, "CopyLine"); DrawLine (Layer, line, 0); AddObjectToCreateUndoList (LINE_TYPE, Layer, line, line); return (line); }
/*! * \brief Draw a rat net (tree) having the shortest lines. * * This also frees the subnet memory as they are consumed. * * \note The \c Netl we are passed is NOT the main netlist - it's the * connectivity for ONE net. * It represents the CURRENT connectivity state for the net, with each * Netl->Net[N] representing one copper-connected subset of the net. * * Everything inside the NetList Netl should be connected together. * * Each Net in \c Netl is a group of Connections which are already * connected together somehow, either by real wires or by rats we've * already drawn. * * Each Connection is a vertex within that blob of connected items. * * This loop finds the closest vertex pairs between each blob and draws * rats that merge the blobs until there's just one big blob. * * Just to clarify, with some examples: * * Each \c Netl is one full net from a netlist, like from gnetlist. * * Each Netl->Net[N] is a subset of that net that's already * physically connected on the pcb. * * So a new design with no traces yet, would have a huge list of Net[N], * each with one pin in it. * * A fully routed design would have one Net[N] with all the pins * (for that net) in it. */ static bool DrawShortestRats (NetListType *Netl, void (*funcp) (register ConnectionType *, register ConnectionType *, register RouteStyleType *)) { RatType *line; register float distance, temp; register ConnectionType *conn1, *conn2, *firstpoint, *secondpoint; PolygonType *polygon; bool changed = false; bool havepoints; Cardinal n, m, j; NetType *next, *subnet, *theSubnet = NULL; /* This is just a sanity check, to make sure we're passed * *something*. */ if (!Netl || Netl->NetN < 1) return false; /* * We keep doing this do/while loop until everything's connected. * I.e. once per rat we add. */ distance = 0.0; havepoints = true; /* so we run the loop at least once */ while (Netl->NetN > 1 && havepoints) { /* This is the top of the "find one rat" logic. */ havepoints = false; firstpoint = secondpoint = NULL; /* Test Net[0] vs Net[N] for N=1..max. Find the shortest distance between any two points in different blobs. */ subnet = &Netl->Net[0]; for (j = 1; j < Netl->NetN; j++) { /* * Scan between Net[0] blob (subnet) and Net[N] blob (next). * Note the shortest distance we find. */ next = &Netl->Net[j]; for (n = subnet->ConnectionN - 1; n != -1; n--) { conn1 = &subnet->Connection[n]; for (m = next->ConnectionN - 1; m != -1; m--) { conn2 = &next->Connection[m]; /* * At this point, conn1 and conn2 are two pins in * different blobs of the same net. See how far * apart they are, and if they're "closer" than what * we already have. */ /* * Prefer to connect Connections over polygons to the * polygons (ie assume the user wants a via to a plane, * not a daisy chain). Further prefer to pick an existing * via in the Net to make that connection. */ if (conn1->type == POLYGON_TYPE && (polygon = (PolygonType *)conn1->ptr2) && !(distance == 0 && firstpoint && firstpoint->type == VIA_TYPE) && IsPointInPolygonIgnoreHoles (conn2->X, conn2->Y, polygon)) { distance = 0; firstpoint = conn2; secondpoint = conn1; theSubnet = next; havepoints = true; } else if (conn2->type == POLYGON_TYPE && (polygon = (PolygonType *)conn2->ptr2) && !(distance == 0 && firstpoint && firstpoint->type == VIA_TYPE) && IsPointInPolygonIgnoreHoles (conn1->X, conn1->Y, polygon)) { distance = 0; firstpoint = conn1; secondpoint = conn2; theSubnet = next; havepoints = true; } else if ((temp = SQUARE (conn1->X - conn2->X) + SQUARE (conn1->Y - conn2->Y)) < distance || !firstpoint) { distance = temp; firstpoint = conn1; secondpoint = conn2; theSubnet = next; havepoints = true; } } } } /* * If HAVEPOINTS is true, we've found a pair of points in two * separate blobs of the net, and need to connect them together. */ if (havepoints) { if (funcp) { (*funcp) (firstpoint, secondpoint, subnet->Style); } else { /* found the shortest distance subnet, draw the rat */ if ((line = CreateNewRat (PCB->Data, firstpoint->X, firstpoint->Y, secondpoint->X, secondpoint->Y, firstpoint->group, secondpoint->group, Settings.RatThickness, NoFlags ())) != NULL) { if (distance == 0) SET_FLAG (VIAFLAG, line); AddObjectToCreateUndoList (RATLINE_TYPE, line, line, line); DrawRat (line); changed = true; } } /* copy theSubnet into the current subnet */ TransferNet (Netl, theSubnet, subnet); } } /* presently nothing to do with the new subnet */ /* so we throw it away and free the space */ FreeNetMemory (&Netl->Net[--(Netl->NetN)]); /* Sadly adding a rat line messes up the sorted arrays in connection finder */ /* hace: perhaps not necessarily now that they aren't stored in normal layers */ if (changed) { FreeConnectionLookupMemory (); InitConnectionLookup (); } return (changed); }