/* --------------------------------------------------------------------------- * copies a rat-line to paste buffer */ static void * AddRatToBuffer (RatType *Rat) { return (CreateNewRat (Dest, Rat->Point1.X, Rat->Point1.Y, Rat->Point2.X, Rat->Point2.Y, Rat->group1, Rat->group2, Rat->Thickness, MaskFlags (Rat->Flags, NOCOPY_FLAGS | ExtraFlag))); }
/*! * \brief This function is moved from the original netlist.c as * part of the gui code separation for the Gtk port. */ RatType * AddNet (void) { static int ratDrawn = 0; char name1[256], *name2; Cardinal group1, group2; char ratname[20]; int found; void *ptr1, *ptr2, *ptr3; LibraryMenuType *menu; LibraryEntryType *entry; if (Crosshair.AttachedLine.Point1.X == Crosshair.AttachedLine.Point2.X && Crosshair.AttachedLine.Point1.Y == Crosshair.AttachedLine.Point2.Y) return (NULL); found = SearchObjectByLocation (PAD_TYPE | PIN_TYPE, &ptr1, &ptr2, &ptr3, Crosshair.AttachedLine.Point1.X, Crosshair.AttachedLine.Point1.Y, 5); if (found == NO_TYPE) { Message (_("No pad/pin under rat line\n")); return (NULL); } if (NAMEONPCB_NAME ((ElementType *) ptr1) == NULL || *NAMEONPCB_NAME ((ElementType *) ptr1) == 0) { Message (_("You must name the starting element first\n")); return (NULL); } /* will work for pins to since the FLAG is common */ group1 = GetLayerGroupNumberBySide ( TEST_FLAG (ONSOLDERFLAG, (PadType *) ptr2) ? BOTTOM_SIDE : TOP_SIDE); strcpy (name1, ConnectionName (found, ptr1, ptr2)); found = SearchObjectByLocation (PAD_TYPE | PIN_TYPE, &ptr1, &ptr2, &ptr3, Crosshair.AttachedLine.Point2.X, Crosshair.AttachedLine.Point2.Y, 5); if (found == NO_TYPE) { Message (_("No pad/pin under rat line\n")); return (NULL); } if (NAMEONPCB_NAME ((ElementType *) ptr1) == NULL || *NAMEONPCB_NAME ((ElementType *) ptr1) == 0) { Message (_("You must name the ending element first\n")); return (NULL); } group2 = GetLayerGroupNumberBySide ( TEST_FLAG (ONSOLDERFLAG, (PadType *) ptr2) ? BOTTOM_SIDE : TOP_SIDE); name2 = ConnectionName (found, ptr1, ptr2); menu = netnode_to_netname (name1); if (menu) { if (netnode_to_netname (name2)) { Message (_ ("Both connections already in netlist - cannot merge nets\n")); return (NULL); } entry = GetLibraryEntryMemory (menu); entry->ListEntry = strdup (name2); netnode_to_netname (name2); goto ratIt; } /* ok, the first name did not belong to a net */ menu = netnode_to_netname (name2); if (menu) { entry = GetLibraryEntryMemory (menu); entry->ListEntry = strdup (name1); netnode_to_netname (name1); goto ratIt; } /* * neither belong to a net, so create a new one. * * before creating a new rats here, we need to search * for a unique name. */ sprintf (ratname, " ratDrawn%i", ++ratDrawn); while (rat_used (ratname)) { sprintf (ratname, " ratDrawn%i", ++ratDrawn); } menu = GetLibraryMenuMemory (&PCB->NetlistLib); menu->Name = strdup (ratname); entry = GetLibraryEntryMemory (menu); entry->ListEntry = strdup (name1); entry = GetLibraryEntryMemory (menu); entry->ListEntry = strdup (name2); menu->flag = 1; ratIt: NetlistChanged (0); return (CreateNewRat (PCB->Data, Crosshair.AttachedLine.Point1.X, Crosshair.AttachedLine.Point1.Y, Crosshair.AttachedLine.Point2.X, Crosshair.AttachedLine.Point2.Y, group1, group2, Settings.RatThickness, NoFlags ())); }
/*! * \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); }