Commit b9f9d539 authored by dickelbeck's avatar dickelbeck
Browse files

more amazing free specctra software

parent 4a0b5607
Loading
Loading
Loading
Loading
+15 −0
Original line number Original line Diff line number Diff line
@@ -5,6 +5,21 @@ Started 2007-June-11
Please add newer entries at the top, list the date and your name with
Please add newer entries at the top, list the date and your name with
email address.
email address.


2008-Jan-29 UPDATE   Dick Hollenbeck <dick@softplc.com>
================================================================================
+pcbnew:
  SPECCTRA export now exports pads with offset OK, exports oval pads OK,
  and tries to do less with pcb edges that are not a connected set of lines,
  putting the burden back on the PCBNEW user to have clean perimeter lines.
  Discovered that freerouter does not support oval pads yet, asked 
  for enhancement.  Discovered a small problem if you modify a PAD in
  the MODULE editor but do not replicate that change throughout all module
  instances in the board.  Is on my @todo list.  Otherwise it is getting pretty 
  good now.  Most boards load into freerouter, except mine, which if exported
  with part numbers, hangs the freerouter!  I may be away for a few days doing
  billable work, after which I will begin the 2 imports, *.dsn and *.ses.
  

2008-Jan-31 UPDATE  Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
2008-Jan-31 UPDATE  Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================
================================================================================
+pcbnew:
+pcbnew:
+1 −1
Original line number Original line Diff line number Diff line
@@ -42,7 +42,7 @@
    Wide use is made of boost::ptr_vector<> and std::vector<> template classes.
    Wide use is made of boost::ptr_vector<> and std::vector<> template classes.
    If the contained object is small, then std::vector tends to be used.
    If the contained object is small, then std::vector tends to be used.
    If the contained object is large, variable size, or would require writing
    If the contained object is large, variable size, or would require writing
    an assignment operator() or copy constructore, then boost::ptr_vector
    an assignment operator() or copy constructor, then boost::ptr_vector
    cannot be beat.
    cannot be beat.
*/    
*/    


+6 −7
Original line number Original line Diff line number Diff line
@@ -695,19 +695,19 @@ public:
        
        
        const char* quote = out->GetQuoteChar( layer_id.c_str() );
        const char* quote = out->GetQuoteChar( layer_id.c_str() );
        
        
        const int RIGHTMARGIN = 80;        
        const int RIGHTMARGIN = 70;        
        int perLine = out->Print( nestLevel, "(%s %s%s%s %.6g", 
        int perLine = out->Print( nestLevel, "(%s %s%s%s %.6g", 
                               LEXER::GetTokenText( Type() ),
                               LEXER::GetTokenText( Type() ),
                               quote, layer_id.c_str(), quote, 
                               quote, layer_id.c_str(), quote, 
                               aperture_width );
                               aperture_width );


        int wrapNest = MAX( nestLevel+1, 6 );
        for( unsigned i=0;  i<points.size();  ++i )
        for( unsigned i=0;  i<points.size();  ++i )
        {
        {
            if( perLine > RIGHTMARGIN )
            if( perLine > RIGHTMARGIN )
            {
            {
                out->Print( 0, "\n" );
                out->Print( 0, "\n" );
                perLine = out->Print( nestLevel+1, "%s", "" );
                perLine = out->Print( wrapNest, "%s", "" );
                newline = "\n";
            }
            }
            else
            else
                perLine += out->Print( 0, "  " );
                perLine += out->Print( 0, "  " );
@@ -717,10 +717,9 @@ public:


        if( aperture_type == T_square )
        if( aperture_type == T_square )
        {
        {
            out->Print( 0, "\n" );
            out->Print( 0, "(aperture_type square)" );
            out->Print( nestLevel+1, "(aperture_type square))\n" );
        }
        }
        else
        
        out->Print( 0, ")%s", newline ); 
        out->Print( 0, ")%s", newline ); 
    }
    }
};
};
+160 −62
Original line number Original line Diff line number Diff line
@@ -74,6 +74,9 @@ void WinEDA_PcbFrame::ExportToSPECCTRA( wxCommandEvent& event )
    bool            ok = true;
    bool            ok = true;
    wxString        errorText;
    wxString        errorText;


    BASE_SCREEN*    screen = GetScreen();
    bool            wasModified = screen->IsModify() && !screen->IsSave();
    
    db.SetPCB( SPECCTRA_DB::MakePCB() );
    db.SetPCB( SPECCTRA_DB::MakePCB() );


    try 
    try 
@@ -92,6 +95,12 @@ void WinEDA_PcbFrame::ExportToSPECCTRA( wxCommandEvent& event )
        errorText = ioe.errorText;
        errorText = ioe.errorText;
    }
    }


    // The two calls below to BOARD::Change_Side_Module(), both set the 
    // modified flag, yet their actions cancel each other out, so it should 
    // be ok to clear the modify flag.
    if( !wasModified )
        screen->ClrModify();
    
    if( ok )
    if( ok )
    {
    {
        // @todo display a message saying the export is complete.
        // @todo display a message saying the export is complete.
@@ -105,8 +114,8 @@ namespace DSN {


struct POINT_PAIR
struct POINT_PAIR
{
{
    POINT       p1;         ///< start
    POINT       start;
    POINT       p2;         ///< end
    POINT       end;
    BOARD_ITEM* item;       ///< the item which has these points, TRACK or DRAWSEGMENT
    BOARD_ITEM* item;       ///< the item which has these points, TRACK or DRAWSEGMENT
};
};
typedef std::vector<POINT_PAIR>     POINT_PAIRS; 
typedef std::vector<POINT_PAIR>     POINT_PAIRS; 
@@ -114,9 +123,9 @@ typedef std::vector<POINT_PAIR> POINT_PAIRS;


static inline void swap( POINT_PAIR& pair )
static inline void swap( POINT_PAIR& pair )
{
{
    POINT temp = pair.p1;
    POINT temp = pair.start;
    pair.p1 = pair.p2;
    pair.start = pair.end;
    pair.p2 = temp;
    pair.end   = temp;
}
}




@@ -157,6 +166,31 @@ static POINT mapPt( const wxPoint& pt )
}
}




/**
 * Function findPOINT
 * searches the list of POINT_PAIRS for a matching end to the given POINT.
 * @return int - 0 if no match, or + one based index of a POINT_PAIR with a matching ".start",
 *              or a - one based index of a POINT_PAIR with a matching ".end".
 */
static int findPOINT( const POINT& pt, const POINT_PAIR source[], int count )
{
    for( int i=0;  i<count;  ++i )
    {
        if( pt == source[i].start )
        {
            return +( i + 1 ); 
        }
        
        if( pt == source[i].end )
        {
            return -( i + 1 ); 
        }
    }
    
    return 0;
}


/**
/**
 * Function swapEnds
 * Function swapEnds
 * will swap ends of any POINT_PAIR in the POINT_PAIRS list in order to
 * will swap ends of any POINT_PAIR in the POINT_PAIRS list in order to
@@ -164,23 +198,46 @@ static POINT mapPt( const wxPoint& pt )
 */
 */
static void swapEnds( POINT_PAIRS& aList )
static void swapEnds( POINT_PAIRS& aList )
{
{
    POINT   temp;
    if( !aList.size() )
    
    if( aList.size() <= 1 )
        return;
        return;
    
    
    for( unsigned i=0;  i<aList.size();  ++i )
    // do an extraction sort based on matching ends here.
    POINT_PAIRS sorted;
    POINT_PAIRS source( aList );

    // try and start the search using a POINT which has at least one match elsewhere.
    if( findPOINT( source.begin()->start, &source[1], source.size()-1 ) != 0 )
        swap( *source.begin() );        // swap start and end of first PAIR
    
    while( source.size() )
    {
    {
        if( aList[i].p1 == aList[i+1].p1 )
        sorted.push_back( *source.begin() );
            swap( aList[i] ); 
        source.erase( source.begin() );


        else if( aList[i].p1 == aList[i+1].p2 )
        // keep looping through the source list looking for a match to the end of the last sorted.        
        int result;
        while( (result = findPOINT( sorted.back().end, &source[0], source.size() ) ) != 0 )
        {
        {
            swap( aList[i] );
            int ndx = ABS(result)-1; 
            swap( aList[i+1] );
            sorted.push_back( source[ ndx ] );
            ++i;    // skip next one, we swapped i+1 here
            source.erase( source.begin()+ndx );
            
            if( result < 0 )
                swap( sorted.back() );
        }
        }
    }
    }
        
#if 1 && defined(DEBUG)
    printf( "swapEnds():\n" );
    for( unsigned i=0;  i<sorted.size();  ++i )
    {
        printf( "(%.6g,%.6g)  (%.6g,%.6g)\n", 
               sorted[i].start.x, sorted[i].start.y, 
               sorted[i].end.x,   sorted[i].end.y );
    }
#endif
    
    aList = sorted;
}
}




@@ -197,15 +254,15 @@ static bool isRectangle( POINT_PAIRS& aList )
        for( unsigned i=0;  i<aList.size();  ++i )
        for( unsigned i=0;  i<aList.size();  ++i )
        {
        {
            if( i < aList.size()-1 )
            if( i < aList.size()-1 )
                if( aList[i].p2 != aList[i+1].p1 )
                if( aList[i].end != aList[i+1].start )
                    return false;
                    return false;
            
            
            if( aList[i].p1.x != aList[i].p2.x 
            if( aList[i].start.x != aList[i].end.x 
            &&  aList[i].p1.y != aList[i].p2.y )
            &&  aList[i].start.y != aList[i].end.y )
                return false;
                return false;
        }
        }
        
        
        return ( aList[0].p1 == aList[3].p2 );
        return ( aList[0].start == aList[3].end );
    }
    }
    return false;
    return false;
}
}
@@ -316,7 +373,11 @@ IMAGE* SPECCTRA_DB::makeIMAGE( MODULE* aModule )
            
            
            pin->padstack_id = padstack->padstack_id;
            pin->padstack_id = padstack->padstack_id;
            pin->pin_id      = CONV_TO_UTF8( pad->ReturnStringPadName() );
            pin->pin_id      = CONV_TO_UTF8( pad->ReturnStringPadName() );
            pin->SetVertex( mapPt( pad->m_Pos0 ) );
            
            // copper shape's position is hole position + offset
            wxPoint pos = pad->m_Pos0 + pad->m_Offset;
            
            pin->SetVertex( mapPt( pos )  );
        }
        }
    }
    }
    
    
@@ -421,14 +482,6 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads )
        // padstacks.size()-1 is the index of the matching padstack in LIBRARY::padstacks
        // padstacks.size()-1 is the index of the matching padstack in LIBRARY::padstacks
        pad->m_logical_connexion = pcb->library->padstacks.size()-1;
        pad->m_logical_connexion = pcb->library->padstacks.size()-1;
        
        
        // paddOfset is the offset of copper shape relative to hole position, 
        // and pad->m_Pos is hole position. All shapes must be shifted by
        // this distance, normally (0,0).
        
        // Note that the y correction here is set negative.
        POINT       padOffset( scale(pad->m_Offset.x), -scale(pad->m_Offset.y) );

        
        // For now, we will report only one layer for the pads.  SMD pads are reported on the
        // For now, we will report only one layer for the pads.  SMD pads are reported on the
        // top layer, and through hole are reported on <reserved_layer_name> "signal".
        // top layer, and through hole are reported on <reserved_layer_name> "signal".
        // We could do better if there was actually a "layer type" field within 
        // We could do better if there was actually a "layer type" field within 
@@ -462,7 +515,6 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads )
                        
                        
                        circle->SetLayerId( layerName );
                        circle->SetLayerId( layerName );
                        circle->SetDiameter( diameter );
                        circle->SetDiameter( diameter );
                        circle->SetVertex( padOffset );
                        ++coppers;
                        ++coppers;
                    }
                    }
                }
                }
@@ -486,9 +538,6 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads )
                POINT   lowerLeft( -dx, -dy );
                POINT   lowerLeft( -dx, -dy );
                POINT   upperRight( dx, dy );
                POINT   upperRight( dx, dy );


                lowerLeft  += padOffset;
                upperRight += padOffset;

                for( int layer=0;  layer<reportedLayers;  ++layer )
                for( int layer=0;  layer<reportedLayers;  ++layer )
                {
                {
                    if( doLayer[layer] )
                    if( doLayer[layer] )
@@ -540,38 +589,55 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads )
                            shape = new SHAPE( padstack );
                            shape = new SHAPE( padstack );
                            padstack->Append( shape );
                            padstack->Append( shape );
                            path = makePath( 
                            path = makePath( 
                                    POINT( -dr + padOffset.x, padOffset.y - radius ),     // aStart
                                    POINT( -dr, -radius ),      // aStart
                                    POINT(  dr + padOffset.x, padOffset.y - radius ),     // aEnd
                                    POINT(  dr, -radius ),      // aEnd
                                    layerName );
                                    layerName );
                            shape->SetShape( path );
                            shape->SetShape( path );
                            
                            
                            shape = new SHAPE( padstack );
                            shape = new SHAPE( padstack );
                            padstack->Append( shape );
                            padstack->Append( shape );
                            // @todo: this 1/2 circle arc needs to be split into two quarter circle arcs 
                            qarc = makeArc( 
                            qarc = makeArc( 
                                    POINT(  dr + padOffset.x, padOffset.y - radius),      // aStart
                                    POINT(  dr, -radius),       // aStart
                                    POINT(  dr + padOffset.x, padOffset.y + radius),      // aEnd
                                    POINT(  dr, 0.0 ),          // aEnd
                                    POINT(  dr + padOffset.x, padOffset.y ),              // aCenter
                                    POINT(  dr, 0.0 ),          // aCenter
                                    layerName );
                            shape->SetShape( qarc );
    
                            shape = new SHAPE( padstack );
                            padstack->Append( shape );
                            qarc = makeArc( 
                                    POINT(  dr, 0.0),           // aStart
                                    POINT(  dr, radius),        // aEnd
                                    POINT(  dr, 0.0 ),          // aCenter
                                    layerName );
                                    layerName );
                            shape->SetShape( qarc );
                            shape->SetShape( qarc );
    
    
                            shape = new SHAPE( padstack );
                            shape = new SHAPE( padstack );
                            padstack->Append( shape );
                            padstack->Append( shape );
                            path = makePath( 
                            path = makePath( 
                                    POINT(  dr + padOffset.x, padOffset.y + radius ),     // aStart
                                    POINT(  dr,  radius ),      // aStart
                                    POINT( -dr + padOffset.x, padOffset.y + radius ),     // aEnd
                                    POINT( -dr,  radius ),      // aEnd
                                    layerName );
                                    layerName );
                            shape->SetShape( path );
                            shape->SetShape( path );
    
    
                            shape = new SHAPE( padstack );
                            shape = new SHAPE( padstack );
                            padstack->Append( shape );
                            padstack->Append( shape );
                            // @todo: this 1/2 circle arc needs to be split into two quarter circle arcs 
                            qarc = makeArc( 
                            qarc = makeArc( 
                                    POINT( -dr + padOffset.x, padOffset.y + radius),      // aStart
                                    POINT( -dr, radius),        // aStart
                                    POINT( -dr + padOffset.x, padOffset.y - radius),      // aEnd
                                    POINT( -dr, 0.0),           // aEnd
                                    POINT( -dr + padOffset.x, padOffset.y ),              // aCenter
                                    POINT( -dr, 0.0 ),          // aCenter
                                    layerName );
                                    layerName );
                            shape->SetShape( qarc );
                            shape->SetShape( qarc );
                            
                            shape = new SHAPE( padstack );
                            padstack->Append( shape );
                            qarc = makeArc( 
                                    POINT( -dr, 0.0),           // aStart
                                    POINT( -dr, -radius),       // aEnd
                                    POINT( -dr, 0.0 ),          // aCenter
                                    layerName );
                            shape->SetShape( qarc );
                            
                            ++coppers;
                            ++coppers;
                        }
                        }
                    }
                    }
@@ -595,38 +661,55 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads )
                            shape = new SHAPE( padstack );
                            shape = new SHAPE( padstack );
                            padstack->Append( shape );
                            padstack->Append( shape );
                            path = makePath( 
                            path = makePath( 
                                    POINT( -radius + padOffset.x, padOffset.y - dr ),   // aStart
                                    POINT( -radius, -dr ),      // aStart
                                    POINT( -radius + padOffset.x, padOffset.y + dr ),   // aEnd
                                    POINT( -radius,  dr ),      // aEnd
                                    layerName );
                                    layerName );
                            shape->SetShape( path );
                            shape->SetShape( path );
    
    
                            shape = new SHAPE( padstack );
                            shape = new SHAPE( padstack );
                            padstack->Append( shape );
                            padstack->Append( shape );
                            // @todo: this 1/2 circle arc needs to be split into two quarter circle arcs 
                            qarc = makeArc( 
                            qarc = makeArc( 
                                    POINT( -radius + padOffset.x, padOffset.y + dr ),   // aStart
                                    POINT( -radius, dr ),       // aStart
                                    POINT(  radius + padOffset.x, padOffset.y + dr),    // aEnd
                                    POINT(  0.0,    dy ),       // aEnd
                                    POINT(  padOffset.x, padOffset.y +dr ),             // aCenter
                                    POINT(  0.0,    dr ),       // aCenter
                                    layerName );
                            shape->SetShape( qarc );
    
                            shape = new SHAPE( padstack );
                            padstack->Append( shape );
                            qarc = makeArc( 
                                    POINT(  0.0,    dy ),       // aStart
                                    POINT(  radius, dr),        // aEnd
                                    POINT(  0.0,    dr ),       // aCenter
                                    layerName );
                                    layerName );
                            shape->SetShape( qarc );
                            shape->SetShape( qarc );
    
    
                            shape = new SHAPE( padstack );
                            shape = new SHAPE( padstack );
                            padstack->Append( shape );
                            padstack->Append( shape );
                            path = makePath( 
                            path = makePath( 
                                    POINT(  radius + padOffset.x, padOffset.y + dr ),   // aStart
                                    POINT(  radius,  dr ),      // aStart
                                    POINT(  radius + padOffset.x, padOffset.y - dr ),   // aEnd
                                    POINT(  radius, -dr ),      // aEnd
                                    layerName );
                                    layerName );
                            shape->SetShape( path );
                            shape->SetShape( path );
    
    
                            shape = new SHAPE( padstack );
                            shape = new SHAPE( padstack );
                            padstack->Append( shape );
                            padstack->Append( shape );
                            // @todo: this 1/2 circle arc needs to be split into two quarter circle arcs 
                            qarc = makeArc( 
                            qarc = makeArc( 
                                    POINT(  radius + padOffset.x, padOffset.y - dr),    // aStart
                                    POINT( radius, -dr ),       // aStart
                                    POINT( -radius + padOffset.x, padOffset.y - dr),    // aEnd
                                    POINT( 0.0,    -dy ),       // aEnd
                                    POINT( padOffset.x, padOffset.y - dr ),             // aCenter
                                    POINT( 0.0,    -dr ),       // aCenter
                                    layerName );
                                    layerName );
                            shape->SetShape( qarc );
                            shape->SetShape( qarc );
                            
                            shape = new SHAPE( padstack );
                            padstack->Append( shape );
                            qarc = makeArc( 
                                    POINT(  0.0,    -dy ),      // aStart
                                    POINT( -radius, -dr ),      // aEnd
                                    POINT( 0.0,     -dr ),      // aCenter
                                    layerName );
                            shape->SetShape( qarc );
                            
                            ++coppers;
                            ++coppers;
                        }
                        }
                    }
                    }
@@ -774,8 +857,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
            
            
            if( item->GetLayer() == EDGE_N )
            if( item->GetLayer() == EDGE_N )
            {
            {
                pair.p1 = mapPt( item->m_Start );
                pair.start = mapPt( item->m_Start );
                pair.p2 = mapPt( item->m_End );
                pair.end = mapPt( item->m_End );
                pair.item = item;
                pair.item = item;
                ppairs.push_back( pair );
                ppairs.push_back( pair );
                haveEdges = true;
                haveEdges = true;
@@ -802,12 +885,14 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
                rect->layer_id = "pcb";
                rect->layer_id = "pcb";
                
                
                // opposite corners
                // opposite corners
                rect->SetCorners( ppairs[0].p1, ppairs[2].p1 );
                rect->SetCorners( ppairs[0].start, ppairs[2].start );
                
                
                boundary->rectangle = rect;
                boundary->rectangle = rect;
            }
            }
            else
            else
            {
            {
#if 0           // PCBNEW user's edges are rarely this clean, let the router figure 
                // out the mess by using code at #else below.             
                PATH*  path = new PATH( boundary );
                PATH*  path = new PATH( boundary );
                
                
                path->layer_id = "pcb";
                path->layer_id = "pcb";
@@ -815,10 +900,21 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
                {
                {
                    // unless its a closed polygon, this probably won't work,
                    // unless its a closed polygon, this probably won't work,
                    // otherwise it will.
                    // otherwise it will.
                    path->points.push_back( ppairs[i].p1 );
                    path->points.push_back( ppairs[i].start );
                }
                }
                
                
                boundary->paths.push_back( path );
                boundary->paths.push_back( path );
#else   
                for( unsigned i=0;  i<ppairs.size();  ++i )
                {
                    PATH*  path = new PATH( boundary );
                    boundary->paths.push_back( path );
                    
                    path->layer_id = "pcb";
                    path->points.push_back( ppairs[i].start );
                    path->points.push_back( ppairs[i].end );
                }
#endif
            }
            }
    
    
            pcb->structure->SetBOUNDARY( boundary );
            pcb->structure->SetBOUNDARY( boundary );
@@ -960,6 +1056,10 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
                delete image;
                delete image;
            }
            }


            // @todo: this only works if the user has not modified the MODULE within the PCB
            // and made it different from what is in the PCBNEW library.  Need to test
            // each image for uniqueness, not just based on name as is done here:
            
            COMPONENT* comp = pcb->placement->LookupCOMPONENT( registered->image_id );
            COMPONENT* comp = pcb->placement->LookupCOMPONENT( registered->image_id );
            
            
            PLACE* place = new PLACE( comp );
            PLACE* place = new PLACE( comp );
@@ -968,8 +1068,6 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
            place->SetRotation( module->m_Orient/10.0 );
            place->SetRotation( module->m_Orient/10.0 );
            place->SetVertex( mapPt( module->m_Pos ) );
            place->SetVertex( mapPt( module->m_Pos ) );
            place->component_id = CONV_TO_UTF8( module->GetReference() );
            place->component_id = CONV_TO_UTF8( module->GetReference() );
            
            // not supported by freerouting.net yet:
            place->part_number  = CONV_TO_UTF8( module->GetValue() );
            place->part_number  = CONV_TO_UTF8( module->GetValue() );
            
            
            // module is flipped from bottom side, set side to T_back
            // module is flipped from bottom side, set side to T_back