bool CN_VISITOR::operator()( CN_ITEM* aCandidate ) { const auto parentA = aCandidate->Parent(); const auto parentB = m_item->Parent(); if( !aCandidate->Valid() || !m_item->Valid() ) return true; if( parentA == parentB ) return true; if( !( parentA->GetLayerSet() & parentB->GetLayerSet() ).any() ) return true; // If both m_item and aCandidate are marked dirty, they will both be searched // Since we are reciprocal in our connection, we arbitrarily pick one of the connections // to conduct the expensive search if( aCandidate->Dirty() && aCandidate < m_item ) return true; // We should handle zone-zone connection separately if ( parentA->Type() == PCB_ZONE_AREA_T && parentB->Type() == PCB_ZONE_AREA_T ) { checkZoneZoneConnection( static_cast<CN_ZONE*>( m_item ), static_cast<CN_ZONE*>( aCandidate ) ); return true; } if( parentA->Type() == PCB_ZONE_AREA_T ) { checkZoneItemConnection( static_cast<CN_ZONE*>( aCandidate ), m_item ); return true; } if( parentB->Type() == PCB_ZONE_AREA_T ) { checkZoneItemConnection( static_cast<CN_ZONE*>( m_item ), aCandidate ); return true; } // Items do not necessarily have reciprocity as we only check for anchors // therefore, we check HitTest both directions A->B & B->A // TODO: Check for collision geometry on extended features wxPoint ptA1( aCandidate->GetAnchor( 0 ).x, aCandidate->GetAnchor( 0 ).y ); wxPoint ptA2( aCandidate->GetAnchor( 1 ).x, aCandidate->GetAnchor( 1 ).y ); wxPoint ptB1( m_item->GetAnchor( 0 ).x, m_item->GetAnchor( 0 ).y ); wxPoint ptB2( m_item->GetAnchor( 1 ).x, m_item->GetAnchor( 1 ).y ); if( parentA->HitTest( ptB1 ) || parentB->HitTest( ptA1 ) || ( parentA->Type() == PCB_TRACE_T && parentB->HitTest( ptA2 ) ) || ( parentB->Type() == PCB_TRACE_T && parentA->HitTest( ptB2 ) ) ) { m_item->Connect( aCandidate ); aCandidate->Connect( m_item ); } return true; };
unsigned int VIA::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const { BOARD* board = GetBoard(); // Only draw the via if at least one of the layers it crosses is being displayed if( board && ( board->GetVisibleLayers() & GetLayerSet() ).any() ) return 0; return std::numeric_limits<unsigned int>::max(); }
unsigned int D_PAD::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const { if( aView->GetPrintMode() > 0 ) // In printing mode the pad is always drawable return 0; const int HIDE = std::numeric_limits<unsigned int>::max(); BOARD* board = GetBoard(); // Handle Render tab switches if( ( GetAttribute() == PAD_ATTRIB_STANDARD || GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED ) && !aView->IsLayerVisible( LAYER_PADS_TH ) ) return HIDE; if( !IsFlipped() && !aView->IsLayerVisible( LAYER_MOD_FR ) ) return HIDE; if( IsFlipped() && !aView->IsLayerVisible( LAYER_MOD_BK ) ) return HIDE; if( IsFrontLayer( ( PCB_LAYER_ID )aLayer ) && !aView->IsLayerVisible( LAYER_PAD_FR ) ) return HIDE; if( IsBackLayer( ( PCB_LAYER_ID )aLayer ) && !aView->IsLayerVisible( LAYER_PAD_BK ) ) return HIDE; // Only draw the pad if at least one of the layers it crosses is being displayed if( board && !( board->GetVisibleLayers() & GetLayerSet() ).any() ) return HIDE; // Netnames will be shown only if zoom is appropriate if( IsNetnameLayer( aLayer ) ) { int divisor = std::max( m_Size.x, m_Size.y ); // Pad sizes can be zero briefly when someone is typing a number like "0.5" // in the pad properties dialog if( divisor == 0 ) return HIDE; return ( Millimeter2iu( 10 ) / divisor ); } // Other layers are shown without any conditions return 0; }
void BOARD_DESIGN_SETTINGS::SetCopperLayerCount( int aNewLayerCount ) { // if( aNewLayerCount < 2 ) aNewLayerCount = 2; m_copperLayerCount = aNewLayerCount; // ensure consistency with the m_EnabledLayers member #if 0 // was: m_enabledLayers &= ~ALL_CU_LAYERS; m_enabledLayers |= LAYER_BACK; if( m_copperLayerCount > 1 ) m_enabledLayers |= LAYER_FRONT; for( LAYER_NUM ii = LAYER_N_2; ii < aNewLayerCount - 1; ++ii ) m_enabledLayers |= GetLayerSet( ii ); #else // Update only enabled copper layers mask m_enabledLayers &= ~LSET::AllCuMask(); m_enabledLayers |= LSET::AllCuMask( aNewLayerCount ); #endif }
void VIA::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, const wxPoint& aOffset ) { int radius; LAYER_ID 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; // Only draw the via if at least one of the layers it crosses is being displayed if( !( brd->GetVisibleLayers() & GetLayerSet() ).any() ) 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( B_Cu ) ) { 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_ID 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 ); } } }
TRACK* TRACK::GetTrack( TRACK* aStartTrace, TRACK* aEndTrace, ENDPOINT_T aEndPoint, bool aSameNetOnly, bool aSequential ) { const wxPoint& position = GetEndPoint( aEndPoint ); LSET refLayers = GetLayerSet(); TRACK* previousSegment; TRACK* nextSegment; if( aSequential ) { // Simple sequential search: from aStartTrace forward to aEndTrace previousSegment = NULL; nextSegment = aStartTrace; } else { /* Local bidirectional search: from this backward to aStartTrace * AND forward to aEndTrace. The idea is that nearest segments * are found (on average) faster in this way. In fact same-net * segments are almost guaranteed to be found faster, in a global * search, since they are grouped together in the track list */ previousSegment = this; nextSegment = this; } while( nextSegment || previousSegment ) { // Terminate the search in the direction if the netcode mismatches if( aSameNetOnly ) { if( nextSegment && (nextSegment->GetNetCode() != GetNetCode()) ) nextSegment = NULL; if( previousSegment && (previousSegment->GetNetCode() != GetNetCode()) ) previousSegment = NULL; } if( nextSegment ) { if ( (nextSegment != this) && !nextSegment->GetState( BUSY | IS_DELETED ) && ( refLayers & nextSegment->GetLayerSet() ).any() ) { if( (position == nextSegment->m_Start) || (position == nextSegment->m_End) ) return nextSegment; } // Keep looking forward if( nextSegment == aEndTrace ) nextSegment = NULL; else nextSegment = nextSegment->Next(); } // Same as above, looking back. During sequential search this branch is inactive if( previousSegment ) { if( (previousSegment != this) && !previousSegment->GetState( BUSY | IS_DELETED ) && ( refLayers & previousSegment->GetLayerSet() ).any() ) { if( (position == previousSegment->m_Start) || (position == previousSegment->m_End) ) return previousSegment; } if( previousSegment == aStartTrace ) previousSegment = NULL; else previousSegment = previousSegment->Back(); } } return NULL; }
void VIA::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, const wxPoint& aOffset ) { wxCHECK_RET( panel != NULL, wxT( "VIA::Draw panel cannot be NULL." ) ); int radius; PCB_LAYER_ID 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(); auto displ_opts = (PCB_DISPLAY_OPTIONS*)( frame->GetDisplayOptions() ); if( displ_opts->m_DisplayViaFill == FILLED ) fillvia = 1; GRSetDrawMode( aDC, aDrawMode ); BOARD * brd = GetBoard(); COLOR4D color = frame->Settings().Colors().GetItemColor( LAYER_VIAS + GetViaType() ); if( brd->IsElementVisible( LAYER_VIAS + GetViaType() ) == false && !( aDrawMode & GR_HIGHLIGHT ) ) return; // Only draw the via if at least one of the layers it crosses is being displayed if( !( brd->GetVisibleLayers() & GetLayerSet() ).any() ) return; if( displ_opts->m_ContrastModeDisplay ) { if( !IsOnLayer( curr_layer ) ) color = COLOR4D( DARKDARKGRAY ); } if( ( aDrawMode & GR_HIGHLIGHT ) && !( aDrawMode & GR_AND ) ) color.SetToLegacyHighlightColor(); color.a = 0.588; 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 ); } 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 ); // Draw hole if the radius is > 1pixel. if( aDC->LogicalToDeviceXRel( drill_radius ) > 1 ) 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( displ_opts, 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( B_Cu ) ) { 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; PCB_LAYER_ID layer_top, layer_bottom; 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( displ_opts->m_DisplayNetNamesMode == 0 || displ_opts->m_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->GetClipBox(); 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 ); } } }