wxString TRACK::GetSelectMenuText() const { wxString text; wxString netname; NETINFO_ITEM* net; BOARD* board = GetBoard(); // deleting tracks requires all the information we can get to // disambiguate all the choices under the cursor! if( board ) { net = GetNet(); if( net ) netname = net->GetNetname(); else netname = _("Not found"); } else { wxFAIL_MSG( wxT( "TRACK::GetSelectMenuText: BOARD is NULL" ) ); netname = wxT( "???" ); } text.Printf( _("Track %s, net [%s] (%d) on layer %s, length: %s" ), GetChars( ShowWidth() ), GetChars( netname ), GetNetCode(), GetChars( GetLayerName() ), GetChars( ::LengthDoubleToString( GetLength() ) ) ); return text; }
PNS_PCBNEW_CLEARANCE_RESOLVER::PNS_PCBNEW_CLEARANCE_RESOLVER( PNS_ROUTER* aRouter ) : m_router( aRouter ) { BOARD* brd = m_router->GetBoard(); m_clearanceCache.resize( brd->GetNetCount() ); m_useDpGap = false; for( unsigned int i = 0; i < brd->GetNetCount(); i++ ) { NETINFO_ITEM* ni = brd->FindNet( i ); if( ni == NULL ) continue; CLEARANCE_ENT ent; ent.coupledNet = m_router->GetWorld()->PairedNet( i ); wxString netClassName = ni->GetClassName(); NETCLASSPTR nc = brd->GetDesignSettings().m_NetClasses.Find( netClassName ); int clearance = nc->GetClearance(); ent.clearance = clearance; m_clearanceCache[i] = ent; TRACE( 1, "Add net %d netclass %s clearance %d", i % netClassName.mb_str() % clearance ); } m_overrideEnabled = false; m_defaultClearance = Millimeter2iu( 0.254 ); // aBoard->m_NetClasses.Find ("Default clearance")->GetClearance(); m_overrideNetA = 0; m_overrideNetB = 0; m_overrideClearance = 0; }
void NETINFO_LIST::AppendNet( NETINFO_ITEM* aNewElement ) { // if there is a net with such name then just assign the correct number NETINFO_ITEM* sameName = GetNetItem( aNewElement->GetNetname() ); if( sameName != NULL ) { aNewElement->m_NetCode = sameName->GetNet(); return; } // be sure that net codes are consecutive // negative net code means that it has to be auto assigned else if( ( aNewElement->m_NetCode != (int) m_netCodes.size() ) || ( aNewElement->m_NetCode < 0 ) ) { aNewElement->m_NetCode = getFreeNetCode(); } // net names & codes are supposed to be unique assert( GetNetItem( aNewElement->GetNetname() ) == NULL ); assert( GetNetItem( aNewElement->GetNet() ) == NULL ); // add an entry for fast look up by a net name using a map m_netNames.insert( std::make_pair( aNewElement->GetNetname(), aNewElement ) ); m_netCodes.insert( std::make_pair( aNewElement->GetNet(), aNewElement ) ); }
void WIDGET_NET_SELECTOR::SetBoard( BOARD* aBoard ) { auto& netinfo = aBoard->GetNetInfo(); for( unsigned i = 1; i < netinfo.GetNetCount(); i++ ) { NETINFO_ITEM* ni = netinfo.GetNetItem( i ); NET net; net.m_Name = ni->GetNetname(); net.m_Code = i; m_nets.push_back( net ); } std::sort( m_nets.begin(), m_nets.end() ); // Add the list of selectable nets to the wxComboBox. // Using a wxArrayString is much faster than adding each name separately wxArrayString netnames; netnames.Add( wxT( "<no net>" ) ); // Always on top of the list for( auto& net : m_nets ) { net.m_Pos = netnames.Add( net.m_Name ); } Append( netnames ); }
void TRACK::GetMsgPanelInfoBase_Common( std::vector< MSG_PANEL_ITEM >& aList ) { wxString msg; // Display Net Name if( GetBoard() ) { NETINFO_ITEM* net = GetNet(); if( net ) msg = net->GetNetname(); else msg = wxT( "<noname>" ); aList.push_back( MSG_PANEL_ITEM( _( "NetName" ), msg, RED ) ); // Display net code : (useful in test or debug) msg.Printf( wxT( "%d.%d" ), GetNetCode(), GetSubNet() ); aList.push_back( MSG_PANEL_ITEM( _( "NetCode" ), msg, RED ) ); } #if defined(DEBUG) // Display the flags msg.Printf( wxT( "0x%08X" ), m_Flags ); aList.push_back( MSG_PANEL_ITEM( wxT( "Flags" ), msg, BLUE ) ); #if 0 // Display start and end pointers: msg.Printf( wxT( "%p" ), start ); aList.push_back( MSG_PANEL_ITEM( wxT( "start ptr" ), msg, BLUE ) ); msg.Printf( wxT( "%p" ), end ); aList.push_back( MSG_PANEL_ITEM( wxT( "end ptr" ), msg, BLUE ) ); // Display this ptr msg.Printf( wxT( "%p" ), this ); aList.push_back( MSG_PANEL_ITEM( wxT( "this" ), msg, BLUE ) ); #endif #if 0 // Display start and end positions: msg.Printf( wxT( "%d %d" ), m_Start.x, m_Start.y ); aList.push_back( MSG_PANEL_ITEM( wxT( "Start pos" ), msg, BLUE ) ); msg.Printf( wxT( "%d %d" ), m_End.x, m_End.y ); aList.push_back( MSG_PANEL_ITEM( wxT( "End pos" ), msg, BLUE ) ); #endif #endif // defined(DEBUG) // Display the State member msg = wxT( ". . " ); if( GetState( TRACK_LOCKED ) ) msg[0] = 'F'; if( GetState( TRACK_AR ) ) msg[2] = 'A'; aList.push_back( MSG_PANEL_ITEM( _( "Status" ), msg, MAGENTA ) ); }
PNS_PCBNEW_RULE_RESOLVER::PNS_PCBNEW_RULE_RESOLVER( BOARD* aBoard, PNS::ROUTER* aRouter ) : m_router( aRouter ), m_board( aBoard ) { PNS::NODE* world = m_router->GetWorld(); PNS::TOPOLOGY topo( world ); m_netClearanceCache.resize( m_board->GetNetCount() ); // Build clearance cache for net classes for( unsigned int i = 0; i < m_board->GetNetCount(); i++ ) { NETINFO_ITEM* ni = m_board->FindNet( i ); if( ni == NULL ) continue; CLEARANCE_ENT ent; ent.coupledNet = DpCoupledNet( i ); wxString netClassName = ni->GetClassName(); NETCLASSPTR nc = m_board->GetDesignSettings().m_NetClasses.Find( netClassName ); int clearance = nc->GetClearance(); ent.clearance = clearance; m_netClearanceCache[i] = ent; wxLogTrace( "PNS", "Add net %u netclass %s clearance %d", i, netClassName.mb_str(), clearance ); } // Build clearance cache for pads for( MODULE* mod = m_board->m_Modules; mod ; mod = mod->Next() ) { auto moduleClearance = mod->GetLocalClearance(); for( D_PAD* pad = mod->PadsList(); pad; pad = pad->Next() ) { int padClearance = pad->GetLocalClearance(); if( padClearance > 0 ) m_localClearanceCache[ pad ] = padClearance; else if( moduleClearance > 0 ) m_localClearanceCache[ pad ] = moduleClearance; } } //printf("DefaultCL : %d\n", m_board->GetDesignSettings().m_NetClasses.Find ("Default clearance")->GetClearance()); m_overrideEnabled = false; m_defaultClearance = Millimeter2iu( 0.254 ); // m_board->m_NetClasses.Find ("Default clearance")->GetClearance(); m_overrideNetA = 0; m_overrideNetB = 0; m_overrideClearance = 0; m_useDpGap = false; }
bool ZONE_CONTAINER::SetNetNameFromNetCode( void ) { NETINFO_ITEM* net; if( m_Parent && ( net = ( (BOARD*) m_Parent )->FindNet( GetNet() ) ) ) { m_Netname = net->GetNetname(); return true; } return false; }
wxString ZONE_CONTAINER::GetSelectMenuText() const { wxString text; NETINFO_ITEM* net; BOARD* board = GetBoard(); int ncont = m_Poly->GetContour( m_CornerSelection ); if( ncont ) text << wxT( " " ) << _( "(Cutout)" ); if( GetIsKeepout() ) text << wxT( " " ) << _( "(Keepout)" ); text << wxString::Format( wxT( " (%08lX)" ), m_TimeStamp ); // Display net name for copper zones if( !GetIsKeepout() ) { if( GetNetCode() >= 0 ) { if( board ) { net = GetNet(); if( net ) { text << wxT( " [" ) << net->GetNetname() << wxT( "]" ); } } else { text << _( "** NO BOARD DEFINED **" ); } } else { // A netcode < 0 is an error: // Netname not found or area not initialised text << wxT( " [" ) << GetNetname() << wxT( "]" ); text << wxT( " <" ) << _( "Not Found" ) << wxT( ">" ); } } wxString msg; msg.Printf( _( "Zone Outline %s on %s" ), GetChars( text ), GetChars( GetLayerName() ) ); return msg; }
/* Emit the netlist (which is actually the thing for which GenCAD is used these * days!); tracks are handled later */ static void CreateSignalsSection( FILE* aFile, BOARD* aPcb ) { wxString msg; NETINFO_ITEM* net; D_PAD* pad; MODULE* module; int NbNoConn = 1; fputs( "$SIGNALS\n", aFile ); for( unsigned ii = 0; ii < aPcb->GetNetCount(); ii++ ) { net = aPcb->FindNet( ii ); if( net->GetNetname() == wxEmptyString ) // dummy netlist (no connection) { wxString msg; msg << wxT( "NoConnection" ) << NbNoConn++; } if( net->GetNet() <= 0 ) // dummy netlist (no connection) continue; msg = wxT( "SIGNAL " ) + net->GetNetname(); fputs( TO_UTF8( msg ), aFile ); fputs( "\n", aFile ); for( module = aPcb->m_Modules; module; module = module->Next() ) { for( pad = module->Pads(); pad; pad = pad->Next() ) { wxString padname; if( pad->GetNetCode() != net->GetNet() ) continue; pad->StringPadName( padname ); msg.Printf( wxT( "NODE %s %s" ), GetChars( module->GetReference() ), GetChars( padname ) ); fputs( TO_UTF8( msg ), aFile ); fputs( "\n", aFile ); } } } fputs( "$ENDSIGNALS\n\n", aFile ); }
PCBNEW_CLEARANCE_FUNC( BOARD* aBoard ) { m_clearanceCache.resize( aBoard->GetNetCount() ); for( unsigned int i = 0; i < aBoard->GetNetCount(); i++ ) { NETINFO_ITEM* ni = aBoard->FindNet( i ); wxString netClassName = ni->GetClassName(); NETCLASS* nc = aBoard->m_NetClasses.Find( netClassName ); int clearance = nc->GetClearance(); m_clearanceCache[i] = clearance; TRACE( 1, "Add net %d netclass %s clearance %d", i % netClassName.mb_str() % clearance ); } m_defaultClearance = 254000; // aBoard->m_NetClasses.Find ("Default clearance")->GetClearance(); }
int PNS_PCBNEW_RULE_RESOLVER::DpCoupledNet( int aNet ) { wxString refName = m_board->FindNet( aNet )->GetNetname(); wxString dummy, coupledNetName; if( matchDpSuffix( refName, coupledNetName, dummy ) ) { NETINFO_ITEM* net = m_board->FindNet( coupledNetName ); if( !net ) return -1; return net->GetNet(); } return -1; }
int PCBNEW_PAIRING_RESOLVER::PairedNet(int aNet) const { wxString refName = m_board->FindNet( aNet )->GetNetname(); wxString dummy, coupledNetName; if( MatchDpSuffix( refName, coupledNetName, dummy ) ) { NETINFO_ITEM* net = m_board->FindNet( coupledNetName ); if( !net ) return -1; return net->GetNet(); } return -1; }
/* Extract the D356 record from the vias */ static void build_via_testpoints( BOARD *aPcb, std::vector <D356_RECORD>& aRecords ) { wxPoint origin = aPcb->GetAuxOrigin(); // Enumerate all the track segments and keep the vias for( TRACK *track = aPcb->m_Track; track; track = track->Next() ) { if( track->Type() == PCB_VIA_T ) { VIA *via = (VIA*) track; NETINFO_ITEM *net = track->GetNet(); D356_RECORD rk; rk.smd = false; rk.hole = true; if( net ) rk.netname = net->GetNetname(); else rk.netname = wxEmptyString; rk.refdes = wxT("VIA"); rk.pin = wxT(""); rk.midpoint = true; // Vias are always midpoints rk.drill = via->GetDrillValue(); rk.mechanical = false; LAYER_ID top_layer, bottom_layer; via->LayerPair( &top_layer, &bottom_layer ); rk.access = via_access_code( aPcb, top_layer, bottom_layer ); rk.x_location = via->GetPosition().x - origin.x; rk.y_location = origin.y - via->GetPosition().y; rk.x_size = via->GetWidth(); rk.y_size = 0; // Round so height = 0 rk.rotation = 0; rk.soldermask = 3; // XXX always tented? aRecords.push_back( rk ); } } }
int PNS_TOPOLOGY::DpCoupledNet( int aNet ) { BOARD* brd = PNS_ROUTER::GetInstance()->GetBoard(); wxString refName = brd->FindNet( aNet )->GetNetname(); wxString dummy, coupledNetName; if( MatchDpSuffix( refName, coupledNetName, dummy ) ) { NETINFO_ITEM* net = brd->FindNet( coupledNetName ); if( !net ) return -1; return net->GetNet(); } return -1; }
void ROUTER_TOOL::getNetclassDimensions( int aNetCode, int& aWidth, int& aViaDiameter, int& aViaDrill ) { BOARD_DESIGN_SETTINGS &bds = m_board->GetDesignSettings(); NETCLASSPTR netClass; NETINFO_ITEM* ni = m_board->FindNet( aNetCode ); if( ni ) { wxString netClassName = ni->GetClassName(); netClass = bds.m_NetClasses.Find( netClassName ); } if( !netClass ) netClass = bds.GetDefault(); aWidth = netClass->GetTrackWidth(); aViaDiameter = netClass->GetViaDiameter(); aViaDrill = netClass->GetViaDrill(); }
void ZONE_CONTAINER::SetNet( int aNetCode ) { BOARD_CONNECTED_ITEM::SetNet( aNetCode ); if( aNetCode < 0 ) return; BOARD* board = GetBoard(); if( board ) { NETINFO_ITEM* net = board->FindNet( aNetCode ); if( net ) m_Netname = net->GetNetname(); else m_Netname.Empty(); } else { m_Netname.Empty(); } }
bool PNS_PCBNEW_RULE_RESOLVER::DpNetPair( PNS::ITEM* aItem, int& aNetP, int& aNetN ) { if( !aItem || !aItem->Parent() || !aItem->Parent()->GetNet() ) return false; wxString netNameP = aItem->Parent()->GetNet()->GetNetname(); wxString netNameN, netNameCoupled, netNameBase; int r = matchDpSuffix( netNameP, netNameCoupled, netNameBase ); if( r == 0 ) return false; else if( r == 1 ) { netNameN = netNameCoupled; } else { netNameN = netNameP; netNameP = netNameCoupled; } // wxLogTrace( "PNS","p %s n %s base %s\n", (const char *)netNameP.c_str(), (const char *)netNameN.c_str(), (const char *)netNameBase.c_str() ); NETINFO_ITEM* netInfoP = m_board->FindNet( netNameP ); NETINFO_ITEM* netInfoN = m_board->FindNet( netNameN ); //wxLogTrace( "PNS","ip %p in %p\n", netInfoP, netInfoN); if( !netInfoP || !netInfoN ) return false; aNetP = netInfoP->GetNet(); aNetN = netInfoN->GetNet(); return true; }
void TRACK::DrawShortNetname( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, EDA_COLOR_T aBgColor ) { /* we must filter tracks, to avoid a lot of texts. * - only tracks with a length > 10 * thickness are eligible * and, of course, if we are not printing the board */ if( DisplayOpt.DisplayNetNamesMode == 0 || DisplayOpt.DisplayNetNamesMode == 1 ) return; #define THRESHOLD 10 int len = KiROUND( GetLineLength( m_Start, m_End ) ); if( len < THRESHOLD * m_Width ) return; // no room to display a text inside track if( aDC->LogicalToDeviceXRel( m_Width ) < MIN_TEXT_SIZE ) return; if( GetNetCode() == NETINFO_LIST::UNCONNECTED ) return; NETINFO_ITEM* net = GetNet(); if( net == NULL ) return; int textlen = net->GetShortNetname().Len(); if( textlen > 0 ) { // calculate a good size for the text int tsize = std::min( m_Width, len / textlen ); int dx = m_End.x - m_Start.x ; int dy = m_End.y - m_Start.y ; wxPoint tpos = m_Start + m_End; tpos.x /= 2; tpos.y /= 2; // Calculate angle: if the track segment is vertical, angle = 90 degrees // If horizontal 0 degrees, otherwise compute it double angle; // angle is in 0.1 degree if( dy == 0 ) // Horizontal segment { angle = 0; } else { if( dx == 0 ) // Vertical segment { angle = 900; } else { /* atan2 is *not* the solution here, since it can give upside down text. We want to work only in the first and fourth quadrant */ angle = RAD2DECIDEG( -atan( double( dy ) / double( dx ) ) ); } } LAYER_NUM curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer; if( ( aDC->LogicalToDeviceXRel( tsize ) >= MIN_TEXT_SIZE ) && ( !(!IsOnLayer( curr_layer )&& DisplayOpt.ContrastModeDisplay) ) ) { if( (aDrawMode & GR_XOR) == 0 ) GRSetDrawMode( aDC, GR_COPY ); tsize = (tsize * 7) / 10; // small reduction to give a better look EDA_RECT* clipbox = panel? panel->GetClipBox() : NULL; DrawGraphicHaloText( clipbox, aDC, tpos, aBgColor, BLACK, WHITE, net->GetShortNetname(), angle, wxSize( tsize, tsize ), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, tsize / 7, false, false ); } } }
void PCB_PAD::AddToModule( MODULE* aModule, int aRotation, bool aEncapsulatedPad ) { PCB_PAD_SHAPE* padShape; wxString padShapeName = wxT( "Ellipse" ); PAD_ATTR_T padType; int i; int width = 0; int height = 0; D_PAD* pad = new D_PAD( aModule ); aModule->Pads().PushBack( pad ); if( !m_isHolePlated && m_hole ) { // mechanical hole pad->SetShape( PAD_CIRCLE ); pad->SetAttribute( PAD_HOLE_NOT_PLATED ); pad->SetDrillShape( PAD_DRILL_CIRCLE ); pad->SetDrillSize( wxSize( m_hole, m_hole ) ); pad->SetSize( wxSize( m_hole, m_hole ) ); pad->SetLayerSet( LSET::AllCuMask() | LSET( 2, B_Mask, F_Mask ) ); } else { ( m_hole ) ? padType = PAD_STANDARD : padType = PAD_SMD; // form layer mask for( i = 0; i < (int) m_shapes.GetCount(); i++ ) { padShape = m_shapes[i]; if( padShape->m_width > 0 && padShape->m_height > 0 ) { if( padShape->m_KiCadLayer == F_Cu || padShape->m_KiCadLayer == B_Cu ) { padShapeName = padShape->m_shape; width = padShape->m_width; height = padShape->m_height; // assume this is SMD pad if( padShape->m_KiCadLayer == F_Cu ) pad->SetLayerSet( LSET( 3, F_Cu, F_Paste, F_Mask ) ); else pad->SetLayerSet( LSET( 3, B_Cu, B_Paste, B_Mask ) ); break; } } } if( padType == PAD_STANDARD ) // actually this is a thru-hole pad pad->SetLayerSet( LSET::AllCuMask() | LSET( 2, B_Mask, F_Mask ) ); if( width == 0 || height == 0 ) THROW_IO_ERROR( wxT( "pad with zero size" ) ); pad->SetPadName( m_name.text ); if( padShapeName == wxT( "Oval" ) || padShapeName == wxT( "Ellipse" ) || padShapeName == wxT( "MtHole" ) ) { if( width != height ) pad->SetShape( PAD_OVAL ); else pad->SetShape( PAD_CIRCLE ); } else if( padShapeName == wxT( "Rect" ) || padShapeName == wxT( "RndRect" ) ) pad->SetShape( PAD_RECT ); else if( padShapeName == wxT( "Polygon" ) ) pad->SetShape( PAD_RECT ); // approximation pad->SetSize( wxSize( width, height ) ); pad->SetDelta( wxSize( 0, 0 ) ); pad->SetOrientation( m_rotation + aRotation ); pad->SetDrillShape( PAD_DRILL_CIRCLE ); pad->SetOffset( wxPoint( 0, 0 ) ); pad->SetDrillSize( wxSize( m_hole, m_hole ) ); pad->SetAttribute( padType ); // Set the proper net code NETINFO_ITEM* netinfo = m_board->FindNet( m_net ); if( netinfo == NULL ) // I believe this should not happen, but just in case { // It is a new net netinfo = new NETINFO_ITEM( m_board, m_net ); m_board->AppendNet( netinfo ); } pad->SetNetCode( netinfo->GetNet() ); } if( !aEncapsulatedPad ) { // pad's "Position" is not relative to the module's, // whereas Pos0 is relative to the module's but is the unrotated coordinate. wxPoint padpos( m_positionX, m_positionY ); pad->SetPos0( padpos ); RotatePoint( &padpos, aModule->GetOrientation() ); pad->SetPosition( padpos + aModule->GetPosition() ); } }
void SPECCTRA_DB::FromSESSION( BOARD* aBoard ) throw( IO_ERROR ) { sessionBoard = aBoard; // not owned here if( !session ) THROW_IO_ERROR( _("Session file is missing the \"session\" section") ); /* Dick 16-Jan-2012: session need not have a placement section. if( !session->placement ) THROW_IO_ERROR( _("Session file is missing the \"placement\" section") ); */ if( !session->route ) THROW_IO_ERROR( _("Session file is missing the \"routes\" section") ); if( !session->route->library ) THROW_IO_ERROR( _("Session file is missing the \"library_out\" section") ); // delete all the old tracks and vias aBoard->m_Track.DeleteAll(); aBoard->DeleteMARKERs(); buildLayerMaps( aBoard ); if( session->placement ) { // Walk the PLACEMENT object's COMPONENTs list, and for each PLACE within // each COMPONENT, reposition and re-orient each component and put on // correct side of the board. COMPONENTS& components = session->placement->components; for( COMPONENTS::iterator comp=components.begin(); comp!=components.end(); ++comp ) { PLACES& places = comp->places; for( unsigned i=0; i<places.size(); ++i ) { PLACE* place = &places[i]; // '&' even though places[] holds a pointer! wxString reference = FROM_UTF8( place->component_id.c_str() ); MODULE* module = aBoard->FindModuleByReference( reference ); if( !module ) { THROW_IO_ERROR( wxString::Format( _("Session file has 'reference' to non-existent component \"%s\""), GetChars( reference ) ) ); } if( !place->hasVertex ) continue; UNIT_RES* resolution = place->GetUnits(); wxASSERT( resolution ); wxPoint newPos = mapPt( place->vertex, resolution ); module->SetPosition( newPos ); if( place->side == T_front ) { // convert from degrees to tenths of degrees used in KiCad. int orientation = KiROUND( place->rotation * 10.0 ); if( module->GetLayer() != F_Cu ) { // module is on copper layer (back) module->Flip( module->GetPosition() ); } module->SetOrientation( orientation ); } else if( place->side == T_back ) { int orientation = KiROUND( (place->rotation + 180.0) * 10.0 ); if( module->GetLayer() != B_Cu ) { // module is on component layer (front) module->Flip( module->GetPosition() ); } module->SetOrientation( orientation ); } else { // as I write this, the PARSER *is* catching this, so we should never see below: wxFAIL_MSG( wxT("DSN::PARSER did not catch an illegal side := 'back|front'") ); } } } } routeResolution = session->route->GetUnits(); // Walk the NET_OUTs and create tracks and vias anew. NET_OUTS& net_outs = session->route->net_outs; for( NET_OUTS::iterator net = net_outs.begin(); net!=net_outs.end(); ++net ) { int netCode = 0; // page 143 of spec says wire's net_id is optional if( net->net_id.size() ) { wxString netName = FROM_UTF8( net->net_id.c_str() ); NETINFO_ITEM* netinfo = aBoard->FindNet( netName ); if( netinfo ) netCode = netinfo->GetNet(); else // else netCode remains 0 { // int breakhere = 1; } } WIRES& wires = net->wires; for( unsigned i = 0; i<wires.size(); ++i ) { WIRE* wire = &wires[i]; DSN_T shape = wire->shape->Type(); if( shape != T_path ) { /* shape == T_polygon is expected from freerouter if you have a zone on a non "power" type layer, i.e. a T_signal layer and the design does a round trip back in as session here. We kept our own zones in the BOARD, so ignore this so called 'wire'. wxString netId = FROM_UTF8( wire->net_id.c_str() ); THROW_IO_ERROR( wxString::Format( _("Unsupported wire shape: \"%s\" for net: \"%s\""), DLEX::GetTokenString(shape).GetData(), netId.GetData() ) ); */ } else { PATH* path = (PATH*) wire->shape; for( unsigned pt=0; pt<path->points.size()-1; ++pt ) { /* a debugging aid, may come in handy if( path->points[pt].x == 547800 && path->points[pt].y == -380250 ) { int breakhere = 1; } */ TRACK* track = makeTRACK( path, pt, netCode ); aBoard->Add( track ); } } } WIRE_VIAS& wire_vias = net->wire_vias; LIBRARY& library = *session->route->library; for( unsigned i=0; i<wire_vias.size(); ++i ) { int netCode = 0; // page 144 of spec says wire_via's net_id is optional if( net->net_id.size() ) { wxString netName = FROM_UTF8( net->net_id.c_str() ); NETINFO_ITEM* net = aBoard->FindNet( netName ); if( net ) netCode = net->GetNet(); // else netCode remains 0 } WIRE_VIA* wire_via = &wire_vias[i]; // example: (via Via_15:8_mil 149000 -71000 ) PADSTACK* padstack = library.FindPADSTACK( wire_via->GetPadstackId() ); if( !padstack ) { // Dick Feb 29, 2008: // Freerouter has a bug where it will not round trip all vias. // Vias which have a (use_via) element will be round tripped. // Vias which do not, don't come back in in the session library, // even though they may be actually used in the pre-routed, // protected wire_vias. So until that is fixed, create the // padstack from its name as a work around. // Could use a STRING_FORMATTER here and convert the entire // wire_via to text and put that text into the exception. wxString psid( FROM_UTF8( wire_via->GetPadstackId().c_str() ) ); THROW_IO_ERROR( wxString::Format( _("A wire_via references a missing padstack \"%s\""), GetChars( psid ) ) ); } NETCLASSPTR netclass = aBoard->GetDesignSettings().m_NetClasses.GetDefault(); int via_drill_default = netclass->GetViaDrill(); for( unsigned v=0; v<wire_via->vertexes.size(); ++v ) { ::VIA* via = makeVIA( padstack, wire_via->vertexes[v], netCode, via_drill_default ); aBoard->Add( via ); } } } }
/** * Function SetTrackSegmentWidth * Modify one track segment width or one via diameter and drill (using DRC control). * Basic routine used by other routines when editing tracks or vias * @param aTrackItem = the track segment or via to modify * @param aItemsListPicker = the list picker to use for an undo command (can be NULL) * @param aUseNetclassValue = true to use NetClass value, false to use BOARD::m_designSettings value * @return true if done, false if no not change (because DRC error) */ bool PCB_EDIT_FRAME::SetTrackSegmentWidth( TRACK* aTrackItem, PICKED_ITEMS_LIST* aItemsListPicker, bool aUseNetclassValue ) { int initial_width, new_width; int initial_drill = -1,new_drill = -1; bool change_ok = false; NETINFO_ITEM* net = NULL; if( aUseNetclassValue ) net = aTrackItem->GetNet(); initial_width = aTrackItem->GetWidth(); if( net ) new_width = net->GetTrackWidth(); else new_width = GetDesignSettings().GetCurrentTrackWidth(); if( aTrackItem->Type() == PCB_VIA_T ) { const VIA *via = static_cast<const VIA *>( aTrackItem ); if( !via->IsDrillDefault() ) initial_drill = via->GetDrillValue(); if( net ) { new_width = net->GetViaSize(); } else { new_width = GetDesignSettings().GetCurrentViaSize(); new_drill = GetDesignSettings().GetCurrentViaDrill(); } if( via->GetViaType() == VIA_MICROVIA ) { if( net ) new_width = net->GetMicroViaSize(); else new_width = GetDesignSettings().GetCurrentMicroViaSize(); } } aTrackItem->SetWidth( new_width ); // make a DRC test because the new size is bigger than the old size if( initial_width < new_width ) { int diagdrc = OK_DRC; if( g_Drc_On ) diagdrc = m_drc->Drc( aTrackItem, GetBoard()->m_Track ); if( diagdrc == OK_DRC ) change_ok = true; } else if( initial_width > new_width ) { change_ok = true; } else if( (aTrackItem->Type() == PCB_VIA_T) && (initial_drill != new_drill) ) { // if new width == initial_width: do nothing, unless a via has its drill value changed change_ok = true; } if( change_ok ) { OnModify(); if( aItemsListPicker ) { aTrackItem->SetWidth( initial_width ); ITEM_PICKER picker( aTrackItem, UR_CHANGED ); picker.SetLink( aTrackItem->Clone() ); aItemsListPicker->PushItem( picker ); aTrackItem->SetWidth( new_width ); if( aTrackItem->Type() == PCB_VIA_T ) { // Set new drill value. Note: currently microvias have only a default drill value VIA *via = static_cast<VIA *>( aTrackItem ); if( new_drill > 0 ) via->SetDrill( new_drill ); else via->SetDrillDefault(); } } } else { aTrackItem->SetWidth( initial_width ); } return change_ok; }
/* Route all traces * : * 1 if OK * -1 if escape (stop being routed) request * -2 if default memory allocation */ int PCB_EDIT_FRAME::Solve( wxDC* DC, int aLayersCount ) { int current_net_code; int row_source, col_source, row_target, col_target; int success, nbsucces = 0, nbunsucces = 0; NETINFO_ITEM* net; bool stop = false; wxString msg; int routedCount = 0; // routed ratsnest count bool two_sides = aLayersCount == 2; m_canvas->SetAbortRequest( false ); s_Clearance = GetBoard()->GetDesignSettings().GetDefault()->GetClearance(); // Prepare the undo command info s_ItemsListPicker.ClearListAndDeleteItems(); // Should not be necessary, but... // go until no more work to do GetWork( &row_source, &col_source, ¤t_net_code, &row_target, &col_target, &pt_cur_ch ); // First net to route. for( ; row_source != ILLEGAL; GetWork( &row_source, &col_source, ¤t_net_code, &row_target, &col_target, &pt_cur_ch ) ) { // Test to stop routing ( escape key pressed ) wxYield(); if( m_canvas->GetAbortRequest() ) { if( IsOK( this, _( "Abort routing?" ) ) ) { success = STOP_FROM_ESC; stop = true; break; } else { m_canvas->SetAbortRequest( false ); } } EraseMsgBox(); routedCount++; net = GetBoard()->FindNet( current_net_code ); if( net ) { msg.Printf( wxT( "[%8.8s]" ), GetChars( net->GetNetname() ) ); AppendMsgPanel( wxT( "Net route" ), msg, BROWN ); msg.Printf( wxT( "%d / %d" ), routedCount, RoutingMatrix.m_RouteCount ); AppendMsgPanel( wxT( "Activity" ), msg, BROWN ); } segm_oX = GetBoard()->GetBoundingBox().GetX() + (RoutingMatrix.m_GridRouting * col_source); segm_oY = GetBoard()->GetBoundingBox().GetY() + (RoutingMatrix.m_GridRouting * row_source); segm_fX = GetBoard()->GetBoundingBox().GetX() + (RoutingMatrix.m_GridRouting * col_target); segm_fY = GetBoard()->GetBoundingBox().GetY() + (RoutingMatrix.m_GridRouting * row_target); // Draw segment. GRLine( m_canvas->GetClipBox(), DC, segm_oX, segm_oY, segm_fX, segm_fY, 0, WHITE ); pt_cur_ch->m_PadStart->Draw( m_canvas, DC, GR_OR | GR_HIGHLIGHT ); pt_cur_ch->m_PadEnd->Draw( m_canvas, DC, GR_OR | GR_HIGHLIGHT ); success = Autoroute_One_Track( this, DC, two_sides, row_source, col_source, row_target, col_target, pt_cur_ch ); switch( success ) { case NOSUCCESS: pt_cur_ch->m_Status |= CH_UNROUTABLE; nbunsucces++; break; case STOP_FROM_ESC: stop = true; break; case ERR_MEMORY: stop = true; break; default: nbsucces++; break; } msg.Printf( wxT( "%d" ), nbsucces ); AppendMsgPanel( wxT( "OK" ), msg, GREEN ); msg.Printf( wxT( "%d" ), nbunsucces ); AppendMsgPanel( wxT( "Fail" ), msg, RED ); msg.Printf( wxT( " %d" ), GetBoard()->GetUnconnectedNetCount() ); AppendMsgPanel( wxT( "Not Connected" ), msg, CYAN ); // Delete routing from display. pt_cur_ch->m_PadStart->Draw( m_canvas, DC, GR_AND ); pt_cur_ch->m_PadEnd->Draw( m_canvas, DC, GR_AND ); if( stop ) break; } SaveCopyInUndoList( s_ItemsListPicker, UR_UNSPECIFIED ); s_ItemsListPicker.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items return SUCCESS; }
bool PCB_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType ) { switch( (IO_MGR::PCB_FILE_T) aFileType ) { case IO_MGR::EAGLE: if( OpenProjectFiles( std::vector<wxString>( 1, aFileName ), KICTL_EAGLE_BRD ) ) { wxString projectpath = Kiway().Prj().GetProjectPath(); wxFileName newfilename; newfilename.SetPath( Prj().GetProjectPath() ); newfilename.SetName( Prj().GetProjectName() ); newfilename.SetExt( KiCadPcbFileExtension ); GetBoard()->SetFileName( newfilename.GetFullPath() ); UpdateTitle(); OnModify(); // Extract a footprint library from the design and add it to the fp-lib-table wxString newLibPath; ArchiveModulesOnBoard( true, newfilename.GetName(), &newLibPath ); if( newLibPath.Length() > 0 ) { FP_LIB_TABLE* prjlibtable = Prj().PcbFootprintLibs(); const wxString& project_env = PROJECT_VAR_NAME; wxString rel_path, env_path; wxGetEnv( project_env, &env_path ); wxString result( newLibPath ); rel_path = result.Replace( env_path, wxString( "$(" + project_env + ")" ) ) ? result : "" ; if( !rel_path.IsEmpty() ) newLibPath = rel_path; FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( newfilename.GetName(), newLibPath, wxT( "KiCad" ), wxEmptyString ); prjlibtable->InsertRow( row ); } if( !GetBoard()->GetFileName().IsEmpty() ) { wxString tblName = Prj().FootprintLibTblName(); try { Prj().PcbFootprintLibs()->Save( tblName ); } catch( const IO_ERROR& ioe ) { wxString msg = wxString::Format( _( "Error occurred saving project specific footprint library " "table:\n\n%s" ), GetChars( ioe.What() ) ); wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR ); } } // Update module LIB_IDs to point to the just imported Eagle library for( MODULE* module : GetBoard()->Modules() ) { LIB_ID libId = module->GetFPID(); if( libId.GetLibItemName().empty() ) continue; libId.SetLibNickname( newfilename.GetName() ); module->SetFPID( libId ); } // Store net names for all pads, to create net remap information std::unordered_map<D_PAD*, wxString> netMap; for( const auto& pad : GetBoard()->GetPads() ) { NETINFO_ITEM* netinfo = pad->GetNet(); if( netinfo->GetNet() > 0 && !netinfo->GetNetname().IsEmpty() ) netMap[pad] = netinfo->GetNetname(); } // Two stage netlist update: // - first, assign valid timestamps to footprints (no reannotation) // - second, perform schematic annotation and update footprint references // based on timestamps NETLIST netlist; FetchNetlistFromSchematic( netlist, NO_ANNOTATION ); DoUpdatePCBFromNetlist( netlist, false ); FetchNetlistFromSchematic( netlist, QUIET_ANNOTATION ); DoUpdatePCBFromNetlist( netlist, true ); std::unordered_map<wxString, wxString> netRemap; // Compare the old net names with the new net names and create a net map for( const auto& pad : GetBoard()->GetPads() ) { auto it = netMap.find( pad ); if( it == netMap.end() ) continue; NETINFO_ITEM* netinfo = pad->GetNet(); // Net name has changed, create a remap entry if( netinfo->GetNet() > 0 && netMap[pad] != netinfo->GetNetname() ) netRemap[netMap[pad]] = netinfo->GetNetname(); } if( !netRemap.empty() ) fixEagleNets( netRemap ); return true; } return false; default: return false; } return false; }
bool PCB_EDIT_FRAME::Other_Layer_Route( TRACK* aTrack, wxDC* DC ) { unsigned itmp; if( aTrack == NULL ) { if( GetActiveLayer() != GetScreen()->m_Route_Layer_TOP ) SetActiveLayer( GetScreen()->m_Route_Layer_TOP ); else SetActiveLayer( GetScreen()->m_Route_Layer_BOTTOM ); UpdateStatusBar(); return true; } // Avoid more than one via on the current location: if( GetBoard()->GetViaByPosition( g_CurrentTrackSegment->GetEnd(), g_CurrentTrackSegment->GetLayer() ) ) return false; for( TRACK* segm = g_FirstTrackSegment; segm; segm = segm->Next() ) { if( segm->Type() == PCB_VIA_T && g_CurrentTrackSegment->GetEnd() == segm->GetStart() ) return false; } // Is the current segment Ok (no DRC error) ? if( g_Drc_On ) { if( BAD_DRC==m_drc->Drc( g_CurrentTrackSegment, GetBoard()->m_Track ) ) // DRC error, the change layer is not made return false; // Handle 2 segments. if( g_TwoSegmentTrackBuild && g_CurrentTrackSegment->Back() ) { if( BAD_DRC == m_drc->Drc( g_CurrentTrackSegment->Back(), GetBoard()->m_Track ) ) return false; } } /* Save current state before placing a via. * If the via cannot be placed this current state will be reused */ itmp = g_CurrentTrackList.GetCount(); Begin_Route( g_CurrentTrackSegment, DC ); m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); // create the via VIA* via = new VIA( GetBoard() ); via->SetFlags( IS_NEW ); via->SetViaType( GetDesignSettings().m_CurrentViaType ); via->SetNetCode( GetBoard()->GetHighLightNetCode() ); via->SetPosition( g_CurrentTrackSegment->GetEnd() ); // for microvias, the size and hole will be changed later. via->SetWidth( GetDesignSettings().GetCurrentViaSize()); via->SetDrill( GetDesignSettings().GetCurrentViaDrill() ); // Usual via is from copper to component. // layer pair is B_Cu and F_Cu. via->SetLayerPair( B_Cu, F_Cu ); LAYER_ID first_layer = GetActiveLayer(); LAYER_ID last_layer; // prepare switch to new active layer: if( first_layer != GetScreen()->m_Route_Layer_TOP ) last_layer = GetScreen()->m_Route_Layer_TOP; else last_layer = GetScreen()->m_Route_Layer_BOTTOM; // Adjust the actual via layer pair switch( via->GetViaType() ) { case VIA_BLIND_BURIED: via->SetLayerPair( first_layer, last_layer ); break; case VIA_MICROVIA: // from external to the near neighbor inner layer { LAYER_ID last_inner_layer = ToLAYER_ID( ( GetBoard()->GetCopperLayerCount() - 2 ) ); if( first_layer == B_Cu ) last_layer = last_inner_layer; else if( first_layer == F_Cu ) last_layer = In1_Cu; else if( first_layer == last_inner_layer ) last_layer = B_Cu; else if( first_layer == In1_Cu ) last_layer = F_Cu; // else error: will be removed later via->SetLayerPair( first_layer, last_layer ); // Update diameter and hole size, which where set previously // for normal vias NETINFO_ITEM* net = via->GetNet(); via->SetWidth( net->GetMicroViaSize() ); via->SetDrill( net->GetMicroViaDrillSize() ); } break; default: break; } if( g_Drc_On && BAD_DRC == m_drc->Drc( via, GetBoard()->m_Track ) ) { // DRC fault: the Via cannot be placed here ... delete via; m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); // delete the track(s) added in Begin_Route() while( g_CurrentTrackList.GetCount() > itmp ) { Delete_Segment( DC, g_CurrentTrackSegment ); } SetCurItem( g_CurrentTrackSegment, false ); // Refresh DRC diag, erased by previous calls if( m_drc->GetCurrentMarker() ) SetMsgPanel( m_drc->GetCurrentMarker() ); return false; } SetActiveLayer( last_layer ); TRACK* lastNonVia = g_CurrentTrackSegment; /* A new via was created. It was Ok. */ g_CurrentTrackList.PushBack( via ); /* The via is now in linked list and we need a new track segment * after the via, starting at via location. * it will become the new current segment (from via to the mouse cursor) */ TRACK* track = (TRACK*)lastNonVia->Clone(); /* the above creates a new segment from the last entered segment, with the * current width, flags, netcode, etc... values. * layer, start and end point are not correct, * and will be modified next */ // set the layer to the new value track->SetLayer( GetActiveLayer() ); /* the start point is the via position and the end point is the cursor * which also is on the via (will change when moving mouse) */ track->SetEnd( via->GetStart() ); track->SetStart( via->GetStart() ); g_CurrentTrackList.PushBack( track ); if( g_TwoSegmentTrackBuild ) { // Create a second segment (we must have 2 track segments to adjust) g_CurrentTrackList.PushBack( (TRACK*)g_CurrentTrackSegment->Clone() ); } m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); SetMsgPanel( via ); UpdateStatusBar(); return true; }
void PCB_EDIT_FRAME::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* aZone ) { ZONE_EDIT_T edited; ZONE_SETTINGS zoneInfo = GetZoneSettings(); m_canvas->SetIgnoreMouseEvents( true ); // Save initial zones configuration, for undo/redo, before adding new zone // note the net name and the layer can be changed, so we must save all zones s_AuxiliaryList.ClearListAndDeleteItems(); s_PickedList.ClearListAndDeleteItems(); SaveCopyOfZones(s_PickedList, GetBoard(), -1, -1 ); if( aZone->GetIsKeepout() ) { // edit a keepout area on a copper layer zoneInfo << *aZone; edited = InvokeKeepoutAreaEditor( this, &zoneInfo ); } else if( aZone->GetLayer() < FIRST_NO_COPPER_LAYER ) { // edit a zone on a copper layer zoneInfo << *aZone; edited = InvokeCopperZonesEditor( this, &zoneInfo ); } else { edited = InvokeNonCopperZonesEditor( this, aZone, &zoneInfo ); } m_canvas->MoveCursorToCrossHair(); m_canvas->SetIgnoreMouseEvents( false ); if( edited == ZONE_ABORT ) { s_AuxiliaryList.ClearListAndDeleteItems(); s_PickedList.ClearListAndDeleteItems(); return; } SetZoneSettings( zoneInfo ); if( edited == ZONE_EXPORT_VALUES ) { UpdateCopyOfZonesList( s_PickedList, s_AuxiliaryList, GetBoard() ); SaveCopyInUndoList(s_PickedList, UR_UNSPECIFIED); s_PickedList.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items return; } // Undraw old zone outlines for( int ii = 0; ii < GetBoard()->GetAreaCount(); ii++ ) { ZONE_CONTAINER* edge_zone = GetBoard()->GetArea( ii ); edge_zone->Draw( m_canvas, DC, GR_XOR ); } zoneInfo.ExportSetting( *aZone ); NETINFO_ITEM* net = GetBoard()->FindNet( zoneInfo.m_NetcodeSelection ); if( net ) // net == NULL should not occur aZone->SetNetName( net->GetNetname() ); // Combine zones if possible GetBoard()->OnAreaPolygonModified( &s_AuxiliaryList, aZone ); // Redraw the real new zone outlines GetBoard()->RedrawAreasOutlines( m_canvas, DC, GR_OR, -1 ); UpdateCopyOfZonesList( s_PickedList, s_AuxiliaryList, GetBoard() ); SaveCopyInUndoList(s_PickedList, UR_UNSPECIFIED); s_PickedList.ClearItemsList(); // s_ItemsListPicker is no longer owner of picked items OnModify(); }
bool DIALOG_COPPER_ZONE::AcceptOptions( bool aPromptForErrors, bool aUseExportableSetupOnly ) { switch( m_PadInZoneOpt->GetSelection() ) { case 3: // Pads are not covered m_settings.SetPadConnection( PAD_NOT_IN_ZONE ); break; case 2: // Use thermal relief for THT pads m_settings.SetPadConnection( THT_THERMAL ); break; case 1: // Use thermal relief for pads m_settings.SetPadConnection( THERMAL_PAD ); break; case 0: // pads are covered by copper m_settings.SetPadConnection( PAD_IN_ZONE ); break; } switch( m_OutlineAppearanceCtrl->GetSelection() ) { case 0: m_settings.m_Zone_HatchingStyle = CPolyLine::NO_HATCH; break; case 1: m_settings.m_Zone_HatchingStyle = CPolyLine::DIAGONAL_EDGE; break; case 2: m_settings.m_Zone_HatchingStyle = CPolyLine::DIAGONAL_FULL; break; } m_settings.m_ArcToSegmentsCount = m_ArcApproximationOpt->GetSelection() == 1 ? ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF : ARC_APPROX_SEGMENTS_COUNT_LOW_DEF; if( m_Config ) { m_Config->Write( ZONE_NET_OUTLINES_HATCH_OPTION_KEY, (long) m_settings.m_Zone_HatchingStyle ); wxString filter = m_DoNotShowNetNameFilter->GetValue(); m_Config->Write( ZONE_NET_FILTER_STRING_KEY, filter ); } m_netNameShowFilter = m_ShowNetNameFilter->GetValue(); m_settings.m_FillMode = (m_FillModeCtrl->GetSelection() == 0) ? 0 : 1; wxString txtvalue = m_ZoneClearanceCtrl->GetValue(); m_settings.m_ZoneClearance = ReturnValueFromString( g_UserUnit, txtvalue ); // Test if this is a reasonable value for this parameter // A too large value can hang Pcbnew #define CLEARANCE_MAX_VALUE ZONE_CLEARANCE_MAX_VALUE_MIL*IU_PER_MILS if( m_settings.m_ZoneClearance > CLEARANCE_MAX_VALUE ) { wxString msg; msg.Printf( _( "Clearance must be smaller than %f\" / %f mm." ), ZONE_CLEARANCE_MAX_VALUE_MIL / 1000.0, ZONE_CLEARANCE_MAX_VALUE_MIL * 0.0254 ); DisplayError( this, msg ); return false; } txtvalue = m_ZoneMinThicknessCtrl->GetValue(); m_settings.m_ZoneMinThickness = ReturnValueFromString( g_UserUnit, txtvalue ); if( m_settings.m_ZoneMinThickness < (ZONE_THICKNESS_MIN_VALUE_MIL*IU_PER_MILS) ) { wxString msg; msg.Printf( _( "Minimum width must be larger than %f\" / %f mm." ), ZONE_THICKNESS_MIN_VALUE_MIL / 1000.0, ZONE_THICKNESS_MIN_VALUE_MIL * 0.0254 ); DisplayError( this, msg ); return false; } m_settings.SetCornerSmoothingType( m_cornerSmoothingChoice->GetSelection() ); txtvalue = m_cornerSmoothingCtrl->GetValue(); m_settings.SetCornerRadius( ReturnValueFromString( g_UserUnit, txtvalue ) ); m_settings.m_ZonePriority = m_PriorityLevelCtrl->GetValue(); if( m_OrientEdgesOpt->GetSelection() == 0 ) m_settings.m_Zone_45_Only = false; else m_settings.m_Zone_45_Only = true; m_settings.m_ThermalReliefGap = ReturnValueFromTextCtrl( *m_AntipadSizeValue ); m_settings.m_ThermalReliefCopperBridge = ReturnValueFromTextCtrl( *m_CopperWidthValue ); if( m_Config ) { ConfigBaseWriteDouble( m_Config, ZONE_CLEARANCE_WIDTH_STRING_KEY, (double) m_settings.m_ZoneClearance / IU_PER_MILS ); ConfigBaseWriteDouble( m_Config, ZONE_MIN_THICKNESS_WIDTH_STRING_KEY, (double) m_settings.m_ZoneMinThickness / IU_PER_MILS ); ConfigBaseWriteDouble( m_Config, ZONE_THERMAL_RELIEF_GAP_STRING_KEY, (double) m_settings.m_ThermalReliefGap / IU_PER_MILS ); ConfigBaseWriteDouble( m_Config, ZONE_THERMAL_RELIEF_COPPER_WIDTH_STRING_KEY, (double) m_settings.m_ThermalReliefCopperBridge / IU_PER_MILS ); } if( m_settings.m_ThermalReliefCopperBridge <= m_settings.m_ZoneMinThickness ) { DisplayError( this, _( "Thermal relief spoke width is smaller than the minimum width." ) ); return false; } // If we use only exportable to others zones parameters, exit here: if( aUseExportableSetupOnly ) return true; // Get the layer selection for this zone int ii = m_LayerSelectionCtrl->GetFirstSelected(); if( ii < 0 && aPromptForErrors ) { DisplayError( this, _( "No layer selected." ) ); return false; } m_settings.m_CurrentZone_Layer = m_LayerId[ii]; // Get the net name selection for this zone ii = m_ListNetNameSelection->GetSelection(); if( ii < 0 && aPromptForErrors ) { DisplayError( this, _( "No net selected." ) ); return false; } if( ii == 0 ) // the not connected option was selected: this is not a good practice: warn: { if( !IsOK( this, _( "You have chosen the \"not connected\" option. This will create insulated copper islands. Are you sure ?" ) ) ) return false; } wxString net_name = m_ListNetNameSelection->GetString( ii ); m_settings.m_NetcodeSelection = 0; // Search net_code for this net, if a net was selected if( m_ListNetNameSelection->GetSelection() > 0 ) { NETINFO_ITEM* net = m_Parent->GetBoard()->FindNet( net_name ); if( net ) m_settings.m_NetcodeSelection = net->GetNet(); } return true; }
void ZONE_CONTAINER::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) { wxString msg; msg = _( "Zone Outline" ); // Display Cutout instead of Outline for holes inside a zone // i.e. when num contour !=0 int ncont = m_Poly->GetContour( m_CornerSelection ); if( ncont ) msg << wxT( " " ) << _( "(Cutout)" ); aList.push_back( MSG_PANEL_ITEM( _( "Type" ), msg, DARKCYAN ) ); if( GetIsKeepout() ) { msg.Empty(); if( GetDoNotAllowVias() ) AccumulateDescription( msg, _("No via") ); if( GetDoNotAllowTracks() ) AccumulateDescription( msg, _("No track") ); if( GetDoNotAllowCopperPour() ) AccumulateDescription( msg, _("No copper pour") ); aList.push_back( MSG_PANEL_ITEM( _( "Keepout" ), msg, RED ) ); } else if( IsOnCopperLayer() ) { if( GetNetCode() >= 0 ) { NETINFO_ITEM* equipot = GetNet(); if( equipot ) msg = equipot->GetNetname(); else msg = wxT( "<noname>" ); } else // a netcode < 0 is an error { msg = wxT( " [" ); msg << GetNetname() + wxT( "]" ); msg << wxT( " <" ) << _( "Not Found" ) << wxT( ">" ); } aList.push_back( MSG_PANEL_ITEM( _( "NetName" ), msg, RED ) ); #if 1 // Display net code : (useful in test or debug) msg.Printf( wxT( "%d" ), GetNetCode() ); aList.push_back( MSG_PANEL_ITEM( _( "NetCode" ), msg, RED ) ); #endif // Display priority level msg.Printf( wxT( "%d" ), GetPriority() ); aList.push_back( MSG_PANEL_ITEM( _( "Priority" ), msg, BLUE ) ); } else { aList.push_back( MSG_PANEL_ITEM( _( "Non Copper Zone" ), wxEmptyString, RED ) ); } aList.push_back( MSG_PANEL_ITEM( _( "Layer" ), GetLayerName(), BROWN ) ); msg.Printf( wxT( "%d" ), (int) m_Poly->m_CornersList.GetCornersCount() ); aList.push_back( MSG_PANEL_ITEM( _( "Corners" ), msg, BLUE ) ); if( m_FillMode ) msg = _( "Segments" ); else msg = _( "Polygons" ); aList.push_back( MSG_PANEL_ITEM( _( "Fill mode" ), msg, BROWN ) ); // Useful for statistics : msg.Printf( wxT( "%d" ), (int) m_Poly->m_HatchLines.size() ); aList.push_back( MSG_PANEL_ITEM( _( "Hatch lines" ), msg, BLUE ) ); if( m_FilledPolysList.GetCornersCount() ) { msg.Printf( wxT( "%d" ), (int) m_FilledPolysList.GetCornersCount() ); aList.push_back( MSG_PANEL_ITEM( _( "Corners in DrawList" ), msg, BLUE ) ); } }
void VIA::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, const wxPoint& aOffset ) { int radius; LAYER_NUM curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer; int fillvia = 0; PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) panel->GetParent(); PCB_SCREEN* screen = frame->GetScreen(); if( frame->m_DisplayViaFill == FILLED ) fillvia = 1; GRSetDrawMode( aDC, aDrawMode ); BOARD * brd = GetBoard( ); EDA_COLOR_T color = brd->GetVisibleElementColor(VIAS_VISIBLE + GetViaType()); if( brd->IsElementVisible( PCB_VISIBLE(VIAS_VISIBLE + GetViaType()) ) == false && ( color & HIGHLIGHT_FLAG ) != HIGHLIGHT_FLAG ) return; if( DisplayOpt.ContrastModeDisplay ) { if( !IsOnLayer( curr_layer ) ) ColorTurnToDarkDarkGray( &color ); } if( aDrawMode & GR_HIGHLIGHT ) ColorChangeHighlightFlag( &color, !(aDrawMode & GR_AND) ); ColorApplyHighlightFlag( &color ); SetAlpha( &color, 150 ); radius = m_Width >> 1; // for small via size on screen (radius < 4 pixels) draw a simplified shape int radius_in_pixels = aDC->LogicalToDeviceXRel( radius ); bool fast_draw = false; // Vias are drawn as a filled circle or a double circle. The hole will be drawn later int drill_radius = GetDrillValue() / 2; int inner_radius = radius - aDC->DeviceToLogicalXRel( 2 ); if( radius_in_pixels < MIN_VIA_DRAW_SIZE ) { fast_draw = true; fillvia = false; } if( fillvia ) { GRFilledCircle( panel->GetClipBox(), aDC, m_Start + aOffset, radius, color ); } else { GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, radius, 0, color ); if ( fast_draw ) return; GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, inner_radius, 0, color ); } // Draw the via hole if the display option allows it if( DisplayOpt.m_DisplayViaMode != VIA_HOLE_NOT_SHOW ) { // Display all drill holes requested or Display non default holes requested if( (DisplayOpt.m_DisplayViaMode == ALL_VIA_HOLE_SHOW) || ( (drill_radius > 0 ) && !IsDrillDefault() ) ) { if( fillvia ) { bool blackpenstate = false; if( screen->m_IsPrinting ) { blackpenstate = GetGRForceBlackPenState(); GRForceBlackPen( false ); color = WHITE; } else { color = BLACK; // or DARKGRAY; } if( (aDrawMode & GR_XOR) == 0) GRSetDrawMode( aDC, GR_COPY ); if( aDC->LogicalToDeviceXRel( drill_radius ) > MIN_DRAW_WIDTH ) // Draw hole if large enough. GRFilledCircle( panel->GetClipBox(), aDC, m_Start.x + aOffset.x, m_Start.y + aOffset.y, drill_radius, 0, color, color ); if( screen->m_IsPrinting ) GRForceBlackPen( blackpenstate ); } else { if( drill_radius < inner_radius ) // We can show the via hole GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, drill_radius, 0, color ); } } } if( ShowClearance( this ) ) { GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, radius + GetClearance(), 0, color ); } // for Micro Vias, draw a partial cross : X on component layer, or + on copper layer // (so we can see 2 superimposed microvias ): if( GetViaType() == VIA_MICROVIA ) { int ax, ay, bx, by; if( IsOnLayer( LAYER_N_BACK ) ) { ax = radius; ay = 0; bx = drill_radius; by = 0; } else { ax = ay = (radius * 707) / 1000; bx = by = (drill_radius * 707) / 1000; } /* lines | or \ */ GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - ax, m_Start.y + aOffset.y - ay, m_Start.x + aOffset.x - bx, m_Start.y + aOffset.y - by, 0, color ); GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x + bx, m_Start.y + aOffset.y + by, m_Start.x + aOffset.x + ax, m_Start.y + aOffset.y + ay, 0, color ); // lines - or / GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x + ay, m_Start.y + aOffset.y - ax, m_Start.x + aOffset.x + by, m_Start.y + aOffset.y - bx, 0, color ); GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - by, m_Start.y + aOffset.y + bx, m_Start.x + aOffset.x - ay, m_Start.y + aOffset.y + ax, 0, color ); } // for Buried Vias, draw a partial line : orient depending on layer pair // (so we can see superimposed buried vias ): if( GetViaType() == VIA_BLIND_BURIED ) { int ax = 0, ay = radius, bx = 0, by = drill_radius; LAYER_NUM layer_top, layer_bottom; ( (VIA*) this )->LayerPair( &layer_top, &layer_bottom ); // lines for the top layer RotatePoint( &ax, &ay, layer_top * 3600.0 / brd->GetCopperLayerCount( ) ); RotatePoint( &bx, &by, layer_top * 3600.0 / brd->GetCopperLayerCount( ) ); GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - ax, m_Start.y + aOffset.y - ay, m_Start.x + aOffset.x - bx, m_Start.y + aOffset.y - by, 0, color ); // lines for the bottom layer ax = 0; ay = radius; bx = 0; by = drill_radius; RotatePoint( &ax, &ay, layer_bottom * 3600.0 / brd->GetCopperLayerCount( ) ); RotatePoint( &bx, &by, layer_bottom * 3600.0 / brd->GetCopperLayerCount( ) ); GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - ax, m_Start.y + aOffset.y - ay, m_Start.x + aOffset.x - bx, m_Start.y + aOffset.y - by, 0, color ); } // Display the short netname: if( GetNetCode() == NETINFO_LIST::UNCONNECTED ) return; if( DisplayOpt.DisplayNetNamesMode == 0 || DisplayOpt.DisplayNetNamesMode == 1 ) return; NETINFO_ITEM* net = GetNet(); if( net == NULL ) return; int len = net->GetShortNetname().Len(); if( len > 0 ) { // calculate a good size for the text int tsize = m_Width / len; if( aDC->LogicalToDeviceXRel( tsize ) >= MIN_TEXT_SIZE ) { tsize = (tsize * 7) / 10; // small reduction to give a better look, inside via if( (aDrawMode & GR_XOR) == 0 ) GRSetDrawMode( aDC, GR_COPY ); EDA_RECT* clipbox = panel? panel->GetClipBox() : NULL; DrawGraphicHaloText( clipbox, aDC, m_Start, color, WHITE, BLACK, net->GetShortNetname(), 0, wxSize( tsize, tsize ), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, tsize / 7, false, false ); } } }
void DIALOG_COPPER_ZONE::buildAvailableListOfNets() { wxArrayString listNetName; m_Parent->GetBoard()->ReturnSortedNetnamesList( listNetName, m_NetSortingByPadCount ); if( m_NetFiltering ) { wxString doNotShowFilter = m_DoNotShowNetNameFilter->GetValue(); wxString ShowFilter = m_ShowNetNameFilter->GetValue(); for( unsigned ii = 0; ii < listNetName.GetCount(); ii++ ) { if( listNetName[ii].Matches( doNotShowFilter ) ) { listNetName.RemoveAt( ii ); ii--; } else if( !listNetName[ii].Matches( ShowFilter ) ) { listNetName.RemoveAt( ii ); ii--; } } } listNetName.Insert( wxT( "<no net>" ), 0 ); // Ensure currently selected net for the zone is visible, regardless of filters int selectedNetListNdx = -1; int net_select = m_settings.m_NetcodeSelection; if( net_select > 0 ) { NETINFO_ITEM* equipot = m_Parent->GetBoard()->FindNet( net_select ); if( equipot ) { selectedNetListNdx = listNetName.Index( equipot->GetNetname() ); if( wxNOT_FOUND == selectedNetListNdx ) { // the currently selected net must *always* be visible. listNetName.Insert( equipot->GetNetname(), 0 ); selectedNetListNdx = 0; } } } else if( net_select == 0 ) selectedNetListNdx = 0; // SetSelection() on "<no net>" else { // selectedNetListNdx remains -1, no net selected. } m_ListNetNameSelection->Clear(); m_ListNetNameSelection->InsertItems( listNetName, 0 ); m_ListNetNameSelection->SetSelection( 0 ); if( selectedNetListNdx >= 0 ) { m_ListNetNameSelection->SetSelection( selectedNetListNdx ); m_ListNetNameSelection->EnsureVisible( selectedNetListNdx ); } }
void BOARD::SynchronizeNetsAndNetClasses() { // D(printf("start\n");) // simple performance/timing indicator. // set all NETs to the default NETCLASS, then later override some // as we go through the NETCLASSes. int count = m_NetInfo.GetNetCount(); for( int i=0; i<count; ++i ) { NETINFO_ITEM* net = FindNet( i ); if( net ) net->SetClass( m_NetClasses.GetDefault() ); } // Add netclass name and pointer to nets. If a net is in more than one netclass, // set the net's name and pointer to only the first netclass. Subsequent // and therefore bogus netclass memberships will be deleted in logic below this loop. for( NETCLASSES::iterator clazz=m_NetClasses.begin(); clazz!=m_NetClasses.end(); ++clazz ) { NETCLASS* netclass = clazz->second; for( NETCLASS::iterator member = netclass->begin(); member!=netclass->end(); ++member ) { const wxString& netname = *member; // although this overall function seems to be adequately fast, // FindNet( wxString ) uses now a fast binary search and is fast // event for large net lists NETINFO_ITEM* net = FindNet( netname ); if( net && net->GetClassName() == NETCLASS::Default ) { net->SetClass( netclass ); } } } // Finally, make sure that every NET is in a NETCLASS, even if that // means the Default NETCLASS. And make sure that all NETCLASSes do not // contain netnames that do not exist, by deleting all netnames from // every netclass and re-adding them. for( NETCLASSES::iterator clazz=m_NetClasses.begin(); clazz!=m_NetClasses.end(); ++clazz ) { NETCLASS* netclass = clazz->second; netclass->Clear(); } m_NetClasses.GetDefault()->Clear(); for( int i=0; i<count; ++i ) { NETINFO_ITEM* net = FindNet( i ); if( net ) { const wxString& classname = net->GetClassName(); // because of the std:map<> this should be fast, and because of // prior logic, netclass should not be NULL. NETCLASS* netclass = m_NetClasses.Find( classname ); wxASSERT( netclass ); netclass->Add( net->GetNetname() ); } } // D(printf("stop\n");) }