Loading change_log.txt +15 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,21 @@ Started 2007-June-11 Please add newer entries at the top, list the date and your name with 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> ================================================================================ +pcbnew: Loading pcbnew/specctra.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ 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 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. */ Loading pcbnew/specctra.h +6 −7 Original line number Diff line number Diff line Loading @@ -695,19 +695,19 @@ public: 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", LEXER::GetTokenText( Type() ), quote, layer_id.c_str(), quote, aperture_width ); int wrapNest = MAX( nestLevel+1, 6 ); for( unsigned i=0; i<points.size(); ++i ) { if( perLine > RIGHTMARGIN ) { out->Print( 0, "\n" ); perLine = out->Print( nestLevel+1, "%s", "" ); newline = "\n"; perLine = out->Print( wrapNest, "%s", "" ); } else perLine += out->Print( 0, " " ); Loading @@ -717,10 +717,9 @@ public: if( aperture_type == T_square ) { out->Print( 0, "\n" ); out->Print( nestLevel+1, "(aperture_type square))\n" ); out->Print( 0, "(aperture_type square)" ); } else out->Print( 0, ")%s", newline ); } }; Loading pcbnew/specctra_export.cpp +160 −62 Original line number Diff line number Diff line Loading @@ -74,6 +74,9 @@ void WinEDA_PcbFrame::ExportToSPECCTRA( wxCommandEvent& event ) bool ok = true; wxString errorText; BASE_SCREEN* screen = GetScreen(); bool wasModified = screen->IsModify() && !screen->IsSave(); db.SetPCB( SPECCTRA_DB::MakePCB() ); try Loading @@ -92,6 +95,12 @@ void WinEDA_PcbFrame::ExportToSPECCTRA( wxCommandEvent& event ) 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 ) { // @todo display a message saying the export is complete. Loading @@ -105,8 +114,8 @@ namespace DSN { struct POINT_PAIR { POINT p1; ///< start POINT p2; ///< end POINT start; POINT end; BOARD_ITEM* item; ///< the item which has these points, TRACK or DRAWSEGMENT }; typedef std::vector<POINT_PAIR> POINT_PAIRS; Loading @@ -114,9 +123,9 @@ typedef std::vector<POINT_PAIR> POINT_PAIRS; static inline void swap( POINT_PAIR& pair ) { POINT temp = pair.p1; pair.p1 = pair.p2; pair.p2 = temp; POINT temp = pair.start; pair.start = pair.end; pair.end = temp; } Loading Loading @@ -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 * will swap ends of any POINT_PAIR in the POINT_PAIRS list in order to Loading @@ -164,23 +198,46 @@ static POINT mapPt( const wxPoint& pt ) */ static void swapEnds( POINT_PAIRS& aList ) { POINT temp; if( aList.size() <= 1 ) if( !aList.size() ) 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 ) swap( aList[i] ); sorted.push_back( *source.begin() ); 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] ); swap( aList[i+1] ); ++i; // skip next one, we swapped i+1 here int ndx = ABS(result)-1; sorted.push_back( source[ ndx ] ); 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; } Loading @@ -197,15 +254,15 @@ static bool isRectangle( POINT_PAIRS& aList ) for( unsigned i=0; i<aList.size(); ++i ) { if( i < aList.size()-1 ) if( aList[i].p2 != aList[i+1].p1 ) if( aList[i].end != aList[i+1].start ) return false; if( aList[i].p1.x != aList[i].p2.x && aList[i].p1.y != aList[i].p2.y ) if( aList[i].start.x != aList[i].end.x && aList[i].start.y != aList[i].end.y ) return false; } return ( aList[0].p1 == aList[3].p2 ); return ( aList[0].start == aList[3].end ); } return false; } Loading Loading @@ -316,7 +373,11 @@ IMAGE* SPECCTRA_DB::makeIMAGE( MODULE* aModule ) pin->padstack_id = padstack->padstack_id; 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 ) ); } } Loading Loading @@ -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 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 // 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 Loading Loading @@ -462,7 +515,6 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads ) circle->SetLayerId( layerName ); circle->SetDiameter( diameter ); circle->SetVertex( padOffset ); ++coppers; } } Loading @@ -486,9 +538,6 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads ) POINT lowerLeft( -dx, -dy ); POINT upperRight( dx, dy ); lowerLeft += padOffset; upperRight += padOffset; for( int layer=0; layer<reportedLayers; ++layer ) { if( doLayer[layer] ) Loading Loading @@ -540,38 +589,55 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads ) shape = new SHAPE( padstack ); padstack->Append( shape ); path = makePath( POINT( -dr + padOffset.x, padOffset.y - radius ), // aStart POINT( dr + padOffset.x, padOffset.y - radius ), // aEnd POINT( -dr, -radius ), // aStart POINT( dr, -radius ), // aEnd layerName ); shape->SetShape( path ); shape = new SHAPE( padstack ); padstack->Append( shape ); // @todo: this 1/2 circle arc needs to be split into two quarter circle arcs qarc = makeArc( POINT( dr + padOffset.x, padOffset.y - radius), // aStart POINT( dr + padOffset.x, padOffset.y + radius), // aEnd POINT( dr + padOffset.x, padOffset.y ), // aCenter POINT( dr, -radius), // aStart POINT( dr, 0.0 ), // aEnd 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 ); shape->SetShape( qarc ); shape = new SHAPE( padstack ); padstack->Append( shape ); path = makePath( POINT( dr + padOffset.x, padOffset.y + radius ), // aStart POINT( -dr + padOffset.x, padOffset.y + radius ), // aEnd POINT( dr, radius ), // aStart POINT( -dr, radius ), // aEnd layerName ); shape->SetShape( path ); shape = new SHAPE( padstack ); padstack->Append( shape ); // @todo: this 1/2 circle arc needs to be split into two quarter circle arcs qarc = makeArc( POINT( -dr + padOffset.x, padOffset.y + radius), // aStart POINT( -dr + padOffset.x, padOffset.y - radius), // aEnd POINT( -dr + padOffset.x, padOffset.y ), // aCenter POINT( -dr, radius), // aStart POINT( -dr, 0.0), // aEnd 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 ); shape->SetShape( qarc ); ++coppers; } } Loading @@ -595,38 +661,55 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads ) shape = new SHAPE( padstack ); padstack->Append( shape ); path = makePath( POINT( -radius + padOffset.x, padOffset.y - dr ), // aStart POINT( -radius + padOffset.x, padOffset.y + dr ), // aEnd POINT( -radius, -dr ), // aStart POINT( -radius, dr ), // aEnd layerName ); shape->SetShape( path ); shape = new SHAPE( padstack ); padstack->Append( shape ); // @todo: this 1/2 circle arc needs to be split into two quarter circle arcs qarc = makeArc( POINT( -radius + padOffset.x, padOffset.y + dr ), // aStart POINT( radius + padOffset.x, padOffset.y + dr), // aEnd POINT( padOffset.x, padOffset.y +dr ), // aCenter POINT( -radius, dr ), // aStart POINT( 0.0, dy ), // aEnd 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 ); shape->SetShape( qarc ); shape = new SHAPE( padstack ); padstack->Append( shape ); path = makePath( POINT( radius + padOffset.x, padOffset.y + dr ), // aStart POINT( radius + padOffset.x, padOffset.y - dr ), // aEnd POINT( radius, dr ), // aStart POINT( radius, -dr ), // aEnd layerName ); shape->SetShape( path ); shape = new SHAPE( padstack ); padstack->Append( shape ); // @todo: this 1/2 circle arc needs to be split into two quarter circle arcs qarc = makeArc( POINT( radius + padOffset.x, padOffset.y - dr), // aStart POINT( -radius + padOffset.x, padOffset.y - dr), // aEnd POINT( padOffset.x, padOffset.y - dr ), // aCenter POINT( radius, -dr ), // aStart POINT( 0.0, -dy ), // aEnd 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 ); shape->SetShape( qarc ); ++coppers; } } Loading Loading @@ -774,8 +857,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) if( item->GetLayer() == EDGE_N ) { pair.p1 = mapPt( item->m_Start ); pair.p2 = mapPt( item->m_End ); pair.start = mapPt( item->m_Start ); pair.end = mapPt( item->m_End ); pair.item = item; ppairs.push_back( pair ); haveEdges = true; Loading @@ -802,12 +885,14 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) rect->layer_id = "pcb"; // opposite corners rect->SetCorners( ppairs[0].p1, ppairs[2].p1 ); rect->SetCorners( ppairs[0].start, ppairs[2].start ); boundary->rectangle = rect; } 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->layer_id = "pcb"; Loading @@ -815,10 +900,21 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) { // unless its a closed polygon, this probably won't work, // otherwise it will. path->points.push_back( ppairs[i].p1 ); path->points.push_back( ppairs[i].start ); } 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 ); Loading Loading @@ -960,6 +1056,10 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) 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 ); PLACE* place = new PLACE( comp ); Loading @@ -968,8 +1068,6 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) place->SetRotation( module->m_Orient/10.0 ); place->SetVertex( mapPt( module->m_Pos ) ); place->component_id = CONV_TO_UTF8( module->GetReference() ); // not supported by freerouting.net yet: place->part_number = CONV_TO_UTF8( module->GetValue() ); // module is flipped from bottom side, set side to T_back Loading Loading
change_log.txt +15 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,21 @@ Started 2007-June-11 Please add newer entries at the top, list the date and your name with 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> ================================================================================ +pcbnew: Loading
pcbnew/specctra.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ 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 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. */ Loading
pcbnew/specctra.h +6 −7 Original line number Diff line number Diff line Loading @@ -695,19 +695,19 @@ public: 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", LEXER::GetTokenText( Type() ), quote, layer_id.c_str(), quote, aperture_width ); int wrapNest = MAX( nestLevel+1, 6 ); for( unsigned i=0; i<points.size(); ++i ) { if( perLine > RIGHTMARGIN ) { out->Print( 0, "\n" ); perLine = out->Print( nestLevel+1, "%s", "" ); newline = "\n"; perLine = out->Print( wrapNest, "%s", "" ); } else perLine += out->Print( 0, " " ); Loading @@ -717,10 +717,9 @@ public: if( aperture_type == T_square ) { out->Print( 0, "\n" ); out->Print( nestLevel+1, "(aperture_type square))\n" ); out->Print( 0, "(aperture_type square)" ); } else out->Print( 0, ")%s", newline ); } }; Loading
pcbnew/specctra_export.cpp +160 −62 Original line number Diff line number Diff line Loading @@ -74,6 +74,9 @@ void WinEDA_PcbFrame::ExportToSPECCTRA( wxCommandEvent& event ) bool ok = true; wxString errorText; BASE_SCREEN* screen = GetScreen(); bool wasModified = screen->IsModify() && !screen->IsSave(); db.SetPCB( SPECCTRA_DB::MakePCB() ); try Loading @@ -92,6 +95,12 @@ void WinEDA_PcbFrame::ExportToSPECCTRA( wxCommandEvent& event ) 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 ) { // @todo display a message saying the export is complete. Loading @@ -105,8 +114,8 @@ namespace DSN { struct POINT_PAIR { POINT p1; ///< start POINT p2; ///< end POINT start; POINT end; BOARD_ITEM* item; ///< the item which has these points, TRACK or DRAWSEGMENT }; typedef std::vector<POINT_PAIR> POINT_PAIRS; Loading @@ -114,9 +123,9 @@ typedef std::vector<POINT_PAIR> POINT_PAIRS; static inline void swap( POINT_PAIR& pair ) { POINT temp = pair.p1; pair.p1 = pair.p2; pair.p2 = temp; POINT temp = pair.start; pair.start = pair.end; pair.end = temp; } Loading Loading @@ -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 * will swap ends of any POINT_PAIR in the POINT_PAIRS list in order to Loading @@ -164,23 +198,46 @@ static POINT mapPt( const wxPoint& pt ) */ static void swapEnds( POINT_PAIRS& aList ) { POINT temp; if( aList.size() <= 1 ) if( !aList.size() ) 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 ) swap( aList[i] ); sorted.push_back( *source.begin() ); 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] ); swap( aList[i+1] ); ++i; // skip next one, we swapped i+1 here int ndx = ABS(result)-1; sorted.push_back( source[ ndx ] ); 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; } Loading @@ -197,15 +254,15 @@ static bool isRectangle( POINT_PAIRS& aList ) for( unsigned i=0; i<aList.size(); ++i ) { if( i < aList.size()-1 ) if( aList[i].p2 != aList[i+1].p1 ) if( aList[i].end != aList[i+1].start ) return false; if( aList[i].p1.x != aList[i].p2.x && aList[i].p1.y != aList[i].p2.y ) if( aList[i].start.x != aList[i].end.x && aList[i].start.y != aList[i].end.y ) return false; } return ( aList[0].p1 == aList[3].p2 ); return ( aList[0].start == aList[3].end ); } return false; } Loading Loading @@ -316,7 +373,11 @@ IMAGE* SPECCTRA_DB::makeIMAGE( MODULE* aModule ) pin->padstack_id = padstack->padstack_id; 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 ) ); } } Loading Loading @@ -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 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 // 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 Loading Loading @@ -462,7 +515,6 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads ) circle->SetLayerId( layerName ); circle->SetDiameter( diameter ); circle->SetVertex( padOffset ); ++coppers; } } Loading @@ -486,9 +538,6 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads ) POINT lowerLeft( -dx, -dy ); POINT upperRight( dx, dy ); lowerLeft += padOffset; upperRight += padOffset; for( int layer=0; layer<reportedLayers; ++layer ) { if( doLayer[layer] ) Loading Loading @@ -540,38 +589,55 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads ) shape = new SHAPE( padstack ); padstack->Append( shape ); path = makePath( POINT( -dr + padOffset.x, padOffset.y - radius ), // aStart POINT( dr + padOffset.x, padOffset.y - radius ), // aEnd POINT( -dr, -radius ), // aStart POINT( dr, -radius ), // aEnd layerName ); shape->SetShape( path ); shape = new SHAPE( padstack ); padstack->Append( shape ); // @todo: this 1/2 circle arc needs to be split into two quarter circle arcs qarc = makeArc( POINT( dr + padOffset.x, padOffset.y - radius), // aStart POINT( dr + padOffset.x, padOffset.y + radius), // aEnd POINT( dr + padOffset.x, padOffset.y ), // aCenter POINT( dr, -radius), // aStart POINT( dr, 0.0 ), // aEnd 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 ); shape->SetShape( qarc ); shape = new SHAPE( padstack ); padstack->Append( shape ); path = makePath( POINT( dr + padOffset.x, padOffset.y + radius ), // aStart POINT( -dr + padOffset.x, padOffset.y + radius ), // aEnd POINT( dr, radius ), // aStart POINT( -dr, radius ), // aEnd layerName ); shape->SetShape( path ); shape = new SHAPE( padstack ); padstack->Append( shape ); // @todo: this 1/2 circle arc needs to be split into two quarter circle arcs qarc = makeArc( POINT( -dr + padOffset.x, padOffset.y + radius), // aStart POINT( -dr + padOffset.x, padOffset.y - radius), // aEnd POINT( -dr + padOffset.x, padOffset.y ), // aCenter POINT( -dr, radius), // aStart POINT( -dr, 0.0), // aEnd 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 ); shape->SetShape( qarc ); ++coppers; } } Loading @@ -595,38 +661,55 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads ) shape = new SHAPE( padstack ); padstack->Append( shape ); path = makePath( POINT( -radius + padOffset.x, padOffset.y - dr ), // aStart POINT( -radius + padOffset.x, padOffset.y + dr ), // aEnd POINT( -radius, -dr ), // aStart POINT( -radius, dr ), // aEnd layerName ); shape->SetShape( path ); shape = new SHAPE( padstack ); padstack->Append( shape ); // @todo: this 1/2 circle arc needs to be split into two quarter circle arcs qarc = makeArc( POINT( -radius + padOffset.x, padOffset.y + dr ), // aStart POINT( radius + padOffset.x, padOffset.y + dr), // aEnd POINT( padOffset.x, padOffset.y +dr ), // aCenter POINT( -radius, dr ), // aStart POINT( 0.0, dy ), // aEnd 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 ); shape->SetShape( qarc ); shape = new SHAPE( padstack ); padstack->Append( shape ); path = makePath( POINT( radius + padOffset.x, padOffset.y + dr ), // aStart POINT( radius + padOffset.x, padOffset.y - dr ), // aEnd POINT( radius, dr ), // aStart POINT( radius, -dr ), // aEnd layerName ); shape->SetShape( path ); shape = new SHAPE( padstack ); padstack->Append( shape ); // @todo: this 1/2 circle arc needs to be split into two quarter circle arcs qarc = makeArc( POINT( radius + padOffset.x, padOffset.y - dr), // aStart POINT( -radius + padOffset.x, padOffset.y - dr), // aEnd POINT( padOffset.x, padOffset.y - dr ), // aCenter POINT( radius, -dr ), // aStart POINT( 0.0, -dy ), // aEnd 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 ); shape->SetShape( qarc ); ++coppers; } } Loading Loading @@ -774,8 +857,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) if( item->GetLayer() == EDGE_N ) { pair.p1 = mapPt( item->m_Start ); pair.p2 = mapPt( item->m_End ); pair.start = mapPt( item->m_Start ); pair.end = mapPt( item->m_End ); pair.item = item; ppairs.push_back( pair ); haveEdges = true; Loading @@ -802,12 +885,14 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) rect->layer_id = "pcb"; // opposite corners rect->SetCorners( ppairs[0].p1, ppairs[2].p1 ); rect->SetCorners( ppairs[0].start, ppairs[2].start ); boundary->rectangle = rect; } 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->layer_id = "pcb"; Loading @@ -815,10 +900,21 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) { // unless its a closed polygon, this probably won't work, // otherwise it will. path->points.push_back( ppairs[i].p1 ); path->points.push_back( ppairs[i].start ); } 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 ); Loading Loading @@ -960,6 +1056,10 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) 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 ); PLACE* place = new PLACE( comp ); Loading @@ -968,8 +1068,6 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) place->SetRotation( module->m_Orient/10.0 ); place->SetVertex( mapPt( module->m_Pos ) ); place->component_id = CONV_TO_UTF8( module->GetReference() ); // not supported by freerouting.net yet: place->part_number = CONV_TO_UTF8( module->GetValue() ); // module is flipped from bottom side, set side to T_back Loading