// Compute the access code for a pad. Returns -1 if there is no copper
static int compute_pad_access_code( BOARD *aPcb, LAYER_MSK aLayerMask )
{
    // Non-copper is not interesting here
    aLayerMask &= ALL_CU_LAYERS;
    if( aLayerMask == 0 )
        return -1;

    // Traditional TH pad
    if( (aLayerMask & LAYER_FRONT) && (aLayerMask & LAYER_BACK) )
        return 0;

    // Front SMD pad
    if( (aLayerMask & LAYER_FRONT) )
        return 1;

    // Back SMD pad
    if( (aLayerMask & LAYER_BACK) )
        return aPcb->GetCopperLayerCount();

    // OK, we have an inner-layer only pad (and I have no idea about
    // what could be used for); anyway, find the first copper layer
    // it's on
    for (LAYER_NUM scan_layer = LAYER_N_2;
            scan_layer < LAYER_N_BACK;
            ++scan_layer)
    {
        if( GetLayerMask( scan_layer ) & aLayerMask )
            return scan_layer + 1;
    }

    // This shouldn't happen
    return -1;
}
void BOARD_DESIGN_SETTINGS::SetLayerVisibility( LAYER_NUM aLayer, bool aNewState )
{
    if( aNewState && IsLayerEnabled( aLayer ) )
        m_VisibleLayers |= GetLayerMask( aLayer );
    else
        m_VisibleLayers &= ~GetLayerMask( aLayer );
}
Esempio n. 3
0
void DIALOG_LAYERS_SETUP::showSelectedLayerCheckBoxes( LAYER_MSK enabledLayers )
{
    for( LAYER_NUM layer=FIRST_LAYER; layer<NB_PCB_LAYERS; ++layer )
    {
        setLayerCheckBox( layer, GetLayerMask( layer ) & enabledLayers );
    }
}
Esempio n. 4
0
LAYER_MSK DIALOG_LAYERS_SETUP::getUILayerMask()
{
    LAYER_MSK layerMaskResult = NO_LAYERS;

    for( LAYER_NUM layer=FIRST_LAYER; layer<NB_PCB_LAYERS; ++layer )
    {
        wxCheckBox*  ctl = getCheckBox( layer );
        if( ctl->GetValue() )
        {
            layerMaskResult |= GetLayerMask( layer );
        }
    }

    return layerMaskResult;
}
void BOARD_DESIGN_SETTINGS::SetCopperLayerCount( int aNewLayerCount )
{
    // if( aNewLayerCount < 2 ) aNewLayerCount = 2;

    m_CopperLayerCount = aNewLayerCount;

    // ensure consistency with the m_EnabledLayers member
    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 |= GetLayerMask( ii );
}
Esempio n. 6
0
bool BOARD_PRINTOUT_CONTROLLER::OnPrintPage( int aPage )
{
#ifdef PCBNEW
    LAYER_NUM layers_count = NB_PCB_LAYERS;
#else
    LAYER_NUM layers_count = NB_LAYERS;
#endif

    LAYER_MSK mask_layer = m_PrintParams.m_PrintMaskLayer;

    // compute layer mask from page number if we want one page per layer
    if( m_PrintParams.m_OptionPrintPage == 0 )  // One page per layer
    {
        int jj;
        LAYER_NUM ii;

        for( ii = FIRST_LAYER, jj = 0; ii < layers_count; ++ii )
        {
            LAYER_MSK mask = GetLayerMask( ii );
            if( mask_layer & mask )
                jj++;

            if( jj == aPage )
            {
                m_PrintParams.m_PrintMaskLayer = mask;
                break;
            }
        }
    }

    if( m_PrintParams.m_PrintMaskLayer == 0 )
        return false;

#ifdef PCBNEW
    // In Pcbnew we can want the layer EDGE always printed
    if( m_PrintParams.m_Flags == 1 )
        m_PrintParams.m_PrintMaskLayer |= EDGE_LAYER;
#endif

    DrawPage();

    m_PrintParams.m_PrintMaskLayer = mask_layer;

    return true;
}
int DIALOG_PRINT_USING_PRINTER::SetLayerMaskFromListSelection()
/**************************************************************/
{
    int page_count = 0;
    s_Parameters.m_PrintMaskLayer = NO_LAYERS;
    for( LAYER_NUM ii = FIRST_LAYER; ii < NB_GERBER_LAYERS; ++ii )
    {
        if( m_BoxSelectLayer[ii]->IsChecked() )
        {
            page_count++;
            s_Parameters.m_PrintMaskLayer |= GetLayerMask( ii );
        }
    }

    s_Parameters.m_PageCount = page_count;

    return page_count;
}
// Reload the Layers
void PCB_LAYER_BOX_SELECTOR::Resync()
{
    Clear();

    static DECLARE_LAYERS_ORDER_LIST( layertranscode );
    static DECLARE_LAYERS_HOTKEY( layerhk );

    // Tray to fix a minimum width fot the BitmapComboBox
    int minwidth = 80, h;
    wxClientDC dc( GetParent() );   // The DC for "this" is not always initialized

    #define BM_SIZE 14
    for( LAYER_NUM i = FIRST_LAYER; i < NB_LAYERS; ++i )
    {
        wxBitmap   layerbmp( BM_SIZE, BM_SIZE );
        wxString   layername;
        LAYER_NUM  layerid = i;

        if( m_layerorder )
            layerid = layertranscode[i];

        if( ! IsLayerEnabled( layerid ) )
            continue;

        if( ( m_layerMaskDisable & GetLayerMask( layerid ) ) )
            continue;

        SetBitmapLayer( layerbmp, layerid );

        layername = GetLayerName( layerid );

        if( m_layerhotkeys && m_hotkeys != NULL )
            layername = AddHotkeyName( layername, m_hotkeys,
                                       layerhk[layerid], IS_COMMENT );

        Append( layername, layerbmp, (void*)(intptr_t) layerid );
        int w;
        dc.GetTextExtent ( layername, &w, &h );
        minwidth = std::max( minwidth, w );
    }

    minwidth += BM_SIZE + 35;    // Take in account the bitmap size and margins
    SetMinSize( wxSize( minwidth, -1 ) );
}
Esempio n. 9
0
	void Scene::Render() 
	{
		for ( Layer* pLayer : mLayerList )
		{
			if ( pLayer->GetLayerDepth() & GetLayerMask() )
			{
				glClear(GL_DEPTH_BUFFER_BIT);

				glLoadIdentity();
				Vector3 cPos = GetCamera()->GetPosition();
				Vector3 cTgt = GetCamera()->GetTargetPosition(); 

				if ( pLayer->IsBackground() )
				{
					Vector3 cDiff = cPos - cTgt;
					gluLookAt(cDiff.x, cDiff.y, cDiff.z, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
				}
				else
				{
					gluLookAt(cPos.x, cPos.y, cPos.z, cTgt.x, cTgt.y, cTgt.z, 0.0f, 1.0f, 0.0f);
				}

				pLayer->Render();
			}
		}

		for ( Layer* pLayerToDelete : mLayersToDelete )
		{
			for ( LayerList::iterator it = mLayerList.begin(), itEnd = mLayerList.end(); it != itEnd; )
			{
				if ( *it == pLayerToDelete )
				{
					delete *it;
					it = mLayerList.erase( it );
				}
				else
					it++;
			}
		}
		mLayersToDelete.clear();
	}
void PCB_LAYER_WIDGET::OnLayerVisible( LAYER_NUM aLayer, bool isVisible, bool isFinal )
{
    BOARD* brd = myframe->GetBoard();

    LAYER_MSK visibleLayers = brd->GetVisibleLayers();

    if( isVisible )
        visibleLayers |= GetLayerMask( aLayer );
    else
        visibleLayers &= ~GetLayerMask( aLayer );

    brd->SetVisibleLayers( visibleLayers );

    EDA_DRAW_PANEL_GAL* galCanvas = myframe->GetGalCanvas();
    if( galCanvas )
    {
        KIGFX::VIEW* view = galCanvas->GetView();
        view->SetLayerVisible( aLayer, isVisible );
    }

    if( isFinal )
        myframe->GetCanvas()->Refresh();
}
Esempio n. 11
0
void DIALOG_SVG_PRINT::initDialog()
{
    m_board = m_parent->GetBoard();

    if( m_config )
    {
        m_config->Read( PLOTSVGMODECOLOR_KEY, &m_printBW, false );
        long ltmp;
        m_config->Read( PLOTSVGPAGESIZEOPT_KEY, &ltmp, 0 );
        m_rbSvgPageSizeOpt->SetSelection( ltmp );
        m_config->Read( PLOTSVGPLOT_BRD_EDGE_KEY, &ltmp, 1 );
        m_PrintBoardEdgesCtrl->SetValue( ltmp );
    }

    m_outputDirectory = m_parent->GetPlotSettings().GetOutputDirectory();
    m_outputDirectoryName->SetValue( m_outputDirectory );

    if( m_printBW )
        m_ModeColorOption->SetSelection( 1 );
    else
        m_ModeColorOption->SetSelection( 0 );

    m_printMirrorOpt->SetValue( m_printMirror );
    m_rbFileOpt->SetSelection( m_oneFileOnly ? 1 : 0 );


    AddUnitSymbol( *m_TextPenWidth, g_UserUnit );
    m_DialogDefaultPenSize->SetValue(
        ReturnStringFromValue( g_UserUnit, g_DrawDefaultLineThickness ) );

    // Create layers list
    LAYER_NUM layer;
    for( layer = FIRST_LAYER; layer < NB_PCB_LAYERS; ++layer )
    {
        if( !m_board->IsLayerEnabled( layer ) )
            m_boxSelectLayer[layer] = NULL;
        else
            m_boxSelectLayer[layer] =
                new wxCheckBox( this, -1, m_board->GetLayerName( layer ) );
    }

    // Add wxCheckBoxes in layers lists dialog
    // List layers in same order than in setup layers dialog
    // (Front or Top to Back or Bottom)
    DECLARE_LAYERS_ORDER_LIST( layersOrder );

    for( LAYER_NUM layer_idx = FIRST_LAYER; layer_idx < NB_PCB_LAYERS; ++layer_idx )
    {
        layer = layersOrder[layer_idx];

        wxASSERT( layer < NB_PCB_LAYERS );

        if( m_boxSelectLayer[layer] == NULL )
            continue;

        LAYER_MSK mask = GetLayerMask( layer );

        if( mask & s_SelectedLayers )
            m_boxSelectLayer[layer]->SetValue( true );

        if( layer <= LAST_COPPER_LAYER )
            m_CopperLayersBoxSizer->Add(  m_boxSelectLayer[layer],
                                          0,
                                          wxGROW | wxALL,
                                          1 );
        else
            m_TechnicalBoxSizer->Add(  m_boxSelectLayer[layer],
                                       0,
                                       wxGROW | wxALL,
                                       1 );
    }

    if( m_config )
    {
        wxString layerKey;

        for( LAYER_NUM layer = FIRST_LAYER; layer < NB_PCB_LAYERS; ++layer )
        {
            bool option;

            if( m_boxSelectLayer[layer] == NULL )
                continue;

            layerKey.Printf( OPTKEY_LAYERBASE, layer );

            if( m_config->Read( layerKey, &option ) )
                m_boxSelectLayer[layer]->SetValue( option );
        }
    }
}
Esempio n. 12
0
void PCB_EDIT_FRAME::Block_SelectItems()
{
    int layerMask;

    GetScreen()->m_BlockLocate.Normalize();

    PICKED_ITEMS_LIST* itemsList = &GetScreen()->m_BlockLocate.m_ItemsSelection;
    ITEM_PICKER        picker( NULL, UR_UNSPECIFIED );

    // Add modules
    if( blockIncludeModules )
    {
        for( MODULE* module = m_Pcb->m_Modules; module != NULL; module = module->Next() )
        {
            int layer = module->GetLayer();

            if( module->HitTest( GetScreen()->m_BlockLocate )
                && ( !module->IsLocked() || blockIncludeLockedModules ) )
            {
                if( blockIncludeItemsOnInvisibleLayers || m_Pcb->IsModuleLayerVisible( layer ) )
                {
                    picker.SetItem ( module );
                    itemsList->PushItem( picker );
                }
            }
        }
    }

    // Add tracks and vias
    if( blockIncludeTracks )
    {
        for( TRACK* pt_segm = m_Pcb->m_Track; pt_segm != NULL; pt_segm = pt_segm->Next() )
        {
            if( pt_segm->HitTest( GetScreen()->m_BlockLocate ) )
            {
                if( blockIncludeItemsOnInvisibleLayers
                  || m_Pcb->IsLayerVisible( pt_segm->GetLayer() ) )
                {
                    picker.SetItem ( pt_segm );
                    itemsList->PushItem( picker );
                }
            }
        }
    }

    // Add graphic items
    layerMask = EDGE_LAYER;

    if( blockIncludeItemsOnTechLayers )
        layerMask = ALL_LAYERS;

    if( !blockIncludeBoardOutlineLayer )
        layerMask &= ~EDGE_LAYER;

    for( BOARD_ITEM* PtStruct = m_Pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() )
    {
        if( !m_Pcb->IsLayerVisible( PtStruct->GetLayer() ) && ! blockIncludeItemsOnInvisibleLayers)
            continue;
        bool select_me = false;
        switch( PtStruct->Type() )
        {
        case PCB_LINE_T:
            if( (GetLayerMask( PtStruct->GetLayer() ) & layerMask) == 0  )
                break;

            if( !PtStruct->HitTest( GetScreen()->m_BlockLocate ) )
                break;

            select_me = true; // This item is in bloc: select it
            break;

        case PCB_TEXT_T:
            if( !blockIncludePcbTexts )
                break;

            if( !PtStruct->HitTest( GetScreen()->m_BlockLocate ) )
                break;

            select_me = true; // This item is in bloc: select it
            break;

        case PCB_TARGET_T:
            if( ( GetLayerMask( PtStruct->GetLayer() ) & layerMask ) == 0  )
                break;

            if( !PtStruct->HitTest( GetScreen()->m_BlockLocate ) )
                break;

            select_me = true; // This item is in bloc: select it
            break;

        case PCB_DIMENSION_T:
            if( ( GetLayerMask( PtStruct->GetLayer() ) & layerMask ) == 0 )
                break;

            if( !PtStruct->HitTest( GetScreen()->m_BlockLocate ) )
                break;

            select_me = true; // This item is in bloc: select it
            break;

        default:
            break;
        }

        if( select_me )
        {
            picker.SetItem ( PtStruct );
            itemsList->PushItem( picker );
        }
    }

    // Add zones
    if( blockIncludeZones )
    {
        for( int ii = 0; ii < m_Pcb->GetAreaCount(); ii++ )
        {
            ZONE_CONTAINER* area = m_Pcb->GetArea( ii );

            if( area->HitTest( GetScreen()->m_BlockLocate ) )
            {
                if( blockIncludeItemsOnInvisibleLayers
                  || m_Pcb->IsLayerVisible( area->GetLayer() ) )
                {
                    BOARD_ITEM* zone_c = (BOARD_ITEM*) area;
                    picker.SetItem ( zone_c );
                    itemsList->PushItem( picker );
                }
            }
        }
    }
}
/**
 * Function CreateKeepOutRectangle
 * builds the cost map:
 * Cells ( in Dist map ) inside the rect x0,y0 a x1,y1 are
 *  incremented by value aKeepOut
 *  Cell outside this rectangle, but inside the rectangle
 *  x0,y0 -marge to x1,y1 + marge are incremented by a decreasing value
 *  (aKeepOut ... 0). The decreasing value depends on the distance to the first rectangle
 *  Therefore the cost is high in rect x0,y0 to x1,y1, and decrease outside this rectangle
 */
void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1,
                             int marge, int aKeepOut, int aLayerMask )
{
    int         row, col;
    int         row_min, row_max, col_min, col_max, pmarge;
    int         trace = 0;
    DIST_CELL   data, LocalKeepOut;
    int         lgain, cgain;

    if( aLayerMask & GetLayerMask( g_Route_Layer_BOTTOM ) )
        trace = 1; // Trace on bottom layer.

    if( ( aLayerMask & GetLayerMask( g_Route_Layer_TOP ) ) && RoutingMatrix.m_RoutingLayersCount )
        trace |= 2; // Trace on top layer.

    if( trace == 0 )
        return;

    ux0 -= RoutingMatrix.m_BrdBox.GetX();
    uy0 -= RoutingMatrix.m_BrdBox.GetY();
    ux1 -= RoutingMatrix.m_BrdBox.GetX();
    uy1 -= RoutingMatrix.m_BrdBox.GetY();

    ux0 -= marge;
    ux1 += marge;
    uy0 -= marge;
    uy1 += marge;

    pmarge = marge / RoutingMatrix.m_GridRouting;

    if( pmarge < 1 )
        pmarge = 1;

    // Calculate the coordinate limits of the rectangle.
    row_max = uy1 / RoutingMatrix.m_GridRouting;
    col_max = ux1 / RoutingMatrix.m_GridRouting;
    row_min = uy0 / RoutingMatrix.m_GridRouting;

    if( uy0 > row_min * RoutingMatrix.m_GridRouting )
        row_min++;

    col_min = ux0 / RoutingMatrix.m_GridRouting;

    if( ux0 > col_min * RoutingMatrix.m_GridRouting )
        col_min++;

    if( row_min < 0 )
        row_min = 0;

    if( row_max >= (RoutingMatrix.m_Nrows - 1) )
        row_max = RoutingMatrix.m_Nrows - 1;

    if( col_min < 0 )
        col_min = 0;

    if( col_max >= (RoutingMatrix.m_Ncols - 1) )
        col_max = RoutingMatrix.m_Ncols - 1;

    for( row = row_min; row <= row_max; row++ )
    {
        lgain = 256;

        if( row < pmarge )
            lgain = ( 256 * row ) / pmarge;
        else if( row > row_max - pmarge )
            lgain = ( 256 * ( row_max - row ) ) / pmarge;

        for( col = col_min; col <= col_max; col++ )
        {
            // RoutingMatrix Dist map containt the "cost" of the cell
            // at position (row, col)
            // in autoplace this is the cost of the cell, when
            // a footprint overlaps it, near a "master" footprint
            // this cost is hight near the "master" footprint
            // and decrease with the distance
            cgain = 256;
            LocalKeepOut = aKeepOut;

            if( col < pmarge )
                cgain = ( 256 * col ) / pmarge;
            else if( col > col_max - pmarge )
                cgain = ( 256 * ( col_max - col ) ) / pmarge;

            cgain = ( cgain * lgain ) / 256;

            if( cgain != 256 )
                LocalKeepOut = ( LocalKeepOut * cgain ) / 256;

            if( trace & 1 )
            {
                data = RoutingMatrix.GetDist( row, col, BOTTOM ) + LocalKeepOut;
                RoutingMatrix.SetDist( row, col, BOTTOM, data );
            }

            if( trace & 2 )
            {
                data    = RoutingMatrix.GetDist( row, col, TOP );
                data    = std::max( data, LocalKeepOut );
                RoutingMatrix.SetDist( row, col, TOP, data );
            }
        }
    }
}
Esempio n. 14
0
/**
 * Function PlaceCells
 * Initialize the matrix routing by setting obstacles for each occupied cell
 * a cell set to HOLE is an obstacle for tracks and vias
 * a cell set to VIA_IMPOSSIBLE is an obstacle for vias only.
 * a cell set to CELL_is_EDGE is a frontier.
 * Tracks and vias having the same net code as net_code are skipped
 * (htey do not are obstacles)
 *
 * For single-sided Routing 1:
 * BOTTOM side is used, and Route_Layer_BOTTOM = Route_Layer_TOP
 *
 * If flag == FORCE_PADS: all pads will be put in matrix as obstacles.
 */
void PlaceCells( BOARD* aPcb, int net_code, int flag )
{
    int       ux0 = 0, uy0 = 0, ux1, uy1, dx, dy;
    int       marge, via_marge;
    LAYER_MSK layerMask;

    // use the default NETCLASS?
    NETCLASS* nc = aPcb->m_NetClasses.GetDefault();

    int       trackWidth = nc->GetTrackWidth();
    int       clearance  = nc->GetClearance();
    int       viaSize    = nc->GetViaDiameter();

    marge     = clearance + (trackWidth / 2);
    via_marge = clearance + (viaSize / 2);

    // Place PADS on matrix routing:
    for( unsigned i = 0; i < aPcb->GetPadCount(); ++i )
    {
        D_PAD* pad = aPcb->GetPad( i );

        if( net_code != pad->GetNet() || (flag & FORCE_PADS) )
        {
            ::PlacePad( pad, HOLE, marge, WRITE_CELL );
        }

        ::PlacePad( pad, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
    }

    // Place outlines of modules on matrix routing, if they are on a copper layer
    // or on the edge layer
    TRACK tmpSegm( NULL );  // A dummy track used to create segments.

    for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
    {
        for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() )
        {
            switch( item->Type() )
            {
            case PCB_MODULE_EDGE_T:
            {
                EDGE_MODULE* edge = (EDGE_MODULE*) item;

                tmpSegm.SetLayer( edge->GetLayer() );

                if( tmpSegm.GetLayer() == EDGE_N )
                    tmpSegm.SetLayer( UNDEFINED_LAYER );

                tmpSegm.SetStart( edge->GetStart() );
                tmpSegm.SetEnd(   edge->GetEnd() );
                tmpSegm.SetShape( edge->GetShape() );
                tmpSegm.SetWidth( edge->GetWidth() );
                tmpSegm.m_Param = edge->GetAngle();
                tmpSegm.SetNet( -1 );

                TraceSegmentPcb( &tmpSegm, HOLE, marge, WRITE_CELL );
                TraceSegmentPcb( &tmpSegm, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
            }
            break;

            default:
                break;
            }
        }
    }

    // Place board outlines and texts on copper layers:
    for( BOARD_ITEM* item = aPcb->m_Drawings; item; item = item->Next() )
    {
        switch( item->Type() )
        {
        case PCB_LINE_T:
        {
            DRAWSEGMENT* DrawSegm;

            int          type_cell = HOLE;
            DrawSegm = (DRAWSEGMENT*) item;
            tmpSegm.SetLayer( DrawSegm->GetLayer() );

            if( DrawSegm->GetLayer() == EDGE_N )
            {
                tmpSegm.SetLayer( UNDEFINED_LAYER );
                type_cell |= CELL_is_EDGE;
            }

            tmpSegm.SetStart( DrawSegm->GetStart() );
            tmpSegm.SetEnd(   DrawSegm->GetEnd() );
            tmpSegm.SetShape( DrawSegm->GetShape() );
            tmpSegm.SetWidth( DrawSegm->GetWidth() );
            tmpSegm.m_Param = DrawSegm->GetAngle();
            tmpSegm.SetNet( -1 );

            TraceSegmentPcb( &tmpSegm, type_cell, marge, WRITE_CELL );
        }
        break;

        case PCB_TEXT_T:
        {
            TEXTE_PCB* PtText;
            PtText = (TEXTE_PCB*) item;

            if( PtText->GetText().Length() == 0 )
                break;

            EDA_RECT textbox = PtText->GetTextBox( -1 );
            ux0 = textbox.GetX();
            uy0 = textbox.GetY();
            dx  = textbox.GetWidth();
            dy  = textbox.GetHeight();

            /* Put bounding box (rectangle) on matrix */
            dx /= 2;
            dy /= 2;

            ux1 = ux0 + dx;
            uy1 = uy0 + dy;

            ux0 -= dx;
            uy0 -= dy;

            layerMask = GetLayerMask( PtText->GetLayer() );

            TraceFilledRectangle( ux0 - marge, uy0 - marge, ux1 + marge,
                                  uy1 + marge, PtText->GetOrientation(),
                                  layerMask, HOLE, WRITE_CELL );

            TraceFilledRectangle( ux0 - via_marge, uy0 - via_marge,
                                  ux1 + via_marge, uy1 + via_marge,
                                  PtText->GetOrientation(),
                                  layerMask, VIA_IMPOSSIBLE, WRITE_OR_CELL );
        }
        break;

        default:
            break;
        }
    }

    /* Put tracks and vias on matrix */
    for( TRACK* track = aPcb->m_Track; track; track = track->Next() )
    {
        if( net_code == track->GetNet() )
            continue;

        TraceSegmentPcb( track, HOLE, marge, WRITE_CELL );
        TraceSegmentPcb( track, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
    }
}
TRACK* TRACK::GetTrack( TRACK* aStartTrace, TRACK* aEndTrace, ENDPOINT_T aEndPoint,
        bool aSameNetOnly, bool aSequential )
{
    const wxPoint &position = GetEndPoint( aEndPoint );
    LAYER_MSK refLayers = GetLayerMask();
    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->GetLayerMask()) )
            {
                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->GetLayerMask()) )
            {
                if( (position == previousSegment->m_Start) ||
                    (position == previousSegment->m_End) )
                    return previousSegment;
            }

            if( previousSegment == aStartTrace )
                previousSegment = NULL;
            else
                previousSegment = previousSegment->Back();
        }
    }

    return NULL;
}
void PCB_LAYER_WIDGET::ReFill()
{
    BOARD*  brd = myframe->GetBoard();
    int     enabledLayers = brd->GetEnabledLayers();

    ClearLayerRows();

    // show all coppers first, with front on top, back on bottom, then technical layers
    for( LAYER_NUM layer = LAYER_N_FRONT; layer >= FIRST_LAYER; --layer )
    {
        if( enabledLayers & GetLayerMask( layer ) )
        {
            wxString dsc;
            switch( layer )
            {
            case LAYER_N_FRONT:
                dsc = _("Front copper layer");
                break;

            case LAYER_N_BACK:
                dsc = _("Back copper layer");
                break;

            default:
                dsc = _("Inner copper layer");
                break;
            }

            AppendLayerRow( LAYER_WIDGET::ROW(
                brd->GetLayerName( layer ), layer, brd->GetLayerColor( layer ),
                dsc, true ) );
        }
    }


    // technical layers are shown in this order:
    // Because they are static, wxGetTranslation must be explicitely
    // called for tooltips.
    static const struct {
        LAYER_NUM   layerId;
        wxString    tooltip;
    } techLayerSeq[] = {
        { ADHESIVE_N_FRONT,     _( "Adhesive on board's front" )    },
        { ADHESIVE_N_BACK,      _( "Adhesive on board's back" )     },
        { SOLDERPASTE_N_FRONT,  _( "Solder paste on board's front" )},
        { SOLDERPASTE_N_BACK,   _( "Solder paste on board's back" ) },
        { SILKSCREEN_N_FRONT,   _( "Silkscreen on board's front" )  },
        { SILKSCREEN_N_BACK,    _( "Silkscreen on board's back" )   },
        { SOLDERMASK_N_FRONT,   _( "Solder mask on board's front" ) },
        { SOLDERMASK_N_BACK,    _( "Solder mask on board's back" )  },
        { DRAW_N,               _( "Explanatory drawings" )         },
        { COMMENT_N,            _( "Explanatory comments" )         },
        { ECO1_N,               _( "User defined meaning" )         },
        { ECO2_N,               _( "User defined meaning" )         },
        { EDGE_N,               _( "Board's perimeter definition" ) },
    };

    for( unsigned i=0;  i<DIM(techLayerSeq);  ++i )
    {
        LAYER_NUM layer = techLayerSeq[i].layerId;

        if( !(enabledLayers & GetLayerMask( layer )) )
            continue;

        AppendLayerRow( LAYER_WIDGET::ROW(
            brd->GetLayerName( layer ), layer, brd->GetLayerColor( layer ),
            wxGetTranslation( techLayerSeq[i].tooltip ), true ) );
    }

    installRightLayerClickHandler();
}
Esempio n. 17
0
/* Route a trace on the BOARD.
 * Parameters:
 * 1 side / 2 sides (0 / 1)
 * Coord source (row, col)
 * Coord destination (row, col)
 * Net_code
 * Pointer to the ratsnest reference
 *
 * Returns:
 * SUCCESS if routed
 * TRIVIAL_SUCCESS if pads are connected by overlay (no track needed)
 * If failure NOSUCCESS
 * Escape STOP_FROM_ESC if demand
 * ERR_MEMORY if memory allocation failed.
 */
static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe,
                                wxDC*           DC,
                                int             two_sides,
                                int             row_source,
                                int             col_source,
                                int             row_target,
                                int             col_target,
                                RATSNEST_ITEM*  pt_rat )
{
    int          r, c, side, d, apx_dist, nr, nc;
    int          result, skip;
    int          i;
    long         curcell, newcell, buddy, lastopen, lastclos, lastmove;
    int          newdist, olddir, _self;
    int          current_net_code;
    int          marge;
    int          padLayerMaskStart;    /* Mask layers belonging to the starting pad. */
    int          padLayerMaskEnd;      /* Mask layers belonging to the ending pad. */
    int          topLayerMask = GetLayerMask( g_Route_Layer_TOP );
    int          bottomLayerMask = GetLayerMask( g_Route_Layer_BOTTOM );
    int          routeLayerMask;       /* Mask two layers for routing. */
    int          tab_mask[2];       /* Enables the calculation of the mask layer being
                                     * tested. (side = TOP or BOTTOM) */
    int          start_mask_layer = 0;
    wxString     msg;

    wxBusyCursor dummy_cursor;      // Set an hourglass cursor while routing a
                                    // track

    result = NOSUCCESS;

    marge = s_Clearance + ( pcbframe->GetDesignSettings().GetCurrentTrackWidth() / 2 );

    /* clear direction flags */
    i = RoutingMatrix.m_Nrows * RoutingMatrix.m_Ncols * sizeof(DIR_CELL);

    if( two_sides )
        memset( RoutingMatrix.m_DirSide[TOP], FROM_NOWHERE, i );
    memset( RoutingMatrix.m_DirSide[BOTTOM], FROM_NOWHERE, i );

    lastopen = lastclos = lastmove = 0;

    /* Set tab_masque[side] for final test of routing. */
    if( two_sides )
        tab_mask[TOP]    = topLayerMask;
    tab_mask[BOTTOM] = bottomLayerMask;

    /* Set active layers mask. */
    routeLayerMask = topLayerMask | bottomLayerMask;

    pt_cur_ch = pt_rat;

    current_net_code  = pt_rat->GetNet();
    padLayerMaskStart = pt_cur_ch->m_PadStart->GetLayerMask();

    padLayerMaskEnd = pt_cur_ch->m_PadEnd->GetLayerMask();


    /* First Test if routing possible ie if the pads are accessible
     * on the routing layers.
     */
    if( ( routeLayerMask & padLayerMaskStart ) == 0 )
        goto end_of_route;

    if( ( routeLayerMask & padLayerMaskEnd ) == 0 )
        goto end_of_route;

    /* Then test if routing possible ie if the pads are accessible
     * On the routing grid (1 grid point must be in the pad)
     */
    {
        int cX = ( RoutingMatrix.m_GridRouting * col_source )
                 + pcbframe->GetBoard()->GetBoundingBox().GetX();
        int cY = ( RoutingMatrix.m_GridRouting * row_source )
                 + pcbframe->GetBoard()->GetBoundingBox().GetY();
        int dx = pt_cur_ch->m_PadStart->GetSize().x / 2;
        int dy = pt_cur_ch->m_PadStart->GetSize().y / 2;
        int px = pt_cur_ch->m_PadStart->GetPosition().x;
        int py = pt_cur_ch->m_PadStart->GetPosition().y;

        if( ( ( int( pt_cur_ch->m_PadStart->GetOrientation() ) / 900 ) & 1 ) != 0 )
            EXCHG( dx, dy );

        if( ( abs( cX - px ) > dx ) || ( abs( cY - py ) > dy ) )
            goto end_of_route;

        cX = ( RoutingMatrix.m_GridRouting * col_target )
             + pcbframe->GetBoard()->GetBoundingBox().GetX();
        cY = ( RoutingMatrix.m_GridRouting * row_target )
             + pcbframe->GetBoard()->GetBoundingBox().GetY();
        dx = pt_cur_ch->m_PadEnd->GetSize().x / 2;
        dy = pt_cur_ch->m_PadEnd->GetSize().y / 2;
        px = pt_cur_ch->m_PadEnd->GetPosition().x;
        py = pt_cur_ch->m_PadEnd->GetPosition().y;

        if( ( ( int( pt_cur_ch->m_PadEnd->GetOrientation() ) / 900) & 1 ) != 0 )
            EXCHG( dx, dy );

        if( ( abs( cX - px ) > dx ) || ( abs( cY - py ) > dy ) )
            goto end_of_route;
    }

    /* Test the trivial case: direct connection overlay pads. */
    if( ( row_source == row_target ) && ( col_source == col_target )
       && ( padLayerMaskEnd & padLayerMaskStart &
            g_TabAllCopperLayerMask[pcbframe->GetBoard()->GetCopperLayerCount() - 1] ) )
    {
        result = TRIVIAL_SUCCESS;
        goto end_of_route;
    }

    /* Placing the bit to remove obstacles on 2 pads to a link. */
    pcbframe->SetStatusText( wxT( "Gen Cells" ) );

    PlacePad( pt_cur_ch->m_PadStart, CURRENT_PAD, marge, WRITE_OR_CELL );
    PlacePad( pt_cur_ch->m_PadEnd, CURRENT_PAD, marge, WRITE_OR_CELL );

    /* Regenerates the remaining barriers (which may encroach on the placement bits precedent)
     */
    i = pcbframe->GetBoard()->GetPadCount();

    for( unsigned ii = 0; ii < pcbframe->GetBoard()->GetPadCount(); ii++ )
    {
        D_PAD* ptr = pcbframe->GetBoard()->GetPad( ii );

        if( ( pt_cur_ch->m_PadStart != ptr ) && ( pt_cur_ch->m_PadEnd != ptr ) )
        {
            PlacePad( ptr, ~CURRENT_PAD, marge, WRITE_AND_CELL );
        }
    }

    InitQueue(); /* initialize the search queue */
    apx_dist = RoutingMatrix.GetApxDist( row_source, col_source, row_target, col_target );

    /* Initialize first search. */
    if( two_sides )   /* Preferred orientation. */
    {
        if( abs( row_target - row_source ) > abs( col_target - col_source ) )
        {
            if( padLayerMaskStart & topLayerMask )
            {
                start_mask_layer = 2;

                if( SetQueue( row_source, col_source, TOP, 0, apx_dist,
                              row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }

            if( padLayerMaskStart & bottomLayerMask )
            {
                start_mask_layer |= 1;

                if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist,
                              row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }
        }
        else
        {
            if( padLayerMaskStart & bottomLayerMask )
            {
                start_mask_layer = 1;

                if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist,
                              row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }

            if( padLayerMaskStart & topLayerMask )
            {
                start_mask_layer |= 2;

                if( SetQueue( row_source, col_source, TOP, 0, apx_dist,
                              row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }
        }
    }
    else if( padLayerMaskStart & bottomLayerMask )
    {
        start_mask_layer = 1;

        if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist, row_target, col_target ) == 0 )
        {
            return ERR_MEMORY;
        }
    }

    /* search until success or we exhaust all possibilities */
    GetQueue( &r, &c, &side, &d, &apx_dist );

    for( ; r != ILLEGAL; GetQueue( &r, &c, &side, &d, &apx_dist ) )
    {
        curcell = RoutingMatrix.GetCell( r, c, side );

        if( curcell & CURRENT_PAD )
            curcell &= ~HOLE;

        if( (r == row_target) && (c == col_target)  /* success if layer OK */
           && ( tab_mask[side] & padLayerMaskEnd) )
        {
            /* Remove link. */
            GRSetDrawMode( DC, GR_XOR );
            GRLine( pcbframe->GetCanvas()->GetClipBox(),
                    DC,
                    segm_oX,
                    segm_oY,
                    segm_fX,
                    segm_fY,
                    0,
                    WHITE );

            /* Generate trace. */
            if( Retrace( pcbframe, DC, row_source, col_source,
                         row_target, col_target, side, current_net_code ) )
            {
                result = SUCCESS;   /* Success : Route OK */
            }

            break;                  /* Routing complete. */
        }

        if( pcbframe->GetCanvas()->GetAbortRequest() )
        {
            result = STOP_FROM_ESC;
            break;
        }

        /* report every COUNT new nodes or so */
        #define COUNT 20000

        if( ( OpenNodes - lastopen > COUNT )
           || ( ClosNodes - lastclos > COUNT )
           || ( MoveNodes - lastmove > COUNT ) )
        {
            lastopen = OpenNodes;
            lastclos = ClosNodes;
            lastmove = MoveNodes;
            msg.Printf( wxT( "Activity: Open %d   Closed %d   Moved %d" ),
                        OpenNodes, ClosNodes, MoveNodes );
            pcbframe->SetStatusText( msg );
        }

        _self = 0;

        if( curcell & HOLE )
        {
            _self = 5;

            /* set 'present' bits */
            for( i = 0; i < 8; i++ )
            {
                selfok2[i].present = 0;

                if( curcell & selfok2[i].trace )
                    selfok2[i].present = 1;
            }
        }

        for( i = 0; i < 8; i++ ) /* consider neighbors */
        {
            nr = r + delta[i][0];
            nc = c + delta[i][1];

            /* off the edge? */
            if( nr < 0 || nr >= RoutingMatrix.m_Nrows ||
                nc < 0 || nc >= RoutingMatrix.m_Ncols )
                continue;  /* off the edge */

            if( _self == 5 && selfok2[i].present )
                continue;

            newcell = RoutingMatrix.GetCell( nr, nc, side );

            if( newcell & CURRENT_PAD )
                newcell &= ~HOLE;

            /* check for non-target hole */
            if( newcell & HOLE )
            {
                if( nr != row_target || nc != col_target )
                    continue;
            }
            /* check for traces */
            else if( newcell & HOLE & ~(newmask[i]) )
            {
                continue;
            }

            /* check blocking on corner neighbors */
            if( delta[i][0] && delta[i][1] )
            {
                /* check first buddy */
                buddy = RoutingMatrix.GetCell( r + blocking[i].r1, c + blocking[i].c1, side );

                if( buddy & CURRENT_PAD )
                    buddy &= ~HOLE;

                if( buddy & HOLE )
                    continue;

//              if (buddy & (blocking[i].b1)) continue;
                /* check second buddy */
                buddy = RoutingMatrix.GetCell( r + blocking[i].r2, c + blocking[i].c2, side );

                if( buddy & CURRENT_PAD )
                    buddy &= ~HOLE;

                if( buddy & HOLE )
                    continue;

//              if (buddy & (blocking[i].b2)) continue;
            }

            olddir  = RoutingMatrix.GetDir( r, c, side );
            newdist = d + RoutingMatrix.CalcDist( ndir[i], olddir,
                                    ( olddir == FROM_OTHERSIDE ) ?
                                    RoutingMatrix.GetDir( r, c, 1 - side ) : 0, side );

            /* if (a) not visited yet, or (b) we have */
            /* found a better path, add it to queue */
            if( !RoutingMatrix.GetDir( nr, nc, side ) )
            {
                RoutingMatrix.SetDir( nr, nc, side, ndir[i] );
                RoutingMatrix.SetDist( nr, nc, side, newdist );

                if( SetQueue( nr, nc, side, newdist,
                              RoutingMatrix.GetApxDist( nr, nc, row_target, col_target ),
                              row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }
            else if( newdist < RoutingMatrix.GetDist( nr, nc, side ) )
            {
                RoutingMatrix.SetDir( nr, nc, side, ndir[i] );
                RoutingMatrix.SetDist( nr, nc, side, newdist );
                ReSetQueue( nr, nc, side, newdist,
                            RoutingMatrix.GetApxDist( nr, nc, row_target, col_target ),
                            row_target, col_target );
            }
        }

        /** Test the other layer. **/
        if( two_sides )
        {
            olddir = RoutingMatrix.GetDir( r, c, side );

            if( olddir == FROM_OTHERSIDE )
                continue;   /* useless move, so don't bother */

            if( curcell )   /* can't drill via if anything here */
                continue;

            /* check for holes or traces on other side */
            if( ( newcell = RoutingMatrix.GetCell( r, c, 1 - side ) ) != 0 )
                continue;

            /* check for nearby holes or traces on both sides */
            for( skip = 0, i = 0; i < 8; i++ )
            {
                nr = r + delta[i][0]; nc = c + delta[i][1];

                if( nr < 0 || nr >= RoutingMatrix.m_Nrows ||
                    nc < 0 || nc >= RoutingMatrix.m_Ncols )
                    continue;  /* off the edge !! */

                if( RoutingMatrix.GetCell( nr, nc, side ) /* & blocking2[i]*/ )
                {
                    skip = 1; /* can't drill via here */
                    break;
                }

                if( RoutingMatrix.GetCell( nr, nc, 1 - side ) /* & blocking2[i]*/ )
                {
                    skip = 1; /* can't drill via here */
                    break;
                }
            }

            if( skip )      /* neighboring hole or trace? */
                continue;   /* yes, can't drill via here */

            newdist = d + RoutingMatrix.CalcDist( FROM_OTHERSIDE, olddir, 0, side );

            /*  if (a) not visited yet,
             *  or (b) we have found a better path,
             *  add it to queue */
            if( !RoutingMatrix.GetDir( r, c, 1 - side ) )
            {
                RoutingMatrix.SetDir( r, c, 1 - side, FROM_OTHERSIDE );
                RoutingMatrix.SetDist( r, c, 1 - side, newdist );

                if( SetQueue( r, c, 1 - side, newdist, apx_dist, row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }
            else if( newdist < RoutingMatrix.GetDist( r, c, 1 - side ) )
            {
                RoutingMatrix.SetDir( r, c, 1 - side, FROM_OTHERSIDE );
                RoutingMatrix.SetDist( r, c, 1 - side, newdist );
                ReSetQueue( r, c,
                            1 - side,
                            newdist,
                            apx_dist,
                            row_target,
                            col_target );
            }
        }     /* Finished attempt to route on other layer. */
    }

end_of_route:
    PlacePad( pt_cur_ch->m_PadStart, ~CURRENT_PAD, marge, WRITE_AND_CELL );
    PlacePad( pt_cur_ch->m_PadEnd, ~CURRENT_PAD, marge, WRITE_AND_CELL );

    msg.Printf( wxT( "Activity: Open %d   Closed %d   Moved %d"),
                OpenNodes, ClosNodes, MoveNodes );
    pcbframe->SetStatusText( msg );

    return result;
}
Esempio n. 18
0
MODULE* PCB_EDIT_FRAME::Genere_Self( wxDC* DC )
{
    D_PAD*   pad;
    int      ll;
    wxString msg;

    m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
    m_canvas->SetMouseCapture( NULL, NULL );

    if( Self_On == 0 )
    {
        DisplayError( this, wxT( "Starting point not init.." ) );
        return NULL;
    }

    Self_On = 0;

    Mself.m_End = GetCrossHairPosition();

    wxPoint pt = Mself.m_End - Mself.m_Start;
    int     min_len = KiROUND( EuclideanNorm( pt ) );
    Mself.lng = min_len;

    // Enter the desired length.
    msg = StringFromValue( g_UserUnit, Mself.lng );
    wxTextEntryDialog dlg( this, _( "Length:" ), _( "Length" ), msg );

    if( dlg.ShowModal() != wxID_OK )
        return NULL; // canceled by user

    msg = dlg.GetValue();
    Mself.lng = ValueFromString( g_UserUnit, msg );

    // Control values (ii = minimum length)
    if( Mself.lng < min_len )
    {
        DisplayError( this, _( "Requested length < minimum length" ) );
        return NULL;
    }

    // Calculate the elements.
    Mself.m_Width = GetBoard()->GetCurrentTrackWidth();

    std::vector <wxPoint> buffer;
    ll = BuildCornersList_S_Shape( buffer, Mself.m_Start, Mself.m_End, Mself.lng, Mself.m_Width );

    if( !ll )
    {
        DisplayError( this, _( "Requested length too large" ) );
        return NULL;
    }

    // Generate module.
    MODULE* module;
    module = Create_1_Module( wxEmptyString );

    if( module == NULL )
        return NULL;

    // here the module is already in the BOARD, Create_1_Module() does that.
    module->SetFPID( FPID( std::string( "MuSelf" ) ) );
    module->SetAttributes( MOD_VIRTUAL | MOD_CMS );
    module->ClearFlags();
    module->SetPosition( Mself.m_End );

    // Generate segments
    for( unsigned jj = 1; jj < buffer.size(); jj++ )
    {
        EDGE_MODULE* PtSegm;
        PtSegm = new EDGE_MODULE( module );
        PtSegm->SetStart( buffer[jj - 1] );
        PtSegm->SetEnd( buffer[jj] );
        PtSegm->SetWidth( Mself.m_Width );
        PtSegm->SetLayer( module->GetLayer() );
        PtSegm->SetShape( S_SEGMENT );
        PtSegm->SetStart0( PtSegm->GetStart() - module->GetPosition() );
        PtSegm->SetEnd0(   PtSegm->GetEnd()   - module->GetPosition() );
        module->GraphicalItems().PushBack( PtSegm );
    }

    // Place a pad on each end of coil.
    pad = new D_PAD( module );

    module->Pads().PushFront( pad );

    pad->SetPadName( wxT( "1" ) );
    pad->SetPosition( Mself.m_End );
    pad->SetPos0( pad->GetPosition() - module->GetPosition() );

    pad->SetSize( wxSize( Mself.m_Width, Mself.m_Width ) );

    pad->SetLayerMask( GetLayerMask( module->GetLayer() ) );
    pad->SetAttribute( PAD_SMD );
    pad->SetShape( PAD_CIRCLE );

    D_PAD* newpad = new D_PAD( *pad );

    module->Pads().Insert( newpad, pad->Next() );

    pad = newpad;
    pad->SetPadName( wxT( "2" ) );
    pad->SetPosition( Mself.m_Start );
    pad->SetPos0( pad->GetPosition() - module->GetPosition() );

    // Modify text positions.
    SetMsgPanel( module );

    wxPoint refPos( ( Mself.m_Start.x + Mself.m_End.x ) / 2,
                    ( Mself.m_Start.y + Mself.m_End.y ) / 2 );

    wxPoint valPos = refPos;

    refPos.y -= module->Reference().GetSize().y;
    module->Reference().SetTextPosition( refPos );
    valPos.y += module->Value().GetSize().y;
    module->Value().SetTextPosition( valPos );
    module->Reference().SetPos0( module->Reference().GetTextPosition() - module->GetPosition() );
    module->Value().SetPos0( module->Value().GetTextPosition() - module->GetPosition() );

    module->CalculateBoundingBox();
    module->Draw( m_canvas, DC, GR_OR );

    return module;
}
void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, LAYER_NUM aLayer,
                     const PCB_PLOT_PARAMS& aPlotOpt )
{
    PCB_PLOT_PARAMS plotOpt = aPlotOpt;
    int soldermask_min_thickness = aBoard->GetDesignSettings().m_SolderMaskMinWidth;

    // Set a default color and the text mode for this layer
    aPlotter->SetColor( aPlotOpt.GetColor() );
    aPlotter->SetTextMode( aPlotOpt.GetTextMode() );

    // Specify that the contents of the "Edges Pcb" layer are to be plotted
    // in addition to the contents of the currently specified layer.
    LAYER_MSK layer_mask = GetLayerMask( aLayer );

    if( !aPlotOpt.GetExcludeEdgeLayer() )
        layer_mask |= EDGE_LAYER;

    switch( aLayer )
    {
    case FIRST_COPPER_LAYER:
    case LAYER_N_2:
    case LAYER_N_3:
    case LAYER_N_4:
    case LAYER_N_5:
    case LAYER_N_6:
    case LAYER_N_7:
    case LAYER_N_8:
    case LAYER_N_9:
    case LAYER_N_10:
    case LAYER_N_11:
    case LAYER_N_12:
    case LAYER_N_13:
    case LAYER_N_14:
    case LAYER_N_15:
    case LAST_COPPER_LAYER:
        // Skip NPTH pads on copper layers ( only if hole size == pad size ):
        plotOpt.SetSkipPlotNPTH_Pads( true );
        // Drill mark will be plotted,
        // if drill mark is SMALL_DRILL_SHAPE  or FULL_DRILL_SHAPE
        PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
        break;

    case SOLDERMASK_N_BACK:
    case SOLDERMASK_N_FRONT:
        plotOpt.SetSkipPlotNPTH_Pads( false );
        // Disable plot pad holes
        plotOpt.SetDrillMarksType( PCB_PLOT_PARAMS::NO_DRILL_SHAPE );

        // Plot solder mask:
        if( soldermask_min_thickness == 0 )
            PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
        else
            PlotSolderMaskLayer( aBoard, aPlotter, layer_mask, plotOpt,
                                 soldermask_min_thickness );

        break;

    case SOLDERPASTE_N_BACK:
    case SOLDERPASTE_N_FRONT:
        plotOpt.SetSkipPlotNPTH_Pads( false );
        // Disable plot pad holes
        plotOpt.SetDrillMarksType( PCB_PLOT_PARAMS::NO_DRILL_SHAPE );
        PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
        break;

    case SILKSCREEN_N_FRONT:
    case SILKSCREEN_N_BACK:
        PlotSilkScreen( aBoard, aPlotter, layer_mask, plotOpt );

        // Gerber: Subtract soldermask from silkscreen if enabled
        if( aPlotter->GetPlotterType() == PLOT_FORMAT_GERBER
            && plotOpt.GetSubtractMaskFromSilk() )
        {
            if( aLayer == SILKSCREEN_N_FRONT )
                layer_mask = GetLayerMask( SOLDERMASK_N_FRONT );
            else
                layer_mask = GetLayerMask( SOLDERMASK_N_BACK );

            // Create the mask to subtract by creating a negative layer polarity
            aPlotter->SetLayerPolarity( false );
            // Disable plot pad holes
            plotOpt.SetDrillMarksType( PCB_PLOT_PARAMS::NO_DRILL_SHAPE );
            // Plot the mask
            PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
        }
        break;

    default:
        PlotSilkScreen( aBoard, aPlotter, layer_mask, plotOpt );
        break;
    }
}
/* Creates the plot for silkscreen layers
 * Silkscreen layers have specific requirement for pads (not filled) and texts
 * (with option to remove them from some copper areas (pads...)
 */
void PlotSilkScreen( BOARD *aBoard, PLOTTER* aPlotter, LAYER_MSK aLayerMask,
                     const PCB_PLOT_PARAMS& aPlotOpt )
{
    BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
    itemplotter.SetLayerMask( aLayerMask );

    // Plot edge layer and graphic items
    itemplotter.PlotBoardGraphicItems();

    // Plot footprint outlines :
    itemplotter.Plot_Edges_Modules();

    // Plot pads (creates pads outlines, for pads on silkscreen layers)
    int layersmask_plotpads = aLayerMask;
    // Calculate the mask layers of allowed layers for pads

    if( !aPlotOpt.GetPlotPadsOnSilkLayer() )       // Do not plot pads on silk screen layers
        layersmask_plotpads &= ~(SILKSCREEN_LAYER_BACK | SILKSCREEN_LAYER_FRONT );

    if( layersmask_plotpads )
    {
        for( MODULE* Module = aBoard->m_Modules; Module; Module = Module->Next() )
        {
            for( D_PAD * pad = Module->Pads(); pad != NULL; pad = pad->Next() )
            {
                // See if the pad is on this layer
                LAYER_MSK masklayer = pad->GetLayerMask();
                if( (masklayer & layersmask_plotpads) == 0 )
                    continue;

                EDA_COLOR_T color = ColorFromInt(0);
                if( (layersmask_plotpads & SILKSCREEN_LAYER_BACK) )
                   color = aBoard->GetLayerColor( SILKSCREEN_N_BACK );

                if((layersmask_plotpads & SILKSCREEN_LAYER_FRONT ) )
                    color = ColorFromInt( color | aBoard->GetLayerColor( SILKSCREEN_N_FRONT ) );

                itemplotter.PlotPad( pad, color, LINE );
            }
        }
    }

    // Plot footprints fields (ref, value ...)
    for( MODULE* module = aBoard->m_Modules;  module;  module = module->Next() )
    {
        if( ! itemplotter.PlotAllTextsModule( module ) )
        {
             wxLogMessage( _( "Your BOARD has a bad layer number for module %s" ),
                           GetChars( module->GetReference() ) );
        }
    }

    // Plot filled areas
    for( int ii = 0; ii < aBoard->GetAreaCount(); ii++ )
    {
        ZONE_CONTAINER* edge_zone = aBoard->GetArea( ii );

        if( ( GetLayerMask( edge_zone->GetLayer() ) & aLayerMask ) == 0 )
            continue;

        itemplotter.PlotFilledAreas( edge_zone );
    }

    // Plot segments used to fill zone areas (outdated, but here for old boards
    // compatibility):
    for( SEGZONE* seg = aBoard->m_Zone; seg != NULL; seg = seg->Next() )
    {
        if( ( GetLayerMask( seg->GetLayer() ) & aLayerMask ) == 0 )
            continue;

        aPlotter->ThickSegment( seg->GetStart(), seg->GetEnd(), seg->GetWidth(),
                                itemplotter.GetMode() );
    }
}
/* Plot a copper layer or mask.
 * Silk screen layers are not plotted here.
 */
void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter,
                        LAYER_MSK aLayerMask, const PCB_PLOT_PARAMS& aPlotOpt )
{

    BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
    itemplotter.SetLayerMask( aLayerMask );

    EDA_DRAW_MODE_T plotMode = aPlotOpt.GetMode();

     // Plot edge layer and graphic items
    itemplotter.PlotBoardGraphicItems();

    // Draw footprint shapes without pads (pads will plotted later)
    // We plot here module texts, but they are usually on silkscreen layer,
    // so they are not plot here but plot by PlotSilkScreen()
    // Plot footprints fields (ref, value ...)
    for( MODULE* module = aBoard->m_Modules;  module;  module = module->Next() )
    {
        if( ! itemplotter.PlotAllTextsModule( module ) )
        {
            wxLogMessage( _( "Your BOARD has a bad layer number for module %s" ),
                           GetChars( module->GetReference() ) );
        }
    }

    for( MODULE* module = aBoard->m_Modules;  module;  module = module->Next() )
    {
        for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() )
        {
            if( ! (aLayerMask & GetLayerMask( item->GetLayer() ) ) )
                continue;

            switch( item->Type() )
            {
            case PCB_MODULE_EDGE_T:
                itemplotter.Plot_1_EdgeModule( (EDGE_MODULE*) item );
                break;

            default:
                break;
            }
        }
    }

    // Plot footprint pads
    for( MODULE* module = aBoard->m_Modules;  module;  module = module->Next() )
    {
        for( D_PAD* pad = module->Pads();  pad;  pad = pad->Next() )
        {
            if( (pad->GetLayerMask() & aLayerMask) == 0 )
                continue;

            wxSize margin;
            double width_adj = 0;

            if( aLayerMask & ALL_CU_LAYERS )
                width_adj =  itemplotter.getFineWidthAdj();

            switch( aLayerMask &
                   ( SOLDERMASK_LAYER_BACK | SOLDERMASK_LAYER_FRONT |
                     SOLDERPASTE_LAYER_BACK | SOLDERPASTE_LAYER_FRONT ) )
            {
            case SOLDERMASK_LAYER_FRONT:
            case SOLDERMASK_LAYER_BACK:
                margin.x = margin.y = pad->GetSolderMaskMargin();
                break;

            case SOLDERPASTE_LAYER_FRONT:
            case SOLDERPASTE_LAYER_BACK:
                margin = pad->GetSolderPasteMargin();
                break;

            default:
                break;
            }

            wxSize padPlotsSize;
            padPlotsSize.x = pad->GetSize().x + ( 2 * margin.x ) + width_adj;
            padPlotsSize.y = pad->GetSize().y + ( 2 * margin.y ) + width_adj;

            // Don't draw a null size item :
            if( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 )
                continue;

            EDA_COLOR_T color = BLACK;

            if( (pad->GetLayerMask() & LAYER_BACK) )
               color = aBoard->GetVisibleElementColor( PAD_BK_VISIBLE );

            if((pad->GetLayerMask() & LAYER_FRONT ) )
                color = ColorFromInt( color | aBoard->GetVisibleElementColor( PAD_FR_VISIBLE ) );

            // Temporary set the pad size to the required plot size:
            wxSize tmppadsize = pad->GetSize();
            pad->SetSize( padPlotsSize );
            switch( pad->GetShape() )
            {
            case PAD_CIRCLE:
            case PAD_OVAL:
                if( aPlotOpt.GetSkipPlotNPTH_Pads() &&
                    (pad->GetSize() == pad->GetDrillSize()) &&
                    (pad->GetAttribute() == PAD_HOLE_NOT_PLATED) )
                    break;

                // Fall through:
            case PAD_TRAPEZOID:
            case PAD_RECT:
            default:
                itemplotter.PlotPad( pad, color, plotMode );
                break;
            }

            pad->SetSize( tmppadsize );     // Restore the pad size
        }
    }

    // Plot vias on copper layers, and if aPlotOpt.GetPlotViaOnMaskLayer() is true,
    // plot them on solder mask
    for( TRACK* track = aBoard->m_Track; track; track = track->Next() )
    {
        const VIA* Via = dynamic_cast<const VIA*>( track );

        if( !Via )
            continue;

        // vias are not plotted if not on selected layer, but if layer
        // is SOLDERMASK_LAYER_BACK or SOLDERMASK_LAYER_FRONT,vias are drawn,
        // only if they are on the corresponding external copper layer
        int via_mask_layer = Via->GetLayerMask();

        if( aPlotOpt.GetPlotViaOnMaskLayer() )
        {
            if( via_mask_layer & LAYER_BACK )
                via_mask_layer |= SOLDERMASK_LAYER_BACK;

            if( via_mask_layer & LAYER_FRONT )
                via_mask_layer |= SOLDERMASK_LAYER_FRONT;
        }

        if( ( via_mask_layer & aLayerMask ) == 0 )
            continue;

        int via_margin = 0;
        double width_adj = 0;

        // If the current layer is a solder mask, use the global mask
        // clearance for vias
        if( ( aLayerMask & ( SOLDERMASK_LAYER_BACK | SOLDERMASK_LAYER_FRONT ) ) )
            via_margin = aBoard->GetDesignSettings().m_SolderMaskMargin;

        if( aLayerMask & ALL_CU_LAYERS )
            width_adj = itemplotter.getFineWidthAdj();

        int diameter = Via->GetWidth() + 2 * via_margin + width_adj;

        // Don't draw a null size item :
        if( diameter <= 0 )
            continue;

        EDA_COLOR_T color = aBoard->GetVisibleElementColor(VIAS_VISIBLE + Via->GetViaType());
        // Set plot color (change WHITE to LIGHTGRAY because
        // the white items are not seen on a white paper or screen
        aPlotter->SetColor( color != WHITE ? color : LIGHTGRAY);
        aPlotter->FlashPadCircle( Via->GetStart(), diameter, plotMode );
    }

    // Plot tracks (not vias) :
    for( TRACK* track = aBoard->m_Track; track; track = track->Next() )
    {
        if( track->Type() == PCB_VIA_T )
            continue;

        if( (GetLayerMask( track->GetLayer() ) & aLayerMask) == 0 )
            continue;

        int width = track->GetWidth() + itemplotter.getFineWidthAdj();
        aPlotter->SetColor( itemplotter.getColor( track->GetLayer() ) );
        aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode );
    }

    // Plot zones (outdated, for old boards compatibility):
    for( TRACK* track = aBoard->m_Zone; track; track = track->Next() )
    {
        if( (GetLayerMask( track->GetLayer() ) & aLayerMask) == 0 )
            continue;

        int width = track->GetWidth() + itemplotter.getFineWidthAdj();
        aPlotter->SetColor( itemplotter.getColor( track->GetLayer() ) );
        aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode );
    }

    // Plot filled ares
    for( int ii = 0; ii < aBoard->GetAreaCount(); ii++ )
    {
        ZONE_CONTAINER* zone = aBoard->GetArea( ii );

        if( ( GetLayerMask(zone->GetLayer() )  & aLayerMask ) == 0 )
            continue;

        itemplotter.PlotFilledAreas( zone );
    }

    // Adding drill marks, if required and if the plotter is able to plot them:
    if( aPlotOpt.GetDrillMarksType() != PCB_PLOT_PARAMS::NO_DRILL_SHAPE )
        itemplotter.PlotDrillMarks();
}
void PlotLayerOutlines( BOARD *aBoard, PLOTTER* aPlotter,
                        LAYER_MSK aLayerMask, const PCB_PLOT_PARAMS& aPlotOpt )
{

    BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
    itemplotter.SetLayerMask( aLayerMask );

    CPOLYGONS_LIST outlines;

    for( LAYER_NUM layer = FIRST_LAYER; layer < NB_PCB_LAYERS; layer++ )
    {
        LAYER_MSK layer_mask = GetLayerMask( layer );

        if( (aLayerMask & layer_mask ) == 0 )
            continue;

        outlines.RemoveAllContours();
        aBoard->ConvertBrdLayerToPolygonalContours( layer, outlines );

        // Merge all overlapping polygons.
        KI_POLYGON_SET kpolygons;
        KI_POLYGON_SET ktmp;
        outlines.ExportTo( ktmp );

        kpolygons += ktmp;

        // Plot outlines
        std::vector< wxPoint > cornerList;

        for( unsigned ii = 0; ii < kpolygons.size(); ii++ )
        {
            KI_POLYGON polygon = kpolygons[ii];

            // polygon contains only one polygon, but it can have holes linked by
            // overlapping segments.
            // To plot clean outlines, we have to break this polygon into more polygons with
            // no overlapping segments, using Clipper, because boost::polygon
            // does not allow that
            ClipperLib::Path raw_polygon;
            ClipperLib::Paths normalized_polygons;

            for( unsigned ic = 0; ic < polygon.size(); ic++ )
            {
                KI_POLY_POINT corner = *(polygon.begin() + ic);
                raw_polygon.push_back( ClipperLib::IntPoint( corner.x(), corner.y() ) );
            }

            ClipperLib::SimplifyPolygon( raw_polygon, normalized_polygons );

            // Now we have one or more basic polygons: plot each polygon
            for( unsigned ii = 0; ii < normalized_polygons.size(); ii++ )
            {
                ClipperLib::Path& polygon = normalized_polygons[ii];
                cornerList.clear();

                for( unsigned jj = 0; jj < polygon.size(); jj++ )
                    cornerList.push_back( wxPoint( polygon[jj].X , polygon[jj].Y ) );

                // Ensure the polygon is closed
                if( cornerList[0] != cornerList[cornerList.size()-1] )
                    cornerList.push_back( cornerList[0] );

                aPlotter->PlotPoly( cornerList, NO_FILL );
            }
        }

        // Plot pad holes
        if( aPlotOpt.GetDrillMarksType() != PCB_PLOT_PARAMS::NO_DRILL_SHAPE )
        {
            for( MODULE* module = aBoard->m_Modules; module; module = module->Next() )
            {
                for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() )
                {
                    wxSize hole = pad->GetDrillSize();

                    if( hole.x == 0 || hole.y == 0 )
                        continue;

                    if( hole.x == hole.y )
                        aPlotter->Circle( pad->GetPosition(), hole.x, NO_FILL );
                    else
                    {
                        wxPoint drl_start, drl_end;
                        int width;
                        pad->GetOblongDrillGeometry( drl_start, drl_end, width );
                        aPlotter->ThickSegment( pad->GetPosition() + drl_start,
                                pad->GetPosition() + drl_end, width, SKETCH );
                    }
                }
            }
        }

        // Plot vias holes
        for( TRACK* track = aBoard->m_Track; track; track = track->Next() )
        {
            const VIA* via = dyn_cast<const VIA*>( track );

            if( via && via->IsOnLayer( layer ) )    // via holes can be not through holes
            {
                aPlotter->Circle( via->GetPosition(), via->GetDrillValue(), NO_FILL );
            }
        }
    }
}
Esempio n. 23
0
void DIALOG_PRINT_USING_PRINTER::InitValues( )
/************************************************************************/
{
    SetFocus();
    LAYER_NUM layer_max = NB_GERBER_LAYERS;
    wxString msg;

    if( g_pageSetupData == NULL )
    {
        g_pageSetupData = new wxPageSetupDialogData;
        // Set initial page margins.
        // Margins are already set in Pcbnew, so we can use 0
        g_pageSetupData->SetMarginTopLeft(wxPoint(0, 0));
        g_pageSetupData->SetMarginBottomRight(wxPoint(0, 0));
    }

    s_Parameters.m_PageSetupData = g_pageSetupData;

    layer_max = NB_LAYERS;
    // Create layer list
    for( LAYER_NUM ii = FIRST_LAYER; ii < layer_max; ++ii )
    {
        LAYER_MSK mask = GetLayerMask( ii );
        msg = _( "Layer" );
        msg << wxT( " " ) << ii + 1;
        m_BoxSelectLayer[ii] = new wxCheckBox( this, -1, msg );

        if( mask & s_SelectedLayers )
            m_BoxSelectLayer[ii]->SetValue( true );
        if( ii < 16 )
            m_leftLayersBoxSizer->Add( m_BoxSelectLayer[ii],
                                         wxGROW | wxLEFT | wxRIGHT | wxTOP );
        else
            m_rightLayersBoxSizer->Add( m_BoxSelectLayer[ii],
                                            wxGROW | wxLEFT | wxRIGHT | wxTOP );
    }


    // Read the scale adjust option
    int scale_idx = 4; // default selected scale = ScaleList[4] = 1.000

    if( m_Config )
    {
        m_Config->Read( OPTKEY_PRINT_X_FINESCALE_ADJ, &s_Parameters.m_XScaleAdjust );
        m_Config->Read( OPTKEY_PRINT_Y_FINESCALE_ADJ, &s_Parameters.m_YScaleAdjust );
        m_Config->Read( OPTKEY_PRINT_SCALE, &scale_idx );
        m_Config->Read( OPTKEY_PRINT_PAGE_FRAME, &s_Parameters.m_Print_Sheet_Ref, 1);
        m_Config->Read( OPTKEY_PRINT_MONOCHROME_MODE, &s_Parameters.m_Print_Black_and_White, 1);

        // Test for a reasonnable scale value. Set to 1 if problem
        if( s_Parameters.m_XScaleAdjust < MIN_SCALE ||
            s_Parameters.m_YScaleAdjust < MIN_SCALE ||
            s_Parameters.m_XScaleAdjust > MAX_SCALE ||
            s_Parameters.m_YScaleAdjust > MAX_SCALE )
            s_Parameters.m_XScaleAdjust = s_Parameters.m_YScaleAdjust = 1.0;

        s_SelectedLayers = 0;
        for( LAYER_NUM layer = FIRST_LAYER; layer < layer_max; ++layer )
        {
            wxString layerKey;
            bool     option;

            layerKey.Printf( OPTKEY_LAYERBASE, layer );

            option = false;
            if( m_Config->Read( layerKey, &option ) )
            {
                m_BoxSelectLayer[layer]->SetValue( option );
                if( option )
                    s_SelectedLayers |= GetLayerMask( layer );
            }
        }
    }

    m_ScaleOption->SetSelection( scale_idx );
    scale_idx = m_ScaleOption->GetSelection();
    s_Parameters.m_PrintScale =  s_ScaleList[scale_idx];
    m_Print_Mirror->SetValue(s_Parameters.m_PrintMirror);


    if( s_Parameters.m_Print_Black_and_White )
        m_ModeColorOption->SetSelection( 1 );
    else
        m_ModeColorOption->SetSelection( 0 );

    s_Parameters.m_PenDefaultSize = 0;

    // Create scale adjust option
    msg.Printf( wxT( "%f" ), s_Parameters.m_XScaleAdjust );
    m_FineAdjustXscaleOpt->SetValue( msg );
    msg.Printf( wxT( "%f" ), s_Parameters.m_YScaleAdjust );
    m_FineAdjustYscaleOpt->SetValue( msg );

    bool enable = (s_Parameters.m_PrintScale == 1.0);
    if( m_FineAdjustXscaleOpt )
        m_FineAdjustXscaleOpt->Enable(enable);
    if( m_FineAdjustYscaleOpt )
        m_FineAdjustYscaleOpt->Enable(enable);
}
Esempio n. 24
0
void DIALOG_SVG_PRINT::ExportSVGFile( bool aOnlyOneFile )
{
    m_outputDirectory = m_outputDirectoryName->GetValue();

    // Create output directory if it does not exist (also transform it in
    // absolute form). Bail if it fails
    wxFileName outputDir = wxFileName::DirName( m_outputDirectory );
    wxString boardFilename = m_board->GetFileName();
    WX_TEXT_CTRL_REPORTER reporter( m_messagesBox );

    if( !EnsureOutputDirectory( &outputDir, boardFilename, &reporter ) )
    {
        wxString msg;
        msg.Printf( _( "Could not write plot files to folder \"%s\"." ),
                    GetChars( outputDir.GetPath() ) );
        DisplayError( this, msg );
        return;
    }

    m_printMirror = m_printMirrorOpt->GetValue();
    m_printBW = m_ModeColorOption->GetSelection();
    SetPenWidth();

    // Build layers mask
    LAYER_MSK printMaskLayer = NO_LAYERS;

    for( LAYER_NUM layer = FIRST_LAYER; layer < NB_PCB_LAYERS; ++layer )
    {
        if( m_boxSelectLayer[layer] && m_boxSelectLayer[layer]->GetValue() )
            printMaskLayer |= GetLayerMask( layer );
    }

    wxString    msg;

    for( LAYER_NUM layer = FIRST_LAYER; layer < NB_PCB_LAYERS; ++layer )
    {
        LAYER_MSK currlayer_mask = GetLayerMask( layer );

        if( (printMaskLayer & currlayer_mask ) == 0 )
            continue;

        wxString suffix = m_board->GetStandardLayerName( layer );

        if( aOnlyOneFile )
        {
            m_printMaskLayer = printMaskLayer;
            suffix = wxT( "brd" );
        }
        else
        {
            m_printMaskLayer = currlayer_mask;
            suffix = m_board->GetStandardLayerName( layer );
        }

        wxFileName fn(boardFilename);
        BuildPlotFileName( &fn, outputDir.GetPath(), suffix, SVGFileExtension );

        if( m_PrintBoardEdgesCtrl->IsChecked() )
            m_printMaskLayer |= EDGE_LAYER;

        if( CreateSVGFile( fn.GetFullPath() ) )
            msg.Printf( _( "Plot: %s OK\n" ), GetChars( fn.GetFullPath() ) );
        else    // Error
            msg.Printf( _( "** Unable to create %s **\n" ), GetChars( fn.GetFullPath() ) );
        m_messagesBox->AppendText( msg );

        if( aOnlyOneFile )
            break;
    }
}
Esempio n. 25
0
/*
 * This function starts a new track segment.
 * If a new track segment is in progress, ends this current new segment,
 * and created a new one.
 */
TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC )
{
    TRACK*      TrackOnStartPoint = NULL;
    int         layerMask = GetLayerMask( GetScreen()->m_Active_Layer );
    BOARD_CONNECTED_ITEM* LockPoint;
    wxPoint     pos = GetScreen()->GetCrossHairPosition();

    if( aTrack == NULL )  // Starting a new track segment
    {
        m_canvas->SetMouseCapture( ShowNewTrackWhenMovingCursor, Abort_Create_Track );

        // Prepare the undo command info
        s_ItemsListPicker.ClearListAndDeleteItems();  // Should not be necessary, but...

        GetBoard()->PushHighLight();

        // erase old highlight
        if( GetBoard()->IsHighLightNetON() )
            HighLight( aDC );

        g_CurrentTrackList.PushBack( new TRACK( GetBoard() ) );
        g_CurrentTrackSegment->SetFlags( IS_NEW );

        GetBoard()->SetHighLightNet( 0 );

        // Search for a starting point of the new track, a track or pad
        LockPoint = GetBoard()->GetLockPoint( pos, layerMask );

        D_PAD* pad = NULL;
        if( LockPoint ) // An item (pad or track) is found
        {
            if( LockPoint->Type() == PCB_PAD_T )
            {
                pad = (D_PAD*) LockPoint;

                // A pad is found: put the starting point on pad center
                pos = pad->GetPosition();
                GetBoard()->SetHighLightNet( pad->GetNet() );
            }
            else // A track segment is found
            {
                TrackOnStartPoint    = (TRACK*) LockPoint;
                GetBoard()->SetHighLightNet( TrackOnStartPoint->GetNet() );
                GetBoard()->CreateLockPoint( pos, TrackOnStartPoint, &s_ItemsListPicker );
            }
        }
        else
        {
            // Not a starting point, but a filled zone area can exist. This is also a
            // good starting point.
            ZONE_CONTAINER* zone;
            zone = GetBoard()->HitTestForAnyFilledArea( pos, GetScreen()-> m_Active_Layer );

            if( zone )
                GetBoard()->SetHighLightNet( zone->GetNet() );
        }

        D( g_CurrentTrackList.VerifyListIntegrity() );

        BuildAirWiresTargetsList( LockPoint, wxPoint( 0, 0 ), true );

        D( g_CurrentTrackList.VerifyListIntegrity() );

        GetBoard()->HighLightON();
        GetBoard()->DrawHighLight( m_canvas, aDC, GetBoard()->GetHighLightNetCode() );

        // Display info about track Net class, and init track and vias sizes:
        g_CurrentTrackSegment->SetNet( GetBoard()->GetHighLightNetCode() );
        GetBoard()->SetCurrentNetClass( g_CurrentTrackSegment->GetNetClassName() );

        g_CurrentTrackSegment->SetLayer( GetScreen()->m_Active_Layer );
        g_CurrentTrackSegment->SetWidth( GetBoard()->GetCurrentTrackWidth() );

        if( GetBoard()->GetDesignSettings().m_UseConnectedTrackWidth )
        {
            if( TrackOnStartPoint && TrackOnStartPoint->Type() == PCB_TRACE_T )
                g_CurrentTrackSegment->SetWidth( TrackOnStartPoint->GetWidth());
        }

        g_CurrentTrackSegment->SetStart( pos );
        g_CurrentTrackSegment->SetEnd( pos );

        if( pad )
        {
            g_CurrentTrackSegment->m_PadsConnected.push_back( pad );
            // Useful to display track length, if the pad has a die length:
            g_CurrentTrackSegment->SetState( BEGIN_ONPAD, ON );
            g_CurrentTrackSegment->start = pad;
        }

        if( g_TwoSegmentTrackBuild )
        {
            // Create 2nd segment
            g_CurrentTrackList.PushBack( (TRACK*)g_CurrentTrackSegment->Clone() );

            D( g_CurrentTrackList.VerifyListIntegrity(); );

            g_CurrentTrackSegment->start = g_FirstTrackSegment;
            g_FirstTrackSegment->end     = g_CurrentTrackSegment;

            g_FirstTrackSegment->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
        }
// Place a dragged (or moved) track segment or via
bool PCB_EDIT_FRAME::PlaceDraggedOrMovedTrackSegment( TRACK* Track, wxDC* DC )
{
    int        errdrc;

    if( Track == NULL )
        return false;

    int current_net_code = Track->GetNetCode();

    // DRC control:
    if( g_Drc_On )
    {
        errdrc = m_drc->Drc( Track, GetBoard()->m_Track );

        if( errdrc == BAD_DRC )
            return false;

        // Redraw the dragged segments
        for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ )
        {
            errdrc = m_drc->Drc( g_DragSegmentList[ii].m_Track, GetBoard()->m_Track );

            if( errdrc == BAD_DRC )
                return false;
        }
    }

    // DRC Ok: place track segments
    Track->ClearFlags();
    Track->SetState( IN_EDIT, false );

    // Draw dragged tracks
    for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ )
    {
        Track = g_DragSegmentList[ii].m_Track;
        Track->SetState( IN_EDIT, false );
        Track->ClearFlags();

        /* Test the connections modified by the move
         *  (only pad connection must be tested, track connection will be
         * tested by TestNetConnection() ) */
        LAYER_MSK layerMask = GetLayerMask( Track->GetLayer() );
        Track->start = GetBoard()->GetPadFast( Track->GetStart(), layerMask );

        if( Track->start )
            Track->SetState( BEGIN_ONPAD, true );
        else
            Track->SetState( BEGIN_ONPAD, false );

        Track->end = GetBoard()->GetPadFast( Track->GetEnd(), layerMask );

        if( Track->end )
            Track->SetState( END_ONPAD, true );
        else
            Track->SetState( END_ONPAD, false );
    }

    EraseDragList();

    SaveCopyInUndoList( s_ItemsListPicker, UR_UNSPECIFIED );
    s_ItemsListPicker.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items

    GetBoard()->PopHighLight();

    OnModify();
    m_canvas->SetMouseCapture( NULL, NULL );

    if( current_net_code > 0 )
        TestNetConnection( DC, current_net_code );

    m_canvas->Refresh();

    return true;
}
/**
 * Function Magnetize
 * tests to see if there are any magnetic items within near reach of the given
 * "curpos".  If yes, then curpos is adjusted appropriately according to that
 * near magnetic item and true is returned.
 * @param frame = the current frame
 * @param aCurrentTool = the current tool id (from vertical right toolbar)
 * @param aGridSize = the current grid size
 * @param on_grid = the on grid position near initial position ( often on_grid = curpos)
 * @param curpos The initial position, and what to adjust if a change is needed.
 * @return bool - true if the position was adjusted magnetically, else false.
 */
bool Magnetize( PCB_EDIT_FRAME* frame, int aCurrentTool, wxSize aGridSize,
                wxPoint on_grid, wxPoint* curpos )
{
    bool    doCheckNet = g_MagneticPadOption != capture_always && g_Drc_On;
    bool    doTrack = false;
    bool    doPad = false;
    bool    amMovingVia = false;

    BOARD* m_Pcb = frame->GetBoard();
    TRACK*      currTrack = g_CurrentTrackSegment;
    BOARD_ITEM* currItem  = frame->GetCurItem();
    PCB_SCREEN* screen = frame->GetScreen();
    wxPoint     pos = frame->RefPos( true );

    // D( printf( "currTrack=%p currItem=%p currTrack->Type()=%d currItem->Type()=%d\n",  currTrack, currItem, currTrack ? currTrack->Type() : 0, currItem ? currItem->Type() : 0 ); )

    if( !currTrack && currItem && currItem->Type()==PCB_VIA_T && currItem->GetFlags() )
    {
        // moving a VIA
        currTrack = (TRACK*) currItem;
        amMovingVia = true;

        return false;   // comment this return out and play with it.
    }
    else if( currItem != currTrack )
    {
        currTrack = NULL;
    }

    if( g_MagneticPadOption == capture_always )
        doPad = true;

    if( g_MagneticTrackOption == capture_always )
        doTrack = true;

    if( aCurrentTool == ID_TRACK_BUTT || amMovingVia )
    {
        int q = capture_cursor_in_track_tool;

        if( g_MagneticPadOption == q )
            doPad = true;

        if( g_MagneticTrackOption == q )
            doTrack = true;
    }

    // D(printf("doPad=%d doTrack=%d aCurrentTool=%d amMovingVia=%d\n", doPad, doTrack, aCurrentTool, amMovingVia );)

    //  The search precedence order is pads, then tracks/vias

    if( doPad )
    {
        LAYER_MSK layer_mask = GetLayerMask( screen->m_Active_Layer );
        D_PAD* pad = m_Pcb->GetPad( pos, layer_mask );

        if( pad )
        {
            if( doCheckNet && currTrack && currTrack->GetNetCode() != pad->GetNetCode() )
                return false;

            *curpos = pad->GetPosition();
            return true;
        }
    }

    // after pads, only track & via tests remain, skip them if not desired
    if( doTrack )
    {
        LAYER_NUM layer = screen->m_Active_Layer;

        for( TRACK* via = m_Pcb->m_Track;
             via && (via = via->GetVia( *curpos, layer )) != NULL;
             via = via->Next() )
        {
            if( via != currTrack )   // a via cannot influence itself
            {
                if( !doCheckNet || !currTrack || currTrack->GetNetCode() == via->GetNetCode() )
                {
                    *curpos = via->GetStart();
                    // D(printf("via hit\n");)
                    return true;
                }
            }
        }

        if( !currTrack )
        {
            LAYER_MSK layer_mask = GetLayerMask( layer );

            TRACK* track = m_Pcb->GetTrack( m_Pcb->m_Track, pos, layer_mask );

            if( !track || track->Type() != PCB_TRACE_T )
            {
                // D(printf("!currTrack and track=%p not found, layer_mask=0x%X\n", track, layer_mask );)
                return false;
            }

            // D( printf( "Project\n" ); )
            return Project( curpos, on_grid, track );
        }

        /*
         * In two segment mode, ignore the final segment if it's inside a grid square.
         */
        if( !amMovingVia && currTrack && g_TwoSegmentTrackBuild && currTrack->Back()
            && currTrack->GetStart().x - aGridSize.x < currTrack->GetEnd().x
            && currTrack->GetStart().x + aGridSize.x > currTrack->GetEnd().x
            && currTrack->GetStart().y - aGridSize.y < currTrack->GetEnd().y
            && currTrack->GetStart().y + aGridSize.y > currTrack->GetEnd().y )
        {
            currTrack = currTrack->Back();
        }


        for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() )
        {
            if( track->Type() != PCB_TRACE_T )
                continue;

            if( doCheckNet && currTrack && currTrack->GetNetCode() != track->GetNetCode() )
                continue;

            if( m_Pcb->IsLayerVisible( track->GetLayer() ) == false )
                continue;

            // omit the layer check if moving a via
            if( !amMovingVia && !track->IsOnLayer( layer ) )
                continue;

            if( !track->HitTest( *curpos ) )
                continue;

            // D(printf( "have track prospect\n");)

            if( Join( curpos, track->GetStart(), track->GetEnd(), currTrack->GetStart(), currTrack->GetEnd() ) )
            {
                // D(printf( "join currTrack->Type()=%d\n", currTrack->Type() );)
                return true;
            }

            if( aCurrentTool == ID_TRACK_BUTT || amMovingVia )
            {
                // At this point we have a drawing mouse on a track, we are drawing
                // a new track and that new track is parallel to the track the
                // mouse is on. Find the nearest end point of the track under mouse
                // to the mouse and return that.
                double distStart = GetLineLength( *curpos, track->GetStart() );
                double distEnd   = GetLineLength( *curpos, track->GetEnd() );

                // if track not via, or if its a via dragging but not with its adjacent track
                if( currTrack->Type() != PCB_VIA_T
                  || ( currTrack->GetStart() != track->GetStart() && currTrack->GetStart() != track->GetEnd() ))
                {
                    if( distStart <= currTrack->GetWidth()/2 )
                    {
                        // D(printf("nearest end is start\n");)
                        *curpos = track->GetStart();
                        return true;
                    }

                    if( distEnd <= currTrack->GetWidth()/2 )
                    {
                        // D(printf("nearest end is end\n");)
                        *curpos = track->GetEnd();
                        return true;
                    }

                    // @todo otherwise confine curpos such that it stays centered within "track"
                }
            }
        }
    }

    return false;
}