Commit 7dbb0da3 authored by dickelbeck's avatar dickelbeck

more amazing free specctra import/export software

parent f0ba106e
......@@ -8,7 +8,10 @@ email address.
2008-Feb-7 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================
+pcbnew
specctra import of *.ses, done by end of today probably.
specctra import of *.ses, did tracks and components.
renamed copy_track.cpp to copy_track.cpp.notused
removed copy_track.cpp from pcbnew/CMakeLists.txt
added setlocale() around import and export for float text style.
2008-Feb-6 UPDATE Dick Hollenbeck <dick@softplc.com>
......
......@@ -39,7 +39,7 @@ SET(PCBNEW_SRCS
collectors.cpp
connect.cpp
controle.cpp
copy_track.cpp
# copy_track.cpp
cotation.cpp
cross-probing.cpp
deltrack.cpp
......@@ -74,7 +74,7 @@ SET(PCBNEW_SRCS
files.cpp
find.cpp
gen_drill_report_files.cpp
gen_holes_and_tools_lists_for_drill.cpp
gen_holes_and_tools_lists_for_drill.cpp
gen_modules_placefile.cpp
gendrill.cpp
globaleditpad.cpp
......
......@@ -41,7 +41,7 @@ WinEDA_BasePcbFrame::WinEDA_BasePcbFrame( wxWindow* father,
const wxString& title,
const wxPoint& pos,
const wxSize& size,
long style) :
long style) :
WinEDA_DrawFrame( father, idtype, parent, title, pos, size, style )
{
m_InternalUnits = 10000; // Internal unit = 1/10000 inch
......@@ -103,9 +103,9 @@ void WinEDA_BasePcbFrame::CursorGoto( const wxPoint& aPos )
// factored out of pcbnew/find.cpp
PCB_SCREEN* screen = GetScreen();
wxClientDC dc( DrawPanel );
/* Il y a peut-etre necessite de recadrer le dessin: */
if( !DrawPanel->IsPointOnDisplay( aPos ) )
{
......@@ -159,10 +159,10 @@ void WinEDA_BasePcbFrame::Show3D_Frame( wxCommandEvent& event )
DisplayInfo( this, _( "3D Frame already opened" ) );
return;
}
#ifdef CVPCB
m_Draw3DFrame = new WinEDA3D_DrawFrame( this, m_Parent, _( "3D Viewer" ),
KICAD_DEFAULT_3D_DRAWFRAME_STYLE | wxFRAME_FLOAT_ON_PARENT );
KICAD_DEFAULT_3D_DRAWFRAME_STYLE | wxFRAME_FLOAT_ON_PARENT );
#else
m_Draw3DFrame = new WinEDA3D_DrawFrame( this, m_Parent, _( "3D Viewer" ) );
#endif
......@@ -277,23 +277,23 @@ void WinEDA_BasePcbFrame::SetCurItem( BOARD_ITEM* aItem )
/*****************************************************************/
{
m_CurrentScreen->SetCurItem( aItem );
if( aItem )
{
aItem->Display_Infos( this );
#if 0 && defined(DEBUG)
#if 1 && defined(DEBUG)
aItem->Show( 0, std::cout );
#endif
}
else
{
// we can use either of these two:
//MsgPanel->EraseMsgBox();
m_Pcb->Display_Infos( this ); // show the BOARD stuff
#if 0 && defined(DEBUG)
std::cout << "SetCurItem(NULL)\n";
#endif
......
/*******************************************/
/* Track editing: routines to copy tracks */
/*******************************************/
#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
#include "pcbnew.h"
#include "autorout.h"
#include "drag.h"
#include "protos.h"
/* local functions */
/* variables locales */
#if 0
/***************************************************************/
void WinEDA_PcbFrame::Place_Dupl_Track(Track * Track, wxDC * DC)
/***************************************************************/
/*
Routine de placement d'une piste (succession de segments)
*/
{
D_PAD * pt_pad;
TRACK * pt_track, *Track, * pt_classe, *NextS;
int masquelayer;
EDA_BaseStruct * LockPoint;
int ii, old_net_code, new_net_code, DRC_error = 0;
wxDC * DC = Cmd->DC;
ActiveDrawPanel->ManageCurseur = NULL;
if( NewTrack == NULL ) return ;
old_net_code = NewTrack->net_code;
/* Placement du flag BUSY de la piste originelle, qui ne doit
pas etre vue dans les recherches de raccordement suivantes */
ii = NbPtNewTrack; pt_track = NewTrack;
for ( ; ii > 0; ii --, pt_track = (TRACK*) pt_track->Pnext)
{
pt_track->SetState(BUSY, ON);
}
/* Detection du nouveau net_code */
ii = NbPtNewTrack; pt_track = NewTrack;
for ( ; ii > 0; ii --, pt_track = (TRACK*) pt_track->Pnext)
{
pt_track->net_code = 0;
}
new_net_code = 0;
ii = 0; pt_track = NewTrack;
for( ; ii < NbPtNewTrack ; ii++, pt_track = (TRACK*)pt_track->Pnext)
{
/* Localisation de la pastille ou segment en debut de segment: */
masquelayer = tab_layer[pt_track->Layer];
LockPoint = LocateLockPoint(pt_track->m_Start.x,pt_track->m_Start.y,masquelayer);
if( LockPoint )
{
if ( LockPoint->Type() == TYPEPAD )
{
pt_pad = (D_PAD*) LockPoint;
new_net_code = pt_pad->net_code;
if ( new_net_code > 0 ) break;
}
else /* debut de piste sur un segment de piste */
{
Track = (TRACK *) LockPoint;
new_net_code = Track->net_code;
if ( new_net_code > 0 ) break;
}
}
LockPoint = LocateLockPoint(pt_track->m_End.x,pt_track->m_End.y,masquelayer);
if( LockPoint )
{
if ( LockPoint->Type() == TYPEPAD )
{
pt_pad = (D_PAD*) LockPoint;
new_net_code = pt_pad->net_code;
if ( new_net_code > 0 ) break;
}
else /* debut de piste sur un segment de piste */
{
Track = (TRACK *) LockPoint;
new_net_code = Track->net_code;
if ( new_net_code > 0 ) break;
}
}
}
/* Mise a jour du nouveau net code de la piste */
ii = 0; pt_track = NewTrack;
for( ; ii < NbPtNewTrack; ii++, pt_track = (TRACK*)pt_track->Pnext)
{
pt_track->net_code = new_net_code;
}
/* Controle DRC de la nouvelle piste */
ii = 0; pt_track = NewTrack;
for( ; ii < NbPtNewTrack; ii++, pt_track = pt_track->Next() )
{
if( Drc_On == RUN )
if( drc(DC, pt_track, pt_pcb->Track, 1) == BAD_DRC )
{
if( confirmation(" Erreur DRC, Place piste:") == YES ) continue;
else { DRC_error = 1; break; }
}
}
if( DRC_error == 0)
{
if(FlagState == MOVE_ROUTE)
{
/* copie nouvelle piste */
pt_track = NewTrack;
NewTrack = pt_track->Copy(NbPtNewTrack);
/* effacement ancienne ( chainage et liens mauvais */
ii = NbPtNewTrack;
for ( ; ii > 0; ii --, pt_track = NextS)
{
NextS = (TRACK*) pt_track->Pnext;
pt_track->DeleteStructure();
}
test_1_net_connexion(DC, old_net_code );
}
pt_classe = NewTrack->GetBestInsertPoint();
NewTrack->Insert(pt_classe);
Trace_Une_Piste(DC, NewTrack,NbPtNewTrack,GR_OR) ;
/* Mise a jour des connexions sur pads et sur pistes */
ii = 0; pt_track = NewTrack;
for( ; ii < NbPtNewTrack; ii++, pt_track = NextS)
{
NextS = (TRACK*)pt_track->Pnext;
pt_track->SetState(BEGIN_ONPAD|END_ONPAD, OFF);
masquelayer = tab_layer[pt_track->Layer];
/* Localisation de la pastille ou segment sur debut segment: */
LockPoint = LocateLockPoint(pt_track->m_Start.x,pt_track->m_Start.y,masquelayer);
if( LockPoint )
{
pt_track->start = LockPoint;
if ( LockPoint->Type() == TYPEPAD )
{ /* fin de piste sur un pad */
pt_pad = (D_PAD*) LockPoint;
pt_track->SetState(BEGIN_ONPAD, ON);
}
else /* debut de piste sur un segment de piste */
{
Track = (TRACK *) LockPoint;
CreateLockPoint(&pt_track->m_Start.x,&pt_track->m_Start.y,Track,pt_track);
}
}
/* Localisation de la pastille ou segment sur fin de segment: */
LockPoint = LocateLockPoint(pt_track->m_End.x,pt_track->m_End.y,masquelayer);
if( LockPoint )
{
pt_track->end = LockPoint;
if ( LockPoint->Type() == TYPEPAD )
{ /* fin de piste sur un pad */
pt_pad = (D_PAD*) LockPoint;
pt_track->SetState(END_ONPAD, ON);
}
else /* debut de piste sur un segment de piste */
{
Track = (TRACK *) LockPoint;
CreateLockPoint(&pt_track->m_Start.x,&pt_track->m_Start.y,Track,pt_track);
}
}
}
/* Clear the BUSY flag */
ii = NbPtNewTrack; pt_track = NewTrack;
for ( ; ii > 0; ii --, pt_track = (TRACK*) pt_track->Pnext)
{
pt_track->SetState(BUSY, OFF);
}
test_1_net_connexion(DC, new_net_code );
ActiveScreen->SetModify();
}
else /* DRC error: Annulation commande */
{
DisplayOpt.DisplayPcbTrackFill = FALSE ;
Trace_Une_Piste(DC, NewTrack,NbPtNewTrack,GR_XOR);
DisplayOpt.DisplayPcbTrackFill = Track_fill_copy ;
if(FlagState == MOVE_ROUTE)
{ /* Remise en position de la piste deplacee */
Track = NewTrack;
PosInitX -= Track->m_Start.x; PosInitY -= Track->m_Start.y;
for( ii = 0; ii < NbPtNewTrack; ii++, Track = (TRACK*) Track->Pnext)
{
if( Track == NULL ) break;
Track->m_Start.x += PosInitX; Track->m_Start.y += PosInitY;
Track->m_End.x += PosInitX; Track->m_End.y += PosInitY;
Track->SetState(BUSY,OFF);
}
Trace_Une_Piste(DC, NewTrack,NbPtNewTrack,GR_OR);
}
if (FlagState == COPY_ROUTE )
{ /* Suppression copie */
for( ii = 0; ii < NbPtNewTrack; NewTrack = NextS)
{
if(NewTrack == NULL) break;
NextS = (TRACK*) NewTrack->Pnext;
delete NewTrack;
}
}
}
NewTrack = NULL;
Affiche_Infos_Status_Pcb(Cmd);
if(Etat_Surbrillance) Hight_Light(DC);
}
/*******************************************************************************/
void WinEDA_PcbFrame::Start_CopyOrMove_Route(TRACK * track, wxDC * DC, bool Drag)
/*******************************************************************************/
/* Routine permettant la recopie d'une piste (suite de segments) deja tracee
*/
{
int ii;
TRACK *pt_segm, *pt_track;
int masquelayer = tab_layer[ActiveScreen->Active_Layer];
if( NewTrack ) return;
FlagState = (int)Cmd->Menu->param_inf;
/* Recherche de la piste sur la couche active (non zone) */
for(pt_segm = pt_pcb->Track; pt_segm != NULL; pt_segm = (TRACK*)pt_segm->Pnext)
{
pt_segm = Locate_Pistes(pt_segm,masquelayer, CURSEUR_OFF_GRILLE);
if( pt_segm == NULL ) break ;
break ;
}
if( pt_segm != NULL )
{
if (FlagState == COPY_ROUTE )
pt_track = Marque_Une_Piste(DC, pt_segm, &NbPtNewTrack, 0);
else pt_track = Marque_Une_Piste(DC, pt_segm, &NbPtNewTrack, GR_XOR);
if(NbPtNewTrack) /* Il y a NbPtNewTrack segments de piste a traiter */
{
/* effacement du flag BUSY de la piste originelle */
ii = NbPtNewTrack; pt_segm = pt_track;
for ( ; ii > 0; ii --, pt_segm = (TRACK*) pt_segm->Pnext)
{
pt_segm->SetState(BUSY, OFF);
}
if (FlagState == COPY_ROUTE )
NewTrack = pt_track->Copy(NbPtNewTrack);
else NewTrack = pt_track;
Affiche_Infos_Piste(Cmd, pt_track) ;
startX = ActiveScreen->Curseur_X;
startY = ActiveScreen->Curseur_Y;
Place_Dupl_Route_Item.State = WAIT;
ActiveDrawPanel->ManageCurseur = Show_Move_Piste;
DisplayOpt.DisplayPcbTrackFill = FALSE ;
Trace_Une_Piste(DC, NewTrack,NbPtNewTrack,GR_XOR) ;
DisplayOpt.DisplayPcbTrackFill = Track_fill_copy ;
PosInitX = NewTrack->m_Start.x; PosInitY = NewTrack->m_Start.y;
}
}
}
#endif
/*******************************************/
/* Track editing: routines to copy tracks */
/*******************************************/
#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
#include "pcbnew.h"
#include "autorout.h"
#include "drag.h"
#include "protos.h"
/* local functions */
/* variables locales */
#if 0
/***************************************************************/
void WinEDA_PcbFrame::Place_Dupl_Track( Track* Track, wxDC* DC )
/***************************************************************/
/*
* Routine de placement d'une piste (succession de segments)
*/
{
D_PAD* pt_pad;
TRACK* pt_track, * Track, * pt_classe, * NextS;
int masquelayer;
EDA_BaseStruct* LockPoint;
int ii, old_net_code, new_net_code, DRC_error = 0;
wxDC* DC = Cmd->DC;
ActiveDrawPanel->ManageCurseur = NULL;
if( NewTrack == NULL )
return;
old_net_code = NewTrack->net_code;
/* Placement du flag BUSY de la piste originelle, qui ne doit
* pas etre vue dans les recherches de raccordement suivantes */
ii = NbPtNewTrack; pt_track = NewTrack;
for( ; ii > 0; ii--, pt_track = (TRACK*) pt_track->Pnext )
{
pt_track->SetState( BUSY, ON );
}
/* Detection du nouveau net_code */
ii = NbPtNewTrack; pt_track = NewTrack;
for( ; ii > 0; ii--, pt_track = (TRACK*) pt_track->Pnext )
{
pt_track->net_code = 0;
}
new_net_code = 0;
ii = 0; pt_track = NewTrack;
for( ; ii < NbPtNewTrack; ii++, pt_track = (TRACK*) pt_track->Pnext )
{
/* Localisation de la pastille ou segment en debut de segment: */
masquelayer = tab_layer[pt_track->Layer];
LockPoint = LocateLockPoint( pt_track->m_Start.x, pt_track->m_Start.y, masquelayer );
if( LockPoint )
{
if( LockPoint->Type() == TYPEPAD )
{
pt_pad = (D_PAD*) LockPoint;
new_net_code = pt_pad->net_code;
if( new_net_code > 0 )
break;
}
else /* debut de piste sur un segment de piste */
{
Track = (TRACK*) LockPoint;
new_net_code = Track->net_code;
if( new_net_code > 0 )
break;
}
}
LockPoint = LocateLockPoint( pt_track->m_End.x, pt_track->m_End.y, masquelayer );
if( LockPoint )
{
if( LockPoint->Type() == TYPEPAD )
{
pt_pad = (D_PAD*) LockPoint;
new_net_code = pt_pad->net_code;
if( new_net_code > 0 )
break;
}
else /* debut de piste sur un segment de piste */
{
Track = (TRACK*) LockPoint;
new_net_code = Track->net_code;
if( new_net_code > 0 )
break;
}
}
}
/* Mise a jour du nouveau net code de la piste */
ii = 0; pt_track = NewTrack;
for( ; ii < NbPtNewTrack; ii++, pt_track = (TRACK*) pt_track->Pnext )
{
pt_track->net_code = new_net_code;
}
/* Controle DRC de la nouvelle piste */
ii = 0; pt_track = NewTrack;
for( ; ii < NbPtNewTrack; ii++, pt_track = pt_track->Next() )
{
if( Drc_On == RUN )
if( drc( DC, pt_track, pt_pcb->Track, 1 ) == BAD_DRC )
{
if( confirmation( " Erreur DRC, Place piste:" ) == YES )
continue;
else
{
DRC_error = 1; break;
}
}
}
if( DRC_error == 0 )
{
if( FlagState == MOVE_ROUTE )
{
/* copie nouvelle piste */
pt_track = NewTrack;
NewTrack = pt_track->Copy( NbPtNewTrack );
/* effacement ancienne ( chainage et liens mauvais */
ii = NbPtNewTrack;
for( ; ii > 0; ii--, pt_track = NextS )
{
NextS = (TRACK*) pt_track->Pnext;
pt_track->DeleteStructure();
}
test_1_net_connexion( DC, old_net_code );
}
pt_classe = NewTrack->GetBestInsertPoint();
NewTrack->Insert( pt_classe );
Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_OR );
/* Mise a jour des connexions sur pads et sur pistes */
ii = 0; pt_track = NewTrack;
for( ; ii < NbPtNewTrack; ii++, pt_track = NextS )
{
NextS = (TRACK*) pt_track->Pnext;
pt_track->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
masquelayer = tab_layer[pt_track->Layer];
/* Localisation de la pastille ou segment sur debut segment: */
LockPoint = LocateLockPoint( pt_track->m_Start.x, pt_track->m_Start.y, masquelayer );
if( LockPoint )
{
pt_track->start = LockPoint;
if( LockPoint->Type() == TYPEPAD )
{ /* fin de piste sur un pad */
pt_pad = (D_PAD*) LockPoint;
pt_track->SetState( BEGIN_ONPAD, ON );
}
else /* debut de piste sur un segment de piste */
{
Track = (TRACK*) LockPoint;
CreateLockPoint( &pt_track->m_Start.x, &pt_track->m_Start.y, Track, pt_track );
}
}
/* Localisation de la pastille ou segment sur fin de segment: */
LockPoint = LocateLockPoint( pt_track->m_End.x, pt_track->m_End.y, masquelayer );
if( LockPoint )
{
pt_track->end = LockPoint;
if( LockPoint->Type() == TYPEPAD )
{ /* fin de piste sur un pad */
pt_pad = (D_PAD*) LockPoint;
pt_track->SetState( END_ONPAD, ON );
}
else /* debut de piste sur un segment de piste */
{
Track = (TRACK*) LockPoint;
CreateLockPoint( &pt_track->m_Start.x, &pt_track->m_Start.y, Track, pt_track );
}
}
}
/* Clear the BUSY flag */
ii = NbPtNewTrack; pt_track = NewTrack;
for( ; ii > 0; ii--, pt_track = (TRACK*) pt_track->Pnext )
{
pt_track->SetState( BUSY, OFF );
}
test_1_net_connexion( DC, new_net_code );
ActiveScreen->SetModify();
}
else /* DRC error: Annulation commande */
{
DisplayOpt.DisplayPcbTrackFill = FALSE;
Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_XOR );
DisplayOpt.DisplayPcbTrackFill = Track_fill_copy;
if( FlagState == MOVE_ROUTE )
{ /* Remise en position de la piste deplacee */
Track = NewTrack;
PosInitX -= Track->m_Start.x; PosInitY -= Track->m_Start.y;
for( ii = 0; ii < NbPtNewTrack; ii++, Track = (TRACK*) Track->Pnext )
{
if( Track == NULL )
break;
Track->m_Start.x += PosInitX; Track->m_Start.y += PosInitY;
Track->m_End.x += PosInitX; Track->m_End.y += PosInitY;
Track->SetState( BUSY, OFF );
}
Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_OR );
}
if( FlagState == COPY_ROUTE )
{ /* Suppression copie */
for( ii = 0; ii < NbPtNewTrack; NewTrack = NextS )
{
if( NewTrack == NULL )
break;
NextS = (TRACK*) NewTrack->Pnext;
delete NewTrack;
}
}
}
NewTrack = NULL;
Affiche_Infos_Status_Pcb( Cmd );
if( Etat_Surbrillance )
Hight_Light( DC );
}
/*******************************************************************************/
void WinEDA_PcbFrame::Start_CopyOrMove_Route( TRACK* track, wxDC* DC, bool Drag )
/*******************************************************************************/
/* Routine permettant la recopie d'une piste (suite de segments) deja tracee
*/
{
int ii;
TRACK* pt_segm, * pt_track;
int masquelayer = tab_layer[ActiveScreen->Active_Layer];
if( NewTrack )
return;
FlagState = (int) Cmd->Menu->param_inf;
/* Recherche de la piste sur la couche active (non zone) */
for( pt_segm = pt_pcb->Track; pt_segm != NULL; pt_segm = (TRACK*) pt_segm->Pnext )
{
pt_segm = Locate_Pistes( pt_segm, masquelayer, CURSEUR_OFF_GRILLE );
if( pt_segm == NULL )
break;
break;
}
if( pt_segm != NULL )
{
if( FlagState == COPY_ROUTE )
pt_track = Marque_Une_Piste( DC, pt_segm, &NbPtNewTrack, 0 );
else
pt_track = Marque_Une_Piste( DC, pt_segm, &NbPtNewTrack, GR_XOR );
if( NbPtNewTrack ) /* Il y a NbPtNewTrack segments de piste a traiter */
{
/* effacement du flag BUSY de la piste originelle */
ii = NbPtNewTrack; pt_segm = pt_track;
for( ; ii > 0; ii--, pt_segm = (TRACK*) pt_segm->Pnext )
{
pt_segm->SetState( BUSY, OFF );
}
if( FlagState == COPY_ROUTE )
NewTrack = pt_track->Copy( NbPtNewTrack );
else
NewTrack = pt_track;
Affiche_Infos_Piste( Cmd, pt_track );
startX = ActiveScreen->Curseur_X;
startY = ActiveScreen->Curseur_Y;
Place_Dupl_Route_Item.State = WAIT;
ActiveDrawPanel->ManageCurseur = Show_Move_Piste;
DisplayOpt.DisplayPcbTrackFill = FALSE;
Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_XOR );
DisplayOpt.DisplayPcbTrackFill = Track_fill_copy;
PosInitX = NewTrack->m_Start.x; PosInitY = NewTrack->m_Start.y;
}
}
}
#endif
......@@ -76,6 +76,43 @@ namespace DSN {
//-----<SPECCTRA_DB>-------------------------------------------------
void SPECCTRA_DB::buildLayerMaps( BOARD* aBoard )
{
// specctra wants top physical layer first, then going down to the
// bottom most physical layer in physical sequence.
// @question : why does Kicad not display layers in that order?
int layerCount = aBoard->GetCopperLayerCount();
layerIds.clear();
pcbLayer2kicad.resize( layerCount );
kicadLayer2pcb.resize( LAYER_CMP_N+1 );
for( int kiNdx=layerCount-1, pcbNdx=0; kiNdx >= 0; --kiNdx, ++pcbNdx )
{
int kilayer = kiNdx>0 && kiNdx==layerCount-1 ? LAYER_CMP_N : kiNdx;
// establish bi-directional mapping between kicad's BOARD layer and PCB layer
pcbLayer2kicad[pcbNdx] = kilayer;
kicadLayer2pcb[kilayer] = pcbNdx;
// save the specctra layer name in SPECCTRA_DB::layerIds for later.
layerIds.push_back( CONV_TO_UTF8( aBoard->GetLayerName( kilayer ) ) );
}
}
int SPECCTRA_DB::findLayerName( const std::string& aLayerName ) const
{
for( unsigned i=0; i<layerIds.size(); ++i )
{
if( 0 == aLayerName.compare( layerIds[i] ) )
return (int) i;
}
return -1;
}
void SPECCTRA_DB::ThrowIOError( const wxChar* fmt, ... ) throw( IOError )
{
wxString errText;
......
......@@ -3345,6 +3345,14 @@ public:
// delete test_points;
}
UNIT_RES* GetUnits() const
{
if( resolution )
return resolution;
return ELEM::GetUnits();
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
if( resolution )
......@@ -3521,8 +3529,27 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
/// maps PCB layer number to BOARD layer numbers
std::vector<int> pcbLayer2kicad;
/// used during FromSESSION() only, memory for it is not owned here.
UNIT_RES* routeResolution;
/// a copy to avoid passing as an argument, memory for it is not owned here.
BOARD* sessionBoard;
static const KICAD_T scanPADs[];
/**
* Function buildLayerMaps
* creates a few data translation structures for layer name and number
* mapping between the DSN::PCB structure and the kicad BOARD structure.
* @param aBoard The BOARD to create the maps for.
*/
void buildLayerMaps( BOARD* aBoard );
/**
* Function findLayerName
* returns the PCB layer index for a given layer name
*/
int findLayerName( const std::string& aLayerName ) const;
/**
* Function nextTok
......@@ -3698,6 +3725,17 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
*/
PADSTACK* makeVia( const SEGVIA* aVia );
//-----<FromSESSION>-----------------------------------------------------
/**
* Function makeTRACK
* creates a TRACK form the PATH and BOARD info.
*/
TRACK* makeTRACK( PATH* aPath, int aPointIndex, int aNetcode ) throw( IOError );
//-----</FromSESSION>----------------------------------------------------
public:
SPECCTRA_DB()
......
......@@ -701,27 +701,17 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
// specctra wants top physical layer first, then going down to the
// bottom most physical layer in physical sequence.
// @question : why does Kicad not display layers in that order?
int layerCount = aBoard->GetCopperLayerCount();
layerIds.clear();
pcbLayer2kicad.resize( layerCount );
kicadLayer2pcb.resize( LAYER_CMP_N+1 );
for( int kiNdx=layerCount-1, pcbNdx=0; kiNdx >= 0; --kiNdx, ++pcbNdx )
{
int kilayer = kiNdx>0 && kiNdx==layerCount-1 ? LAYER_CMP_N : kiNdx;
// establish bi-directional mapping between kicad's BOARD layer and PCB layer
pcbLayer2kicad[pcbNdx] = kilayer;
kicadLayer2pcb[kilayer] = pcbNdx;
buildLayerMaps( aBoard );
// save the specctra layer name in SPECCTRA_DB::layerIds for later.
layerIds.push_back( CONV_TO_UTF8( aBoard->GetLayerName( kilayer ) ) );
int layerCount = aBoard->GetCopperLayerCount();
for( int pcbNdx=0; pcbNdx<layerCount; ++pcbNdx )
{
LAYER* layer = new LAYER( pcb->structure );
pcb->structure->layers.push_back( layer );
layer->name = layerIds.back();
layer->name = layerIds[pcbNdx];
layer->properties.push_back( PROPERTY() );
PROPERTY* property = &layer->properties.back();
......
......@@ -110,32 +110,29 @@ void WinEDA_PcbFrame::ImportSpecctraSession( wxCommandEvent& event )
namespace DSN {
static wxPoint mapPt( const POINT& aPoint, UNIT_RES* aResolution )
static int scale( double distance, UNIT_RES* aResolution )
{
wxPoint ret;
double resValue = aResolution->GetValue();
double factor; // multiply this times units to get mils for Kicad.
double factor; // multiply this times session value to get mils for Kicad.
switch( aResolution->GetEngUnits() )
{
default:
case T_inch:
factor = 0.001;
factor = 1000.0;
break;
case T_mil:
factor = 1.0;
break;
case T_cm:
factor = 2.54/1000.0;
factor = 1000.0/2.54;
break;
case T_mm:
factor = 25.4/1000.0;
factor = 1000.0/25.4;
break;
case T_um:
factor = 25.4;
factor = 1.0/25.4;
break;
}
......@@ -143,19 +140,47 @@ static wxPoint mapPt( const POINT& aPoint, UNIT_RES* aResolution )
// used within Kicad.
factor *= 10.0;
ret.x = (int) (factor * aPoint.x / resValue);
ret.y = (int) -(factor * aPoint.y / resValue); // negate y coord
return (int) round(factor * distance / resValue);
}
static wxPoint mapPt( const POINT& aPoint, UNIT_RES* aResolution )
{
wxPoint ret( scale( aPoint.x, aResolution ),
-scale( aPoint.y, aResolution )); // negate y
return ret;
}
TRACK* SPECCTRA_DB::makeTRACK( PATH* aPath, int aPointIndex, int aNetcode ) throw( IOError )
{
int layerNdx = findLayerName( aPath->layer_id );
if( layerNdx == -1 )
{
wxString layerName = CONV_FROM_UTF8( aPath->layer_id.c_str() );
ThrowIOError( _("Session file uses invalid layer id \"%s\""),
layerName.GetData() );
}
TRACK* track = new TRACK( sessionBoard );
track->m_Start = mapPt( aPath->points[aPointIndex+0], routeResolution );
track->m_End = mapPt( aPath->points[aPointIndex+1], routeResolution );
track->SetLayer( pcbLayer2kicad[layerNdx] );
track->m_Width = scale( aPath->aperture_width, routeResolution );
track->SetNet( aNetcode );
return track;
}
// no UI code in this function, throw exception to report problems to the
// UI handler: void WinEDA_PcbFrame::ImportSpecctraSession( wxCommandEvent& event )
void SPECCTRA_DB::FromSESSION( BOARD* aBoard ) throw( IOError )
{
//wxASSERT( session );
sessionBoard = aBoard; // not owned here
if( !session )
ThrowIOError( _("Session file is missing the \"session\" section") );
......@@ -176,6 +201,8 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard ) throw( IOError )
aBoard->DeleteMARKERs();
buildLayerMaps( aBoard );
// Walk the PLACEMENT object's COMPONENTs list, and for each PLACE within
// each COMPONENT, reposition and re-orient each component and put on
// correct side of the board.
......@@ -235,13 +262,53 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard ) throw( IOError )
}
}
routeResolution = session->route->GetUnits();
// Walk the NET_OUTs and create tracks and vias anew.
NET_OUTS& net_outs = session->route->net_outs;
for( NET_OUTS::iterator i=net_outs.begin(); i!=net_outs.end(); ++i )
for( NET_OUTS::iterator net=net_outs.begin(); net!=net_outs.end(); ++net )
{
// create a track or via and position it.
wxString netName( CONV_FROM_UTF8( net->net_id.c_str() ) );
EQUIPOT* equipot = aBoard->FindNet( netName );
if( !equipot )
{
ThrowIOError( _("Session file uses invalid net::net_id \"%s\""),
netName.GetData() );
}
WIRES& wires = net->wires;
for( unsigned i=0; i<wires.size(); ++i )
{
WIRE* wire = &wires[i];
DSN_T shape = wire->shape->Type();
if( shape != T_path )
{
wxString netId = CONV_FROM_UTF8( wire->net_id.c_str() );
ThrowIOError(
_("Unsupported wire shape: \"%s\" for net: \"%s\""),
LEXER::GetTokenString(shape).GetData(),
netId.GetData()
);
}
PATH* path = (PATH*) wire->shape;
for( unsigned pt=0; pt<path->points.size()-1; ++pt )
{
TRACK* track = makeTRACK( path, pt, equipot->GetNet() );
TRACK* insertAid = track->GetBestInsertPoint( aBoard );
track->Insert( aBoard, insertAid );
}
}
WIRE_VIAS& wire_vias = net->wire_vias;
for( unsigned i=0; i<wire_vias.size(); ++i )
{
// WIRE_VIA* wire_via = &wire_vias[i];
}
}
}
......
/**************************************************/
/* Edition des pistes */
/* Routines de modification automatique de pistes */
/**************************************************/
/**************************************************/
/* Edition des pistes */
/* Routines de modification automatique de pistes */
/**************************************************/
#include "fctsys.h"
#include "gr_basic.h"
......@@ -12,201 +12,219 @@
#include "protos.h"
/*********************************************************************/
int EraseOldTrack(WinEDA_BasePcbFrame * frame, BOARD * Pcb, wxDC * DC,
TRACK * pt_new_track, int nbptnewpiste)
int EraseOldTrack( WinEDA_BasePcbFrame* frame, BOARD* Pcb, wxDC* DC,
TRACK* pt_new_track, int nbptnewpiste )
/*********************************************************************/
/* Routine d'effacement de la piste redondante a la piste nouvellement cree
pointee par pt_new_track (nbptnewpiste segments)
la piste cree est supposee constituee de segments contigus en memoire avec:
point de depart pt_newtrack->m_Start.x,y
point d'arrivee pt_newtrack->m_End.x,y
*/
/* Routine d'effacement de la piste redondante a la piste nouvellement cree
* pointee par pt_new_track (nbptnewpiste segments)
*
* la piste cree est supposee constituee de segments contigus en memoire avec:
* point de depart pt_newtrack->m_Start.x,y
* point d'arrivee pt_newtrack->m_End.x,y
*/
{
TRACK * StartTrack, * EndTrack; /* Pointeurs des segments de debut et fin
(extremites) de la nouvelle piste */
TRACK * EndNewTrack, /* Pointeur sur le dernier segment de la liste
chainee de la mouvelle piste */
* pt_segm, * pt_del;
int ii, jj, nb_segm, nbconnect;
wxPoint start; /* coord du point de depart de la piste */
wxPoint end; /* coord du point de fin de la piste */
int startmasklayer, endmasklayer; /* masque couche de depart et de fin */
TRACK * BufDeb, *BufEnd; /* Pointeurs de debut et de fin de la zone
des pistes equipotentielles */
/* Reconstitution de la piste complete ( la nouvelle piste
a pu demarrer sur un segment de piste en l'air */
ListSetState(pt_new_track,nbptnewpiste,BUSY,OFF);
/* si la novelle piste commence par une via, il est plus sur de rechercher
la piste complete en utilisant le segment suivant comme reference, car
une via est souvent sur un carrefour de segments, et ne caracterise pas
une piste */
if( pt_new_track->Type() == TYPEVIA && (nbptnewpiste > 1 ) )
pt_new_track = (TRACK *) pt_new_track->Pnext;
pt_new_track = Marque_Une_Piste(frame, DC, pt_new_track, &nbptnewpiste, 0);
EndNewTrack = pt_new_track;
for( ii = 1; ii < nbptnewpiste; ii++ )
{
EndNewTrack = (TRACK *) EndNewTrack->Pnext;
}
/* Calcul des limites de recherche des segments de piste */
/* BufDeb pointe le 1er segment utile */
BufDeb = Pcb->m_Track->GetStartNetCode(pt_new_track->GetNet());
/* BufEnd Pointe le dernier segment */
BufEnd = BufDeb->GetEndNetCode(pt_new_track->GetNet());
/* nettoyage des flags pour tout le net */
for(pt_del = BufDeb; pt_del != NULL; pt_del = (TRACK*)pt_del->Pnext)
{
pt_del->SetState(BUSY|EDIT|CHAIN, OFF);
if( pt_del == BufEnd ) break;
}
/* Calcul des points limites de la nouvelle piste */
if( ReturnEndsTrack(pt_new_track,nbptnewpiste,
&StartTrack, &EndTrack) == 0 ) return(0);
if( (StartTrack == NULL) || (EndTrack == NULL) ) return(0);
/* Calcul des caracteristiques des points de debut et de fin */
start = StartTrack->m_Start;
end = EndTrack->m_End;
/* Les points de depart et de fin doivent etre distincts */
if( start == end ) return(0);
/* Determinations des couches interconnectees a ces points */
startmasklayer = StartTrack->ReturnMaskLayer();
endmasklayer = EndTrack->ReturnMaskLayer();
/* Il peut y avoir une via ou un pad sur les extremites: */
pt_segm = Fast_Locate_Via(Pcb->m_Track, NULL, start, startmasklayer);
if( pt_segm ) startmasklayer |= pt_segm->ReturnMaskLayer();
if( StartTrack->start && (StartTrack->start->Type() == TYPEPAD) )
{ /* start sur pad */
D_PAD * pt_pad = (D_PAD*) (StartTrack->start) ;
startmasklayer |= pt_pad->m_Masque_Layer;
}
pt_segm = Fast_Locate_Via(Pcb->m_Track, NULL, end, endmasklayer);
if( pt_segm ) endmasklayer |= pt_segm->ReturnMaskLayer();
if( EndTrack->end && ( EndTrack->end->Type() == TYPEPAD) )
{
D_PAD * pt_pad = (D_PAD*) (EndTrack->end) ;
endmasklayer |= pt_pad->m_Masque_Layer;
}
/* Marquage a DELETED de la piste nouvelle (qui ne doit pas intervenir
dans la recherche d'autres connexions) */
ListSetState(pt_new_track, nbptnewpiste,DELETED,ON);
/* test : un segment doit etre connecte au point de depart car sinon
il est inutile d'analyser l'autre point */
pt_segm = Fast_Locate_Piste(BufDeb, BufEnd, start, startmasklayer);
if(pt_segm == NULL) /* Pas de piste reliee au point de depart */
{
/* Suppression du flag DELETED */
ListSetState(pt_new_track,nbptnewpiste, DELETED,OFF);
return(0);
}
/* Marquage a CHAIN des segments candidats connectes au point de fin
Remarque: les vias ne sont pas prises en compte car elles ne permettent
pas de definir une piste, puisque elles sont sur un carrefour */
for( pt_del = BufDeb, nbconnect = 0; ; )
{
pt_segm = Fast_Locate_Piste( pt_del,BufEnd, end, endmasklayer );
if( pt_segm == NULL) break;
if(pt_segm->Type() != TYPEVIA)
{ /* Segment trouve */
if( pt_segm->GetState(CHAIN) == 0 )
{
pt_segm->SetState(CHAIN,ON);
nbconnect++;
}
}
if( pt_del == BufEnd ) break;
pt_del = (TRACK*)pt_segm->Pnext;
}
if( nbconnect == 0)
{
/* nettoyage des flags */
for(pt_del = BufDeb; pt_del != NULL; pt_del = (TRACK*)pt_del->Pnext)
{
pt_del->SetState(DELETED|EDIT|CHAIN, OFF);
if( pt_del == BufEnd ) break;
}
return(0);
}
/* Marquage a EDIT de la piste nouvelle (qui ne doit pas intervenir
dans la recherche d'autres pistes) */
ListSetState(pt_new_track,nbptnewpiste, DELETED,OFF);
ListSetState(pt_new_track,nbptnewpiste, EDIT,ON);
/* Examen de tous les segments marques */
while( nbconnect )
{
for(pt_del = BufDeb; pt_del != NULL; pt_del = (TRACK*)pt_del->Pnext)
{
if( pt_del->GetState(CHAIN) ) break;
if( pt_del == BufEnd ) break;
}
nbconnect--; pt_del->SetState(CHAIN,OFF);
pt_del = Marque_Une_Piste(frame, DC, pt_del, &nb_segm, 0);
/* Test si La piste marquee est redondante, c'est a dire si l'un des
segments marques est connecte au point de depart de la piste nouvelle
*/
ii = 0; pt_segm = pt_del;
for( ;pt_segm && (ii < nb_segm); pt_segm = (TRACK*)pt_segm->Pnext, ii++)
{
if( (pt_segm->GetState(BUSY)) == 0 ) break;
if( (pt_segm->m_Start == start) || (pt_segm->m_End == start) )
{ /* la piste marquee peut etre effacee */
TRACK* NextS;
Trace_Une_Piste(frame->DrawPanel, DC, pt_del, nb_segm, GR_XOR|GR_SURBRILL);
for ( jj = 0; jj < nb_segm; jj++, pt_del = NextS)
{
NextS = (TRACK*) pt_del->Pnext;
pt_del->DeleteStructure();
}
/* nettoyage des flags */
for(pt_del = Pcb->m_Track; pt_del != NULL; pt_del = (TRACK*)pt_del->Pnext)
{
if (pt_del->GetState(EDIT) )
{
pt_del->SetState(EDIT, OFF);
pt_del->Draw(frame->DrawPanel, DC, GR_OR);
}
pt_del->SetState(EDIT|CHAIN, OFF);
}
return(1);
}
}
/* nettoyage du flag BUSY puisque ici la piste marquee n'a pas
ete retenuee */
ListSetState(pt_del, nb_segm, BUSY,OFF);
}
/* nettoyage des flags */
for(pt_del = Pcb->m_Track; pt_del != NULL; pt_del = (TRACK*)pt_del->Pnext)
{
pt_del->SetState(DELETED|EDIT|CHAIN, OFF);
if( pt_del == BufEnd ) break;
}
return(0);
TRACK* StartTrack, * EndTrack;/* Pointeurs des segments de debut et fin
* (extremites) de la nouvelle piste */
TRACK* EndNewTrack, /* Pointeur sur le dernier segment de la liste
* chainee de la mouvelle piste */
* pt_segm, * pt_del;
int ii, jj, nb_segm, nbconnect;
wxPoint start; /* coord du point de depart de la piste */
wxPoint end; /* coord du point de fin de la piste */
int startmasklayer, endmasklayer; /* masque couche de depart et de fin */
TRACK* BufDeb, * BufEnd; /* Pointeurs de debut et de fin de la zone
* des pistes equipotentielles */
/* Reconstitution de la piste complete ( la nouvelle piste
* a pu demarrer sur un segment de piste en l'air */
ListSetState( pt_new_track, nbptnewpiste, BUSY, OFF );
/* si la novelle piste commence par une via, il est plus sur de rechercher
* la piste complete en utilisant le segment suivant comme reference, car
* une via est souvent sur un carrefour de segments, et ne caracterise pas
* une piste */
if( pt_new_track->Type() == TYPEVIA && (nbptnewpiste > 1 ) )
pt_new_track = (TRACK*) pt_new_track->Pnext;
pt_new_track = Marque_Une_Piste( frame, DC, pt_new_track, &nbptnewpiste, 0 );
EndNewTrack = pt_new_track;
for( ii = 1; ii < nbptnewpiste; ii++ )
{
EndNewTrack = (TRACK*) EndNewTrack->Pnext;
}
/* Calcul des limites de recherche des segments de piste */
/* BufDeb pointe le 1er segment utile */
BufDeb = Pcb->m_Track->GetStartNetCode( pt_new_track->GetNet() );
/* BufEnd Pointe le dernier segment */
BufEnd = BufDeb->GetEndNetCode( pt_new_track->GetNet() );
/* nettoyage des flags pour tout le net */
for( pt_del = BufDeb; pt_del != NULL; pt_del = (TRACK*) pt_del->Pnext )
{
pt_del->SetState( BUSY | EDIT | CHAIN, OFF );
if( pt_del == BufEnd )
break;
}
/* Calcul des points limites de la nouvelle piste */
if( ReturnEndsTrack( pt_new_track, nbptnewpiste,
&StartTrack, &EndTrack ) == 0 )
return 0;
if( (StartTrack == NULL) || (EndTrack == NULL) )
return 0;
/* Calcul des caracteristiques des points de debut et de fin */
start = StartTrack->m_Start;
end = EndTrack->m_End;
/* Les points de depart et de fin doivent etre distincts */
if( start == end )
return 0;
/* Determinations des couches interconnectees a ces points */
startmasklayer = StartTrack->ReturnMaskLayer();
endmasklayer = EndTrack->ReturnMaskLayer();
/* Il peut y avoir une via ou un pad sur les extremites: */
pt_segm = Fast_Locate_Via( Pcb->m_Track, NULL, start, startmasklayer );
if( pt_segm )
startmasklayer |= pt_segm->ReturnMaskLayer();
if( StartTrack->start && (StartTrack->start->Type() == TYPEPAD) )
{ /* start sur pad */
D_PAD* pt_pad = (D_PAD*) (StartTrack->start);
startmasklayer |= pt_pad->m_Masque_Layer;
}
pt_segm = Fast_Locate_Via( Pcb->m_Track, NULL, end, endmasklayer );
if( pt_segm )
endmasklayer |= pt_segm->ReturnMaskLayer();
if( EndTrack->end && ( EndTrack->end->Type() == TYPEPAD) )
{
D_PAD* pt_pad = (D_PAD*) (EndTrack->end);
endmasklayer |= pt_pad->m_Masque_Layer;
}
/* Marquage a DELETED de la piste nouvelle (qui ne doit pas intervenir
* dans la recherche d'autres connexions) */
ListSetState( pt_new_track, nbptnewpiste, DELETED, ON );
/* test : un segment doit etre connecte au point de depart car sinon
* il est inutile d'analyser l'autre point */
pt_segm = Fast_Locate_Piste( BufDeb, BufEnd, start, startmasklayer );
if( pt_segm == NULL ) /* Pas de piste reliee au point de depart */
{
/* Suppression du flag DELETED */
ListSetState( pt_new_track, nbptnewpiste, DELETED, OFF );
return 0;
}
/* Marquage a CHAIN des segments candidats connectes au point de fin
* Remarque: les vias ne sont pas prises en compte car elles ne permettent
* pas de definir une piste, puisque elles sont sur un carrefour */
for( pt_del = BufDeb, nbconnect = 0; ; )
{
pt_segm = Fast_Locate_Piste( pt_del, BufEnd, end, endmasklayer );
if( pt_segm == NULL )
break;
if( pt_segm->Type() != TYPEVIA )
{ /* Segment trouve */
if( pt_segm->GetState( CHAIN ) == 0 )
{
pt_segm->SetState( CHAIN, ON );
nbconnect++;
}
}
if( pt_del == BufEnd )
break;
pt_del = (TRACK*) pt_segm->Pnext;
}
if( nbconnect == 0 )
{
/* nettoyage des flags */
for( pt_del = BufDeb; pt_del != NULL; pt_del = (TRACK*) pt_del->Pnext )
{
pt_del->SetState( DELETED | EDIT | CHAIN, OFF );
if( pt_del == BufEnd )
break;
}
return 0;
}
/* Marquage a EDIT de la piste nouvelle (qui ne doit pas intervenir
* dans la recherche d'autres pistes) */
ListSetState( pt_new_track, nbptnewpiste, DELETED, OFF );
ListSetState( pt_new_track, nbptnewpiste, EDIT, ON );
/* Examen de tous les segments marques */
while( nbconnect )
{
for( pt_del = BufDeb; pt_del != NULL; pt_del = (TRACK*) pt_del->Pnext )
{
if( pt_del->GetState( CHAIN ) )
break;
if( pt_del == BufEnd )
break;
}
nbconnect--; pt_del->SetState( CHAIN, OFF );
pt_del = Marque_Une_Piste( frame, DC, pt_del, &nb_segm, 0 );
/* Test si La piste marquee est redondante, c'est a dire si l'un des
* segments marques est connecte au point de depart de la piste nouvelle
*/
ii = 0; pt_segm = pt_del;
for( ; pt_segm && (ii < nb_segm); pt_segm = (TRACK*) pt_segm->Pnext, ii++ )
{
if( ( pt_segm->GetState( BUSY ) ) == 0 )
break;
if( (pt_segm->m_Start == start) || (pt_segm->m_End == start) )
{ /* la piste marquee peut etre effacee */
TRACK* NextS;
Trace_Une_Piste( frame->DrawPanel, DC, pt_del, nb_segm, GR_XOR | GR_SURBRILL );
for( jj = 0; jj < nb_segm; jj++, pt_del = NextS )
{
NextS = (TRACK*) pt_del->Pnext;
pt_del->DeleteStructure();
}
/* nettoyage des flags */
for( pt_del = Pcb->m_Track; pt_del != NULL; pt_del = (TRACK*) pt_del->Pnext )
{
if( pt_del->GetState( EDIT ) )
{
pt_del->SetState( EDIT, OFF );
pt_del->Draw( frame->DrawPanel, DC, GR_OR );
}
pt_del->SetState( EDIT | CHAIN, OFF );
}
return 1;
}
}
/* nettoyage du flag BUSY puisque ici la piste marquee n'a pas
* ete retenuee */
ListSetState( pt_del, nb_segm, BUSY, OFF );
}
/* nettoyage des flags */
for( pt_del = Pcb->m_Track; pt_del != NULL; pt_del = (TRACK*) pt_del->Pnext )
{
pt_del->SetState( DELETED | EDIT | CHAIN, OFF );
if( pt_del == BufEnd )
break;
}
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment