/** * 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 ); } }
int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent ) { if( !m_frame->GetModel() ) return 0; DIALOG_DXF_IMPORT dlg( m_frame ); int dlgResult = dlg.ShowModal(); const std::list<BOARD_ITEM*>& list = dlg.GetImportedItems(); if( dlgResult != wxID_OK || list.empty() ) return 0; VECTOR2I cursorPos = m_controls->GetCursorPosition(); VECTOR2I delta = cursorPos - list.front()->GetPosition(); // Add a VIEW_GROUP that serves as a preview for the new item SELECTION preview( m_view ); BOARD_COMMIT commit( m_frame ); // Build the undo list & add items to the current view for( auto item : list ) { assert( item->Type() == PCB_LINE_T || item->Type() == PCB_TEXT_T ); preview.Add( item ); } BOARD_ITEM* firstItem = preview.Front(); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_controls->ShowCursor( true ); m_controls->SetSnapping( true ); SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DXF ); Activate(); // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { cursorPos = m_controls->GetCursorPosition(); if( evt->IsMotion() ) { delta = cursorPos - firstItem->GetPosition(); for( auto item : preview ) item->Move( wxPoint( delta.x, delta.y ) ); m_view->Update( &preview ); } else if( evt->Category() == TC_COMMAND ) { // TODO it should be handled by EDIT_TOOL, so add items and select? if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { for( auto item : preview ) item->Rotate( wxPoint( cursorPos.x, cursorPos.y ), m_frame->GetRotationAngle() ); m_view->Update( &preview ); } else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { for( auto item : preview ) item->Flip( wxPoint( cursorPos.x, cursorPos.y ) ); m_view->Update( &preview ); } else if( evt->IsCancel() || evt->IsActivate() ) { preview.FreeItems(); break; } } else if ( evt->IsClick( BUT_RIGHT ) ) { showContextMenu(); } else if( evt->IsClick( BUT_LEFT ) ) { // Place the drawing BOARD_ITEM_CONTAINER* parent = m_frame->GetModel(); for( auto item : preview ) { if( m_editModules ) { // Modules use different types for the same things, // so we need to convert imported items to appropriate classes. BOARD_ITEM* converted = NULL; switch( item->Type() ) { case PCB_TEXT_T: { TEXTE_PCB* text = static_cast<TEXTE_PCB*>( item ); TEXTE_MODULE* textMod = new TEXTE_MODULE( (MODULE*) parent ); // Assignment operator also copies the item PCB_TEXT_T type, // so it cannot be added to a module which handles PCB_MODULE_TEXT_T textMod->SetPosition( text->GetPosition() ); textMod->SetText( text->GetText() ); textMod->SetSize( text->GetSize() ); textMod->SetThickness( text->GetThickness() ); textMod->SetOrientation( text->GetOrientation() ); textMod->SetTextPosition( text->GetTextPosition() ); textMod->SetSize( text->GetSize() ); textMod->SetMirrored( text->IsMirrored() ); textMod->SetAttributes( text->GetAttributes() ); textMod->SetItalic( text->IsItalic() ); textMod->SetBold( text->IsBold() ); textMod->SetHorizJustify( text->GetHorizJustify() ); textMod->SetVertJustify( text->GetVertJustify() ); textMod->SetMultilineAllowed( text->IsMultilineAllowed() ); converted = textMod; break; } case PCB_LINE_T: { DRAWSEGMENT* seg = static_cast<DRAWSEGMENT*>( item ); EDGE_MODULE* modSeg = new EDGE_MODULE( (MODULE*) parent ); // Assignment operator also copies the item PCB_LINE_T type, // so it cannot be added to a module which handles PCB_MODULE_EDGE_T modSeg->SetWidth( seg->GetWidth() ); modSeg->SetStart( seg->GetStart() ); modSeg->SetEnd( seg->GetEnd() ); modSeg->SetAngle( seg->GetAngle() ); modSeg->SetShape( seg->GetShape() ); modSeg->SetType( seg->GetType() ); modSeg->SetBezControl1( seg->GetBezControl1() ); modSeg->SetBezControl2( seg->GetBezControl2() ); modSeg->SetBezierPoints( seg->GetBezierPoints() ); modSeg->SetPolyPoints( seg->GetPolyPoints() ); converted = modSeg; break; } default: assert( false ); break; } if( converted ) converted->SetLayer( item->GetLayer() ); delete item; item = converted; } if( item ) commit.Add( item ); } commit.Push( _( "Place a DXF drawing" ) ); break; } } preview.Clear(); m_controls->ShowCursor( false ); m_controls->SetSnapping( false ); m_controls->SetAutoPan( false ); m_controls->CaptureCursor( false ); m_view->Remove( &preview ); return 0; }