From ef5f1b9e6b4786424ff132cbd5d011e21c7ce24e Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Wed, 25 Jul 2012 09:36:56 +0200 Subject: [PATCH 1/2] Start work on a better support of polygons in Kicad (code cleaning). Some coding style policy fix. --- 3d-viewer/3d_draw.cpp | 4 +- pcb_calculator/bitmaps/Thumbs.db | Bin 36864 -> 0 bytes ...board_items_to_polygon_shape_transform.cpp | 12 +- pcbnew/class_zone.cpp | 50 +-- pcbnew/kicad_plugin.cpp | 2 +- pcbnew/legacy_plugin.cpp | 6 +- pcbnew/polygons_defs.h | 51 ++- pcbnew/specctra_export.cpp | 28 +- pcbnew/zone_filling_algorithm.cpp | 2 +- ...nvert_brd_items_to_polygons_with_Boost.cpp | 83 +++-- pcbnew/zones_functions_for_undo_redo.cpp | 2 +- pcbnew/zones_test_and_combine_areas.cpp | 221 +++++++------ polygon/PolyLine.cpp | 306 +++++++++--------- polygon/PolyLine.h | 44 +-- 14 files changed, 423 insertions(+), 388 deletions(-) delete mode 100644 pcb_calculator/bitmaps/Thumbs.db diff --git a/3d-viewer/3d_draw.cpp b/3d-viewer/3d_draw.cpp index 0c0a6b05d8..36e2bcea1c 100644 --- a/3d-viewer/3d_draw.cpp +++ b/3d-viewer/3d_draw.cpp @@ -305,7 +305,7 @@ GLuint EDA_3D_CANVAS::CreateDrawGL_List() { CPolyPt* endcorner = &polysList[ic]; - if( begincorner->utility == 0 ) + if( begincorner->m_utility == 0 ) { // Draw only basic outlines, not extra segments dummysegment.m_Start.x = begincorner->x; @@ -318,7 +318,7 @@ GLuint EDA_3D_CANVAS::CreateDrawGL_List() if( (endcorner->end_contour) || (ic == imax) ) { // the last corner of a filled area is found: draw it - if( endcorner->utility == 0 ) + if( endcorner->m_utility == 0 ) { // Draw only basic outlines, not extra segments dummysegment.m_Start.x = endcorner->x; diff --git a/pcb_calculator/bitmaps/Thumbs.db b/pcb_calculator/bitmaps/Thumbs.db deleted file mode 100644 index a26a0e272b0bc90cae3713fe050031b9552c1d2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36864 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 diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp index 10d03071a3..47a8bbd736 100644 --- a/pcbnew/board_items_to_polygon_shape_transform.cpp +++ b/pcbnew/board_items_to_polygon_shape_transform.cpp @@ -167,19 +167,19 @@ void ZONE_CONTAINER::TransformShapeWithClearanceToPolygon( std::vector // Calculate the polygon with clearance and holes // holes are linked to the main outline, so only one polygon should be created. - KPolygonSet polyset_zone_solid_areas; - std::vector cornerslist; + KI_POLYGON_SET polyset_zone_solid_areas; + std::vector cornerslist; unsigned ic = 0; unsigned corners_count = zoneOutines.size(); while( ic < corners_count ) { cornerslist.clear(); - KPolygon poly; + KI_POLYGON poly; { for( ; ic < corners_count; ic++ ) { CPolyPt* corner = &zoneOutines[ic]; - cornerslist.push_back( KPolyPoint( corner->x, corner->y ) ); + cornerslist.push_back( KI_POLY_POINT( corner->x, corner->y ) ); if( corner->end_contour ) { ic++; @@ -197,12 +197,12 @@ void ZONE_CONTAINER::TransformShapeWithClearanceToPolygon( std::vector // Put the resultng polygon in buffer for( unsigned ii = 0; ii < polyset_zone_solid_areas.size(); ii++ ) { - KPolygon& poly = polyset_zone_solid_areas[ii]; + KI_POLYGON& poly = polyset_zone_solid_areas[ii]; CPolyPt corner( 0, 0, false ); for( unsigned jj = 0; jj < poly.size(); jj++ ) { - KPolyPoint point = *(poly.begin() + jj); + KI_POLY_POINT point = *(poly.begin() + jj); corner.x = point.x(); corner.y = point.y(); corner.end_contour = false; diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index d67142aaa8..d79c1e4ffc 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -210,7 +210,7 @@ void ZONE_CONTAINER::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int aDrawMode, const { seg_start = GetCornerPosition( ic ) + offset; - if( m_Poly->corner[ic].end_contour == false && ic < GetNumCorners() - 1 ) + if( m_Poly->m_CornersList[ic].end_contour == false && ic < GetNumCorners() - 1 ) { seg_end = GetCornerPosition( ic + 1 ) + offset; } @@ -306,7 +306,7 @@ void ZONE_CONTAINER::DrawFilledArea( EDA_DRAW_PANEL* panel, CornersBuffer.push_back( coord ); - CornersTypeBuffer.push_back( (char) corner->utility ); + CornersTypeBuffer.push_back( (char) corner->m_utility ); if( (corner->end_contour) || (ic == imax) ) // the last corner of a filled area is found: draw it { @@ -432,13 +432,13 @@ void ZONE_CONTAINER::DrawWhileCreateOutline( EDA_DRAW_PANEL* panel, wxDC* DC, in int yi = GetCornerPosition( ic ).y; int xf, yf; - if( m_Poly->corner[ic].end_contour == false && ic < icmax ) + if( m_Poly->m_CornersList[ic].end_contour == false && ic < icmax ) { is_close_segment = false; xf = GetCornerPosition( ic + 1 ).x; yf = GetCornerPosition( ic + 1 ).y; - if( (m_Poly->corner[ic + 1].end_contour) || (ic == icmax - 1) ) + if( (m_Poly->m_CornersList[ic + 1].end_contour) || (ic == icmax - 1) ) current_gr_mode = GR_XOR; else current_gr_mode = draw_mode; @@ -507,12 +507,12 @@ bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos ) int min_dist = MIN_DIST_IN_MILS*IU_PER_MILS; wxPoint delta; - unsigned lim = m_Poly->corner.size(); + unsigned lim = m_Poly->m_CornersList.size(); for( unsigned item_pos = 0; item_pos < lim; item_pos++ ) { - delta.x = refPos.x - m_Poly->corner[item_pos].x; - delta.y = refPos.y - m_Poly->corner[item_pos].y; + delta.x = refPos.x - m_Poly->m_CornersList[item_pos].x; + delta.y = refPos.y - m_Poly->m_CornersList[item_pos].y; // Calculate a distance: int dist = MAX( abs( delta.x ), abs( delta.y ) ); @@ -530,7 +530,7 @@ bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos ) bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos ) { - unsigned lim = m_Poly->corner.size(); + unsigned lim = m_Poly->m_CornersList.size(); m_CornerSelection = -1; // Set to not found @@ -547,7 +547,7 @@ bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos ) * the last segment of the current outline starts at current corner, and ends * at the first corner of the outline */ - if( m_Poly->corner[item_pos].end_contour || end_segm >= lim ) + if( m_Poly->m_CornersList[item_pos].end_contour || end_segm >= lim ) { unsigned tmp = first_corner_pos; first_corner_pos = end_segm; // first_corner_pos is now the beginning of the next outline @@ -557,10 +557,10 @@ bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos ) /* test the dist between segment and ref point */ int dist = (int) GetPointToLineSegmentDistance( refPos.x, refPos.y, - m_Poly->corner[item_pos].x, - m_Poly->corner[item_pos].y, - m_Poly->corner[end_segm].x, - m_Poly->corner[end_segm].y ); + m_Poly->m_CornersList[item_pos].x, + m_Poly->m_CornersList[item_pos].y, + m_Poly->m_CornersList[end_segm].x, + m_Poly->m_CornersList[end_segm].y ); if( dist < min_dist ) { @@ -703,7 +703,7 @@ void ZONE_CONTAINER::DisplayInfo( EDA_DRAW_FRAME* frame ) msg = board->GetLayerName( m_Layer ); frame->AppendMsgPanel( _( "Layer" ), msg, BROWN ); - msg.Printf( wxT( "%d" ), (int) m_Poly->corner.size() ); + msg.Printf( wxT( "%d" ), (int) m_Poly->m_CornersList.size() ); frame->AppendMsgPanel( _( "Corners" ), msg, BLUE ); if( m_FillMode ) @@ -730,7 +730,7 @@ void ZONE_CONTAINER::DisplayInfo( EDA_DRAW_FRAME* frame ) void ZONE_CONTAINER::Move( const wxPoint& offset ) { /* move outlines */ - for( unsigned ii = 0; ii < m_Poly->corner.size(); ii++ ) + for( unsigned ii = 0; ii < m_Poly->m_CornersList.size(); ii++ ) { SetCornerPosition( ii, GetCornerPosition( ii ) + offset ); } @@ -761,7 +761,7 @@ void ZONE_CONTAINER::MoveEdge( const wxPoint& offset ) SetCornerPosition( ii, GetCornerPosition( ii ) + offset ); // Move the end point of the selected edge: - if( m_Poly->corner[ii].end_contour || ii == GetNumCorners() - 1 ) + if( m_Poly->m_CornersList[ii].end_contour || ii == GetNumCorners() - 1 ) { int icont = m_Poly->GetContour( ii ); ii = m_Poly->GetContourStart( icont ); @@ -781,13 +781,13 @@ void ZONE_CONTAINER::Rotate( const wxPoint& centre, double angle ) { wxPoint pos; - for( unsigned ii = 0; ii < m_Poly->corner.size(); ii++ ) + for( unsigned ii = 0; ii < m_Poly->m_CornersList.size(); ii++ ) { - pos.x = m_Poly->corner[ii].x; - pos.y = m_Poly->corner[ii].y; + pos.x = m_Poly->m_CornersList[ii].x; + pos.y = m_Poly->m_CornersList[ii].y; RotatePoint( &pos, centre, angle ); - m_Poly->corner[ii].x = pos.x; - m_Poly->corner[ii].y = pos.y; + m_Poly->m_CornersList[ii].x = pos.x; + m_Poly->m_CornersList[ii].y = pos.y; } m_Poly->Hatch(); @@ -820,11 +820,11 @@ void ZONE_CONTAINER::Flip( const wxPoint& aCentre ) void ZONE_CONTAINER::Mirror( const wxPoint& mirror_ref ) { - for( unsigned ii = 0; ii < m_Poly->corner.size(); ii++ ) + for( unsigned ii = 0; ii < m_Poly->m_CornersList.size(); ii++ ) { - m_Poly->corner[ii].y -= mirror_ref.y; - NEGATE( m_Poly->corner[ii].y ); - m_Poly->corner[ii].y += mirror_ref.y; + m_Poly->m_CornersList[ii].y -= mirror_ref.y; + NEGATE( m_Poly->m_CornersList[ii].y ); + m_Poly->m_CornersList[ii].y += mirror_ref.y; } m_Poly->Hatch(); diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index 9387c24cc3..0c14255698 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -1059,7 +1059,7 @@ void PCB_IO::format( ZONE_CONTAINER* aZone, int aNestLevel ) const m_out->Print( 0, ")\n" ); - const std::vector< CPolyPt >& cv = aZone->m_Poly->corner; + const std::vector< CPolyPt >& cv = aZone->m_Poly->m_CornersList; int newLine = 0; if( cv.size() ) diff --git a/pcbnew/legacy_plugin.cpp b/pcbnew/legacy_plugin.cpp index 028b2f9248..77618154a4 100644 --- a/pcbnew/legacy_plugin.cpp +++ b/pcbnew/legacy_plugin.cpp @@ -3609,7 +3609,7 @@ void LEGACY_PLUGIN::saveZONE_CONTAINER( const ZONE_CONTAINER* me ) const typedef std::vector< CPolyPt > CPOLY_PTS; // Save the corner list - const CPOLY_PTS& cv = me->m_Poly->corner; + const CPOLY_PTS& cv = me->m_Poly->m_CornersList; for( CPOLY_PTS::const_iterator it = cv.begin(); it != cv.end(); ++it ) { fprintf( m_fp, "ZCorner %s %d\n", @@ -3623,12 +3623,12 @@ void LEGACY_PLUGIN::saveZONE_CONTAINER( const ZONE_CONTAINER* me ) const { fprintf( m_fp, "$POLYSCORNERS\n" ); - for( CPOLY_PTS::const_iterator it = fv.begin(); it != fv.end(); ++it ) + for( CPOLY_PTS::const_iterator it = fv.begin(); it != fv.end(); ++it ) { fprintf( m_fp, "%s %d %d\n", fmtBIUPair( it->x, it->y ).c_str(), it->end_contour, - it->utility ); + it->m_utility ); } fprintf( m_fp, "$endPOLYSCORNERS\n" ); diff --git a/pcbnew/polygons_defs.h b/pcbnew/polygons_defs.h index 3d7640c8d8..f9055c1cc6 100644 --- a/pcbnew/polygons_defs.h +++ b/pcbnew/polygons_defs.h @@ -12,10 +12,55 @@ namespace bpl = boost::polygon; // bpl = boost polygon library using namespace bpl::operators; // +, -, =, ... +// Definitions needed by boost::polygon typedef int coordinate_type; -typedef bpl::polygon_data KPolygon; -typedef std::vector KPolygonSet; +/** + * KI_POLYGON defines a single polygon ( boost::polygon_data type. + * When holes are created in a KPolygon, they are + * linked to main outline by overlapping segments, + * so there is always one polygon and one list of corners + * coordinates are int + */ +typedef bpl::polygon_data KI_POLYGON; + +/** + * KI_POLYGON_SET defines a set of single KI_POLYGON. + * A KI_POLYGON_SET is used to store a set of polygons + * when performing operations between 2 polygons + * or 2 sets of polygons + * The result of operations like and, xor... between 2 polygons + * is always stored in a KI_POLYGON_SET, because these operations + * can create many polygons + */ +typedef std::vector KI_POLYGON_SET; + +/** + * KI_POLY_POINT defines a point for boost::polygon. + * KI_POLY_POINT store x and y coordinates (int) + */ +typedef bpl::point_data KI_POLY_POINT; + +/** + * KI_POLYGON_WITH_HOLES defines a single polygon with holes + * When holes are created in a KI_POLYGON_WITH_HOLES, they are + * stored as separate single polygons, + * KI_POLYGON_WITH_HOLES store always one polygon for the external outline + * and one list of polygons (holes) which can be empty + */ +typedef bpl::polygon_with_holes_data KI_POLYGON_WITH_HOLES; + +/** + * KI_POLYGON_WITH_HOLES_SET defines a set of KI_POLYGON_WITH_HOLES. + * A KI_POLYGON_WITH_HOLES_SET is used to store a set of polygons with holes + * when performing operations between 2 polygons + * or 2 sets of polygons with holes + * The result of operations like and, xor... between 2 polygons with holes + * is always stored in a KI_POLYGON_WITH_HOLES_SET, because these operations + * can create many separate polygons with holespolygons + */ + +typedef std::vector KI_POLYGON_WITH_HOLES_SET; + -typedef bpl::point_data KPolyPoint; #endif // #ifndef _POLYGONS_DEFS_H_ diff --git a/pcbnew/specctra_export.cpp b/pcbnew/specctra_export.cpp index be1a66e462..1a51b76aca 100644 --- a/pcbnew/specctra_export.cpp +++ b/pcbnew/specctra_export.cpp @@ -1178,16 +1178,16 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) mainPolygon->layer_id = layerIds[ kicadLayer2pcb[ item->GetLayer() ] ]; - int count = item->m_Poly->corner.size(); + int count = item->m_Poly->m_CornersList.size(); int ndx = 0; // used in 2 for() loops below for( ; ndxm_Poly->corner[ndx].x, - item->m_Poly->corner[ndx].y ); + wxPoint point( item->m_Poly->m_CornersList[ndx].x, + item->m_Poly->m_CornersList[ndx].y ); mainPolygon->AppendPoint( mapPt(point) ); // this was the end of the main polygon - if( item->m_Poly->corner[ndx].end_contour ) + if( item->m_Poly->m_CornersList[ndx].end_contour ) break; } @@ -1197,7 +1197,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) // handle the cutouts for( ++ndx; ndxm_Poly->corner[ndx-1].end_contour ) + if( item->m_Poly->m_CornersList[ndx-1].end_contour ) { window = new WINDOW( plane ); plane->AddWindow( window ); @@ -1211,8 +1211,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) wxASSERT( window ); wxASSERT( cutout ); - wxPoint point(item->m_Poly->corner[ndx].x, - item->m_Poly->corner[ndx].y ); + wxPoint point(item->m_Poly->m_CornersList[ndx].x, + item->m_Poly->m_CornersList[ndx].y ); cutout->AppendPoint( mapPt(point) ); } } @@ -1253,16 +1253,16 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) mainPolygon->layer_id = layerIds[ kicadLayer2pcb[ item->GetLayer() ] ]; - int count = item->m_Poly->corner.size(); + int count = item->m_Poly->m_CornersList.size(); int ndx = 0; // used in 2 for() loops below for( ; ndxm_Poly->corner[ndx].x, - item->m_Poly->corner[ndx].y ); + wxPoint point( item->m_Poly->m_CornersList[ndx].x, + item->m_Poly->m_CornersList[ndx].y ); mainPolygon->AppendPoint( mapPt(point) ); // this was the end of the main polygon - if( item->m_Poly->corner[ndx].end_contour ) + if( item->m_Poly->m_CornersList[ndx].end_contour ) break; } @@ -1272,7 +1272,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) // handle the cutouts for( ++ndx; ndxm_Poly->corner[ndx-1].end_contour ) + if( item->m_Poly->m_CornersList[ndx-1].end_contour ) { window = new WINDOW( keepout ); keepout->AddWindow( window ); @@ -1286,8 +1286,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IO_ERROR ) wxASSERT( window ); wxASSERT( cutout ); - wxPoint point(item->m_Poly->corner[ndx].x, - item->m_Poly->corner[ndx].y ); + wxPoint point(item->m_Poly->m_CornersList[ndx].x, + item->m_Poly->m_CornersList[ndx].y ); cutout->AppendPoint( mapPt(point) ); } } diff --git a/pcbnew/zone_filling_algorithm.cpp b/pcbnew/zone_filling_algorithm.cpp index 539d6a0f0c..e829c37f96 100644 --- a/pcbnew/zone_filling_algorithm.cpp +++ b/pcbnew/zone_filling_algorithm.cpp @@ -188,7 +188,7 @@ int ZONE_CONTAINER::Fill_Zone_Areas_With_Segments() x_coordinates.clear(); for( ics = istart, ice = iend; ics <= iend; ice = ics, ics++ ) { - if ( m_FilledPolysList[ice].utility ) + if ( m_FilledPolysList[ice].m_utility ) continue; int seg_startX = m_FilledPolysList[ics].x; int seg_startY = m_FilledPolysList[ics].y; diff --git a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp index 487ce0110d..48e1e418b5 100644 --- a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp +++ b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp @@ -81,14 +81,14 @@ extern void CreateThermalReliefPadPolygon( std::vector& aCornerBuffer, int aThermalRot ); // Local Functions: helper function to calculate solid areas -static void AddPolygonCornersToKPolygonList( std::vector & aCornersBuffer, - KPolygonSet& aKPolyList ); +static void AddPolygonCornersToKiPolygonList( std::vector & aCornersBuffer, + KI_POLYGON_SET& aKiPolyList ); -static int CopyPolygonsFromKPolygonListToFilledPolysList( ZONE_CONTAINER* aZone, - KPolygonSet& aKPolyList ); +static int CopyPolygonsFromKiPolygonListToFilledPolysList( ZONE_CONTAINER* aZone, + KI_POLYGON_SET& aKiPolyList ); -static int CopyPolygonsFromFilledPolysListTotKPolygonList( ZONE_CONTAINER* aZone, - KPolygonSet& aKPolyList ); +static int CopyPolygonsFromFilledPolysListToKiPolygonList( ZONE_CONTAINER* aZone, + KI_POLYGON_SET& aKiPolyList ); // Local Variables: @@ -148,8 +148,8 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) */ s_Correction = 1.0 / cos( 3.14159265 / s_CircleToSegmentsCount ); - // This KPolygonSet is the area(s) to fill, with m_ZoneMinThickness/2 - KPolygonSet polyset_zone_solid_areas; + // This KI_POLYGON_SET is the area(s) to fill, with m_ZoneMinThickness/2 + KI_POLYGON_SET polyset_zone_solid_areas; int margin = m_ZoneMinThickness / 2; /* First, creates the main polygon (i.e. the filled area using only one outline) @@ -160,7 +160,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) * the main polygon is stored in polyset_zone_solid_areas */ - CopyPolygonsFromFilledPolysListTotKPolygonList( this, polyset_zone_solid_areas ); + CopyPolygonsFromFilledPolysListToKiPolygonList( this, polyset_zone_solid_areas ); polyset_zone_solid_areas -= margin; if( polyset_zone_solid_areas.size() == 0 ) @@ -431,15 +431,15 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) // Calculate now actual solid areas if( cornerBufferPolysToSubstract.size() > 0 ) { - KPolygonSet polyset_holes; - AddPolygonCornersToKPolygonList( cornerBufferPolysToSubstract, polyset_holes ); + KI_POLYGON_SET polyset_holes; + AddPolygonCornersToKiPolygonList( cornerBufferPolysToSubstract, polyset_holes ); // Remove holes from initial area.: polyset_zone_solid_areas -= polyset_holes; } // put solid areas in m_FilledPolysList: m_FilledPolysList.clear(); - CopyPolygonsFromKPolygonListToFilledPolysList( this, polyset_zone_solid_areas ); + CopyPolygonsFromKiPolygonListToFilledPolysList( this, polyset_zone_solid_areas ); // Remove insulated islands: if( GetNet() > 0 ) @@ -455,13 +455,13 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) // remove copper areas if( cornerBufferPolysToSubstract.size() ) { - KPolygonSet polyset_holes; - AddPolygonCornersToKPolygonList( cornerBufferPolysToSubstract, polyset_holes ); + KI_POLYGON_SET polyset_holes; + AddPolygonCornersToKiPolygonList( cornerBufferPolysToSubstract, polyset_holes ); polyset_zone_solid_areas -= polyset_holes; // put these areas in m_FilledPolysList m_FilledPolysList.clear(); - CopyPolygonsFromKPolygonListToFilledPolysList( this, polyset_zone_solid_areas ); + CopyPolygonsFromKiPolygonListToFilledPolysList( this, polyset_zone_solid_areas ); if( GetNet() > 0 ) Test_For_Copper_Island_And_Remove_Insulated_Islands( aPcb ); @@ -470,12 +470,12 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) cornerBufferPolysToSubstract.clear(); } -void AddPolygonCornersToKPolygonList( std::vector & aCornersBuffer, - KPolygonSet& aKPolyList ) +void AddPolygonCornersToKiPolygonList( std::vector & aCornersBuffer, + KI_POLYGON_SET& aKiPolyList ) { unsigned ii; - std::vector cornerslist; + std::vector cornerslist; int polycount = 0; @@ -485,42 +485,42 @@ void AddPolygonCornersToKPolygonList( std::vector & aCornersBuffer, polycount++; } - aKPolyList.reserve( polycount ); + aKiPolyList.reserve( polycount ); for( unsigned icnt = 0; icnt < aCornersBuffer.size(); ) { - KPolygon poly; + KI_POLYGON poly; cornerslist.clear(); for( ii = icnt; ii < aCornersBuffer.size(); ii++ ) { - cornerslist.push_back( KPolyPoint( aCornersBuffer[ii].x, aCornersBuffer[ii].y ) ); + cornerslist.push_back( KI_POLY_POINT( aCornersBuffer[ii].x, aCornersBuffer[ii].y ) ); if( aCornersBuffer[ii].end_contour ) break; } bpl::set_points( poly, cornerslist.begin(), cornerslist.end() ); - aKPolyList.push_back( poly ); + aKiPolyList.push_back( poly ); icnt = ii + 1; } } -int CopyPolygonsFromKPolygonListToFilledPolysList( ZONE_CONTAINER* aZone, - KPolygonSet& aKPolyList ) +int CopyPolygonsFromKiPolygonListToFilledPolysList( ZONE_CONTAINER* aZone, + KI_POLYGON_SET& aKiPolyList ) { int count = 0; std::vector polysList; - for( unsigned ii = 0; ii < aKPolyList.size(); ii++ ) + for( unsigned ii = 0; ii < aKiPolyList.size(); ii++ ) { - KPolygon& poly = aKPolyList[ii]; + KI_POLYGON& poly = aKiPolyList[ii]; CPolyPt corner( 0, 0, false ); for( unsigned jj = 0; jj < poly.size(); jj++ ) { - KPolyPoint point = *(poly.begin() + jj); + KI_POLY_POINT point = *(poly.begin() + jj); corner.x = point.x(); corner.y = point.y(); corner.end_contour = false; @@ -542,10 +542,10 @@ int CopyPolygonsFromKPolygonListToFilledPolysList( ZONE_CONTAINER* aZone, } -int CopyPolygonsFromFilledPolysListTotKPolygonList( ZONE_CONTAINER* aZone, - KPolygonSet& aKPolyList ) +int CopyPolygonsFromFilledPolysListToKiPolygonList( ZONE_CONTAINER* aZone, + KI_POLYGON_SET& aKiPolyList ) { - std::vector polysList = aZone->GetFilledPolysList(); + const std::vector& polysList = aZone->GetFilledPolysList(); unsigned corners_count = polysList.size(); int count = 0; unsigned ic = 0; @@ -554,35 +554,32 @@ int CopyPolygonsFromFilledPolysListTotKPolygonList( ZONE_CONTAINER* aZone, for( unsigned ii = 0; ii < corners_count; ii++ ) { - CPolyPt* corner = &polysList[ic]; + const CPolyPt& corner = polysList[ii]; - if( corner->end_contour ) + if( corner.end_contour ) polycount++; } - aKPolyList.reserve( polycount ); - std::vector cornerslist; + aKiPolyList.reserve( polycount ); + std::vector cornerslist; while( ic < corners_count ) { cornerslist.clear(); - KPolygon poly; + KI_POLYGON poly; { - for( ; ic < corners_count; ic++ ) + while( ic < corners_count ) { - CPolyPt* corner = &polysList[ic]; - cornerslist.push_back( KPolyPoint( corner->x, corner->y ) ); + const CPolyPt& corner = polysList[ic++]; + cornerslist.push_back( KI_POLY_POINT( corner.x, corner.y ) ); count++; - if( corner->end_contour ) - { - ic++; + if( corner.end_contour ) break; - } } bpl::set_points( poly, cornerslist.begin(), cornerslist.end() ); - aKPolyList.push_back( poly ); + aKiPolyList.push_back( poly ); } } diff --git a/pcbnew/zones_functions_for_undo_redo.cpp b/pcbnew/zones_functions_for_undo_redo.cpp index d3971a44fd..7d13e3b6b4 100644 --- a/pcbnew/zones_functions_for_undo_redo.cpp +++ b/pcbnew/zones_functions_for_undo_redo.cpp @@ -115,7 +115,7 @@ bool ZONE_CONTAINER::IsSame( const ZONE_CONTAINER& aZoneToCompare ) wxASSERT( m_Poly ); // m_Poly == NULL Should never happen wxASSERT( aZoneToCompare.m_Poly ); - if( m_Poly->corner != aZoneToCompare.m_Poly->corner ) // Compare vector + if( m_Poly->m_CornersList != aZoneToCompare.m_Poly->m_CornersList ) // Compare vector return false; return true; diff --git a/pcbnew/zones_test_and_combine_areas.cpp b/pcbnew/zones_test_and_combine_areas.cpp index d790a8eb9e..fd5092d0bf 100644 --- a/pcbnew/zones_test_and_combine_areas.cpp +++ b/pcbnew/zones_test_and_combine_areas.cpp @@ -31,6 +31,7 @@ */ #include +#include #include #include #include @@ -142,7 +143,7 @@ int BOARD::TestAreaPolygon( ZONE_CONTAINER* CurrArea ) // first, check for sides intersecting other sides, especially arcs bool bInt = false; bool bArcInt = false; - int n_cont = p->GetNumContours(); + int n_cont = p->GetContoursCount(); // make bounding rect for each contour std::vector cr; @@ -550,7 +551,7 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test ) continue; // test for intersecting segments - for( int icont1 = 0; icont1GetNumContours(); icont1++ ) + for( int icont1 = 0; icont1GetContoursCount(); icont1++ ) { int is1 = poly1->GetContourStart( icont1 ); int ie1 = poly1->GetContourEnd( icont1 ); @@ -574,7 +575,7 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test ) style1 = poly1->GetSideStyle( ic1 ); - for( int icont2 = 0; icont2 < poly2->GetNumContours(); icont2++ ) + for( int icont2 = 0; icont2 < poly2->GetContoursCount(); icont2++ ) { int is2 = poly2->GetContourStart( icont2 ); int ie2 = poly2->GetContourEnd( icont2 ); @@ -668,7 +669,7 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_ bool bInt = false; bool bArcInt = false; - for( int icont1 = 0; icont1GetNumContours(); icont1++ ) + for( int icont1 = 0; icont1GetContoursCount(); icont1++ ) { int is1 = poly1->GetContourStart( icont1 ); int ie1 = poly1->GetContourEnd( icont1 ); @@ -692,7 +693,7 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_ style1 = poly1->GetSideStyle( ic1 ); - for( int icont2 = 0; icont2GetNumContours(); icont2++ ) + for( int icont2 = 0; icont2GetContoursCount(); icont2++ ) { int is2 = poly2->GetContourStart( icont2 ); int ie2 = poly2->GetContourEnd( icont2 ); @@ -778,145 +779,139 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_ return 1; } +/** + * Function CopyPolysListToKiPolygonWithHole + * converts the outline contours aPolysList to a KI_POLYGON_WITH_HOLES + * + * @param aPolysList = the list of corners of contours + * @param aPolygoneWithHole = a KI_POLYGON_WITH_HOLES to populate + */ +void CopyPolysListToKiPolygonWithHole( const std::vector& aPolysList, + KI_POLYGON_WITH_HOLES& aPolygoneWithHole ) +{ + unsigned corners_count = aPolysList.size(); + + std::vector cornerslist; + KI_POLYGON poly; + + // Enter main outline: this is the first contour + unsigned ic = 0; + while( ic < corners_count ) + { + const CPolyPt& corner = aPolysList[ic++]; + cornerslist.push_back( KI_POLY_POINT( corner.x, corner.y ) ); + + if( corner.end_contour ) + break; + } + + aPolygoneWithHole.set( cornerslist.begin(), cornerslist.end() ); + + // Enter holes: they are next contours (when exist) + if( ic < corners_count ) + { + KI_POLYGON_SET holePolyList; + while( ic < corners_count ) + { + cornerslist.clear(); + + while( ic < corners_count ) + { + const CPolyPt& corner = aPolysList[ic++]; + cornerslist.push_back( KI_POLY_POINT( corner.x, corner.y ) ); + + if( corner.end_contour ) + break; + } + + bpl::set_points( poly, cornerslist.begin(), cornerslist.end() ); + holePolyList.push_back( poly ); + } + aPolygoneWithHole.set_holes( holePolyList.begin(), holePolyList.end() ); + } +} + /** * Function CombineAreas - * If possible, combine 2 copper areas + * Merge 2 copper areas (which are expected intersecting) * @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in undo * commands can be NULL - * @param area_ref = tje main area (zone) + * @param area_ref = the main area (zone) * @param area_to_combine = the zone that can be merged with area_ref * area_ref must be BEFORE area_to_combine * area_to_combine will be deleted, if areas are combined * @return : 0 if no intersection * 1 if intersection - * 2 if arcs intersect + * 2 if arcs intersect (Currently not supported) */ + int BOARD::CombineAreas( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combine ) { if( area_ref == area_to_combine ) { wxASSERT( 0 ); + return 0; } // polygons intersect, combine them - std::vector arc_array1; - std::vector arc_array2; - bool keep_area_to_combine = false; +// std::vector arc_array1; +// std::vector arc_array2; + bool keep_area_to_combine = false; // TODO test if areas intersect - Bool_Engine* booleng = new Bool_Engine(); - ArmBoolEng( booleng ); + KI_POLYGON_WITH_HOLES areaRefPoly; + KI_POLYGON_WITH_HOLES areaToMergePoly; + CopyPolysListToKiPolygonWithHole( area_ref->m_Poly->m_CornersList, areaRefPoly ); + CopyPolysListToKiPolygonWithHole( area_to_combine->m_Poly->m_CornersList, areaToMergePoly ); - area_ref->m_Poly->AddPolygonsToBoolEng( booleng, GROUP_A, -1, -1 ); - area_to_combine->m_Poly->AddPolygonsToBoolEng( booleng, GROUP_B, -1, -1 ); - booleng->Do_Operation( BOOL_OR ); + KI_POLYGON_WITH_HOLES_SET mergedOutlines; + mergedOutlines.push_back( areaRefPoly ); + mergedOutlines += areaToMergePoly; + // We should have only one polygon with holes in mergedOutlines + // or the 2 initial outlines do not intersect + if( mergedOutlines.size() > 1 ) + return 0; + + areaRefPoly = mergedOutlines[0]; + area_ref->m_Poly->RemoveAllContours(); + + KI_POLYGON_WITH_HOLES::iterator_type corner = areaRefPoly.begin(); // create area with external contour: Recreate only area edges, NOT holes - if( booleng->StartPolygonGet() ) + area_ref->m_Poly->Start( area_ref->GetLayer(), corner->x(), corner->y(), + area_ref->m_Poly->GetHatchStyle() ); + while( ++corner != areaRefPoly.end() ) { - if( booleng->GetPolygonPointEdgeType() == KB_INSIDE_EDGE ) + area_ref->m_Poly->AppendCorner( corner->x(), corner->y() ); + } + + area_ref->m_Poly->Close(); + + // add holes (set of polygons) + KI_POLYGON_WITH_HOLES::iterator_holes_type hole = areaRefPoly.begin_holes(); + while( hole != areaRefPoly.end_holes() ) + { + KI_POLYGON::iterator_type hole_corner = hole->begin(); + // create area with external contour: Recreate only area edges, NOT holes + while( hole_corner != hole->end() ) { - DisplayError( NULL, wxT( "BOARD::CombineAreas() error: unexpected hole descriptor" ) ); + area_ref->m_Poly->AppendCorner( hole_corner->x(), hole_corner->y() ); + hole_corner++; } - - area_ref->m_Poly->RemoveAllContours(); - - // foreach point in the polygon - bool first = true; - - while( booleng->PolygonHasMorePoints() ) - { - int x = (int) booleng->GetPolygonXPoint(); - int y = (int) booleng->GetPolygonYPoint(); - - if( first ) - { - first = false; - area_ref->m_Poly->Start( area_ref->GetLayer( - ), x, y, area_ref->m_Poly->GetHatchStyle() ); - } - else - { - area_ref->m_Poly->AppendCorner( x, y ); - } - } - - booleng->EndPolygonGet(); area_ref->m_Poly->Close(); + hole++; } - // Recreate the area_to_combine if a second polygon exists - // if not exists , the first poly contains the 2 initial polygons -#if 0 // TestAreaIntersection must be called before combine areas, so - // 2 intersecting areas are expected, and only one outline contour after combining areas - else - { - area_to_combine->m_Poly->RemoveAllContours(); - keep_area_to_combine = true; - - // create area with external contour: Recreate only area edges, NOT holes (todo..) - { - // foreach point in the polygon - bool first = true; - while( booleng->PolygonHasMorePoints() ) - { - int x = booleng->GetPolygonXPoint(); - int y = booleng->GetPolygonYPoint(); - - if( first ) - { - first = false; - area_to_combine->m_Poly->Start( area_ref->GetLayer(), x, y, - area_ref->m_Poly->GetHatchStyle() ); - } - else - { - area_to_combine->m_Poly->AppendCorner( x, y ); - } - } - - booleng->EndPolygonGet(); - area_to_combine->m_Poly->Close(); - } - } -#endif - - // add holes - bool show_error = true; - - while( booleng->StartPolygonGet() ) - { - // we expect all vertex are holes inside the main outline - if( booleng->GetPolygonPointEdgeType() != KB_INSIDE_EDGE ) - { - if( show_error ) // show this error only once, if happens - DisplayError( NULL, - wxT( "BOARD::CombineAreas() error: unexpected outside contour descriptor" ) ); - - show_error = false; - continue; - } - - while( booleng->PolygonHasMorePoints() ) - { - int x = (int) booleng->GetPolygonXPoint(); - int y = (int) booleng->GetPolygonYPoint(); - area_ref->m_Poly->AppendCorner( x, y ); - } - - area_ref->m_Poly->Close(); - booleng->EndPolygonGet(); - } if( !keep_area_to_combine ) RemoveArea( aDeletedList, area_to_combine ); area_ref->utility = 1; - area_ref->m_Poly->RestoreArcs( &arc_array1 ); - area_ref->m_Poly->RestoreArcs( &arc_array2 ); +// area_ref->m_Poly->RestoreArcs( &arc_array1 ); +// area_ref->m_Poly->RestoreArcs( &arc_array2 ); area_ref->m_Poly->Hatch(); - delete booleng; + return 1; } @@ -1024,7 +1019,7 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E } // now test spacing between areas - for( int icont = 0; icont < refSmoothedPoly->GetNumContours(); icont++ ) + for( int icont = 0; icont < refSmoothedPoly->GetContoursCount(); icont++ ) { int ic_start = refSmoothedPoly->GetContourStart( icont ); int ic_end = refSmoothedPoly->GetContourEnd( icont ); @@ -1048,7 +1043,7 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E int astyle = refSmoothedPoly->GetSideStyle( ic ); - for( int icont2 = 0; icont2 < testSmoothedPoly->GetNumContours(); icont2++ ) + for( int icont2 = 0; icont2 < testSmoothedPoly->GetContoursCount(); icont2++ ) { int ic_start2 = testSmoothedPoly->GetContourStart( icont2 ); int ic_end2 = testSmoothedPoly->GetContourEnd( icont2 ); @@ -1128,7 +1123,7 @@ bool DRC::doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex ) wxPoint end; // Search the end point of the edge starting at aCornerIndex - if( aArea->m_Poly->corner[aCornerIndex].end_contour == false + if( aArea->m_Poly->m_CornersList[aCornerIndex].end_contour == false && aCornerIndex < (aArea->GetNumCorners() - 1) ) { end = aArea->GetCornerPosition( aCornerIndex + 1 ); @@ -1141,7 +1136,7 @@ bool DRC::doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex ) while( ii >= 0 ) { - if( aArea->m_Poly->corner[ii].end_contour ) + if( aArea->m_Poly->m_CornersList[ii].end_contour ) break; end = aArea->GetCornerPosition( ii ); @@ -1189,7 +1184,7 @@ bool DRC::doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex ) int ax2 = end.x; int ay2 = end.y; - for( int icont2 = 0; icont2 < area_to_test->m_Poly->GetNumContours(); icont2++ ) + for( int icont2 = 0; icont2 < area_to_test->m_Poly->GetContoursCount(); icont2++ ) { int ic_start2 = area_to_test->m_Poly->GetContourStart( icont2 ); int ic_end2 = area_to_test->m_Poly->GetContourEnd( icont2 ); diff --git a/polygon/PolyLine.cpp b/polygon/PolyLine.cpp index 4630e9dbbc..99fa36f76c 100644 --- a/polygon/PolyLine.cpp +++ b/polygon/PolyLine.cpp @@ -18,8 +18,8 @@ CPolyLine::CPolyLine() { m_hatchStyle = NO_HATCH; m_hatchPitch = 0; - m_Width = 0; - utility = 0; + m_width = 0; + m_utility = 0; m_Kbool_Poly_Engine = NULL; } @@ -33,6 +33,16 @@ CPolyLine::~CPolyLine() delete m_Kbool_Poly_Engine; } +/** + * Function armBoolEng + * Initialise parameters used in kbool + * @param aBooleng = pointer to the Bool_Engine to initialise + * @param aConvertHoles = mode for holes when a boolean operation is made + * true: holes are linked into outer contours by double overlapping segments + * false: holes are not linked: in this mode contours are added clockwise + * and polygons added counter clockwise are holes (default) + */ +static void armBoolEng( Bool_Engine* aBooleng, bool aConvertHoles = false ); /** * Function NormalizeWithKbool @@ -95,8 +105,8 @@ int CPolyLine::NormalizeWithKbool( std::vector * aExtraPolyList, boo else if( n_ext_cont == 0 ) { // first external contour, replace this poly - corner.clear(); - side_style.clear(); + m_CornersList.clear(); + m_SideStyle.clear(); bool first = true; while( m_Kbool_Poly_Engine->PolygonHasMorePoints() ) { @@ -271,7 +281,7 @@ int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector< m_Kbool_Poly_Engine = NULL; } - int polycount = GetNumContours(); + int polycount = GetContoursCount(); if( !GetClosed() && (aStart_contour == (polycount - 1) || aStart_contour == -1) ) return 1; // error @@ -297,7 +307,7 @@ int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector< // Fill a kbool engine for this contour, // and combine it with previous contours Bool_Engine* booleng = new Bool_Engine(); - ArmBoolEng( booleng, aConvertHoles ); + armBoolEng( booleng, aConvertHoles ); if( m_Kbool_Poly_Engine ) // a previous contour exists. Put it in new engine { @@ -329,7 +339,7 @@ int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector< } for( int ic = ic_st; ic<=ic_end; ic++ ) { - int style = side_style[ic]; + int style = m_SideStyle[ic]; if( style == STRAIGHT ) n_vertices++; else @@ -345,19 +355,19 @@ int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector< int ivtx = 0; for( int ic = ic_st; ic<=ic_end; ic++ ) { - int style = side_style[ic]; - int x1 = corner[ic].x; - int y1 = corner[ic].y; + int style = m_SideStyle[ic]; + int x1 = m_CornersList[ic].x; + int y1 = m_CornersList[ic].y; int x2, y2; if( ic < ic_end ) { - x2 = corner[ic + 1].x; - y2 = corner[ic + 1].y; + x2 = m_CornersList[ic + 1].x; + y2 = m_CornersList[ic + 1].y; } else { - x2 = corner[ic_st].x; - y2 = corner[ic_st].y; + x2 = m_CornersList[ic_st].x; + y2 = m_CornersList[ic_st].y; } if( style == STRAIGHT ) { @@ -504,14 +514,14 @@ int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector< /** - * Function ArmBoolEng + * Function armBoolEng * Initialise parameters used in kbool * @param aBooleng = pointer to the Bool_Engine to initialise * @param aConvertHoles = mode for holes when a boolean operation is made * true: in resulting polygon, holes are linked into outer contours by double overlapping segments * false: in resulting polygons, holes are not linked: they are separate polygons */ -void ArmBoolEng( Bool_Engine* aBooleng, bool aConvertHoles ) +void armBoolEng( Bool_Engine* aBooleng, bool aConvertHoles ) { // set some global vals to arm the boolean engine @@ -614,7 +624,7 @@ int CPolyLine::RestoreArcs( std::vector * arc_array, std::vectorsize(); CPolyLine* poly; - // undraw polys and clear utility flag for all corners + // undraw polys and clear m_utility flag for all corners for( int ip = 0; ip * arc_array, std::vectorGetNumCorners(); ic++ ) poly->SetUtility( ic, 0 ); - // clear utility flag + // clear m_utility flag } // find arcs and replace them @@ -649,7 +659,7 @@ int CPolyLine::RestoreArcs( std::vector * arc_array, std::vectorGetNumContours(); + int polycount = poly->GetContoursCount(); for( int icont = 0; icont < polycount; icont++ ) { int ic_start = poly->GetContourStart( icont ); @@ -697,7 +707,7 @@ int CPolyLine::RestoreArcs( std::vector * arc_array, std::vectorside_style[arc_start] = style; + poly->m_SideStyle[arc_start] = style; // mark corners for deletion from arc_start+1 to arc_end-1 for( int i = arc_start + 1; i!=arc_end; ) @@ -769,8 +779,8 @@ void CPolyLine::Start( int layer, int x, int y, int hatch ) CPolyPt poly_pt( x, y ); poly_pt.end_contour = false; - corner.push_back( poly_pt ); - side_style.push_back( 0 ); + m_CornersList.push_back( poly_pt ); + m_SideStyle.push_back( 0 ); } @@ -783,10 +793,10 @@ void CPolyLine::AppendCorner( int x, int y, int style, bool bDraw ) poly_pt.end_contour = false; // add entries for new corner and side - corner.push_back( poly_pt ); - side_style.push_back( style ); - if( corner.size() > 0 && !corner[corner.size() - 1].end_contour ) - side_style[corner.size() - 1] = style; + m_CornersList.push_back( poly_pt ); + m_SideStyle.push_back( style ); + if( m_CornersList.size() > 0 && !m_CornersList[m_CornersList.size() - 1].end_contour ) + m_SideStyle[m_CornersList.size() - 1] = style; if( bDraw ) Hatch(); } @@ -801,8 +811,8 @@ void CPolyLine::Close( int style, bool bDraw ) wxASSERT( 0 ); } UnHatch(); - side_style[corner.size() - 1] = style; - corner[corner.size() - 1].end_contour = true; + m_SideStyle[m_CornersList.size() - 1] = style; + m_CornersList[m_CornersList.size() - 1].end_contour = true; if( bDraw ) Hatch(); } @@ -813,8 +823,8 @@ void CPolyLine::Close( int style, bool bDraw ) void CPolyLine::MoveCorner( int ic, int x, int y ) { UnHatch(); - corner[ic].x = x; - corner[ic].y = y; + m_CornersList[ic].x = x; + m_CornersList[ic].y = y; Hatch(); } @@ -827,23 +837,23 @@ void CPolyLine::DeleteCorner( int ic, bool bDraw ) int icont = GetContour( ic ); int istart = GetContourStart( icont ); int iend = GetContourEnd( icont ); - bool bClosed = icont < GetNumContours() - 1 || GetClosed(); + bool bClosed = icont < GetContoursCount() - 1 || GetClosed(); if( !bClosed ) { // open contour, must be last contour - corner.erase( corner.begin() + ic ); + m_CornersList.erase( m_CornersList.begin() + ic ); if( ic != istart ) - side_style.erase( side_style.begin() + ic - 1 ); + m_SideStyle.erase( m_SideStyle.begin() + ic - 1 ); } else { // closed contour - corner.erase( corner.begin() + ic ); - side_style.erase( side_style.begin() + ic ); + m_CornersList.erase( m_CornersList.begin() + ic ); + m_SideStyle.erase( m_SideStyle.begin() + ic ); if( ic == iend ) - corner[ic - 1].end_contour = true; + m_CornersList[ic - 1].end_contour = true; } if( bClosed && GetContourSize( icont ) < 3 ) { @@ -869,7 +879,7 @@ void CPolyLine::RemoveContour( int icont ) int istart = GetContourStart( icont ); int iend = GetContourEnd( icont ); - int polycount = GetNumContours(); + int polycount = GetContoursCount(); if( icont == 0 && polycount == 1 ) { // remove the only contour @@ -878,16 +888,16 @@ void CPolyLine::RemoveContour( int icont ) else if( icont == polycount - 1 ) { // remove last contour - corner.erase( corner.begin() + istart, corner.end() ); - side_style.erase( side_style.begin() + istart, side_style.end() ); + m_CornersList.erase( m_CornersList.begin() + istart, m_CornersList.end() ); + m_SideStyle.erase( m_SideStyle.begin() + istart, m_SideStyle.end() ); } else { // remove closed contour for( int ic = iend; ic>=istart; ic-- ) { - corner.erase( corner.begin() + ic ); - side_style.erase( side_style.begin() + ic ); + m_CornersList.erase( m_CornersList.begin() + ic ); + m_SideStyle.erase( m_SideStyle.begin() + ic ); } } Hatch(); @@ -904,7 +914,7 @@ CPolyLine* CPolyLine::Chamfer( unsigned int aDistance ) return newPoly; } - int polycount = GetNumContours(); + int polycount = GetContoursCount(); for( int contour = 0; contour < polycount; contour++ ) { unsigned int startIndex = GetContourStart( contour ); @@ -915,29 +925,29 @@ CPolyLine* CPolyLine::Chamfer( unsigned int aDistance ) int x1, y1, nx, ny; long long xa, ya, xb, yb; - x1 = corner[index].x; - y1 = corner[index].y; + x1 = m_CornersList[index].x; + y1 = m_CornersList[index].y; if( index == startIndex ) { - xa = corner[endIndex].x - x1; - ya = corner[endIndex].y - y1; + xa = m_CornersList[endIndex].x - x1; + ya = m_CornersList[endIndex].y - y1; } else { - xa = corner[index-1].x - x1; - ya = corner[index-1].y - y1; + xa = m_CornersList[index-1].x - x1; + ya = m_CornersList[index-1].y - y1; } if( index == endIndex ) { - xb = corner[startIndex].x - x1; - yb = corner[startIndex].y - y1; + xb = m_CornersList[startIndex].x - x1; + yb = m_CornersList[startIndex].y - y1; } else { - xb = corner[index+1].x - x1; - yb = corner[index+1].y - y1; + xb = m_CornersList[index+1].x - x1; + yb = m_CornersList[index+1].y - y1; } unsigned int lena = (unsigned int)sqrt( (double)(xa*xa + ya*ya) ); @@ -980,7 +990,7 @@ CPolyLine* CPolyLine::Fillet( unsigned int aRadius, unsigned int aSegments ) return newPoly; } - int polycount = GetNumContours(); + int polycount = GetContoursCount(); for( int contour = 0; contour < polycount; contour++ ) { unsigned int startIndex = GetContourStart( contour ); @@ -994,29 +1004,29 @@ CPolyLine* CPolyLine::Fillet( unsigned int aRadius, unsigned int aSegments ) long long xb, yb; // Next vertex double nx, ny; - x1 = corner[index].x; - y1 = corner[index].y; + x1 = m_CornersList[index].x; + y1 = m_CornersList[index].y; if( index == startIndex ) { - xa = corner[endIndex].x - x1; - ya = corner[endIndex].y - y1; + xa = m_CornersList[endIndex].x - x1; + ya = m_CornersList[endIndex].y - y1; } else { - xa = corner[index-1].x - x1; - ya = corner[index-1].y - y1; + xa = m_CornersList[index-1].x - x1; + ya = m_CornersList[index-1].y - y1; } if( index == endIndex ) { - xb = corner[startIndex].x - x1; - yb = corner[startIndex].y - y1; + xb = m_CornersList[startIndex].x - x1; + yb = m_CornersList[startIndex].y - y1; } else { - xb = corner[index+1].x - x1; - yb = corner[index+1].y - y1; + xb = m_CornersList[index+1].x - x1; + yb = m_CornersList[index+1].y - y1; } double lena = sqrt( (double) (xa*xa + ya*ya) ); @@ -1103,8 +1113,8 @@ void CPolyLine::RemoveAllContours( void ) * Others params are not chnaged */ { - corner.clear(); - side_style.clear(); + m_CornersList.clear(); + m_SideStyle.clear(); } @@ -1117,23 +1127,23 @@ void CPolyLine::RemoveAllContours( void ) void CPolyLine::InsertCorner( int ic, int x, int y ) { UnHatch(); - if( (unsigned) (ic) >= corner.size() ) + if( (unsigned) (ic) >= m_CornersList.size() ) { - corner.push_back( CPolyPt( x, y ) ); - side_style.push_back( STRAIGHT ); + m_CornersList.push_back( CPolyPt( x, y ) ); + m_SideStyle.push_back( STRAIGHT ); } else { - corner.insert( corner.begin() + ic + 1, CPolyPt( x, y ) ); - side_style.insert( side_style.begin() + ic + 1, STRAIGHT ); + m_CornersList.insert( m_CornersList.begin() + ic + 1, CPolyPt( x, y ) ); + m_SideStyle.insert( m_SideStyle.begin() + ic + 1, STRAIGHT ); } - if( (unsigned) (ic + 1) < corner.size() ) + if( (unsigned) (ic + 1) < m_CornersList.size() ) { - if( corner[ic].end_contour ) + if( m_CornersList[ic].end_contour ) { - corner[ic + 1].end_contour = true; - corner[ic].end_contour = false; + m_CornersList[ic + 1].end_contour = true; + m_CornersList[ic].end_contour = false; } } Hatch(); @@ -1150,7 +1160,7 @@ void CPolyLine::UnHatch() int CPolyLine::GetEndContour( int ic ) { - return corner[ic].end_contour; + return m_CornersList[ic].end_contour; } @@ -1158,10 +1168,10 @@ CRect CPolyLine::GetBounds() { CRect r = GetCornerBounds(); - r.left -= m_Width / 2; - r.right += m_Width / 2; - r.bottom -= m_Width / 2; - r.top += m_Width / 2; + r.left -= m_width / 2; + r.right += m_width / 2; + r.bottom -= m_width / 2; + r.top += m_width / 2; return r; } @@ -1172,12 +1182,12 @@ CRect CPolyLine::GetCornerBounds() r.left = r.bottom = INT_MAX; r.right = r.top = INT_MIN; - for( unsigned i = 0; i max_x ) - max_x = corner[ic].x; - if( corner[ic].y < min_y ) - min_y = corner[ic].y; - if( corner[ic].y > max_y ) - max_y = corner[ic].y; + if( m_CornersList[ic].x < min_x ) + min_x = m_CornersList[ic].x; + if( m_CornersList[ic].x > max_x ) + max_x = m_CornersList[ic].x; + if( m_CornersList[ic].y < min_y ) + min_y = m_CornersList[ic].y; + if( m_CornersList[ic].y > max_y ) + max_y = m_CornersList[ic].y; } // Calculate spacing betwwen 2 hatch lines @@ -1409,7 +1419,7 @@ void CPolyLine::Hatch() min_a += offset; // now calculate and draw hatch lines - int nc = corner.size(); + int nc = m_CornersList.size(); // loop through hatch lines #define MAXPTS 200 // Usually we store only few values per one hatch line @@ -1433,22 +1443,22 @@ void CPolyLine::Hatch() { double x, y, x2, y2; int ok; - if( corner[ic].end_contour || ( ic == (int) (corner.size() - 1) ) ) + if( m_CornersList[ic].end_contour || ( ic == (int) (m_CornersList.size() - 1) ) ) { ok = FindLineSegmentIntersection( a, slope, - corner[ic].x, corner[ic].y, - corner[i_start_contour].x, - corner[i_start_contour].y, - side_style[ic], + m_CornersList[ic].x, m_CornersList[ic].y, + m_CornersList[i_start_contour].x, + m_CornersList[i_start_contour].y, + m_SideStyle[ic], &x, &y, &x2, &y2 ); i_start_contour = ic + 1; } else { ok = FindLineSegmentIntersection( a, slope, - corner[ic].x, corner[ic].y, - corner[ic + 1].x, corner[ic + 1].y, - side_style[ic], + m_CornersList[ic].x, m_CornersList[ic].y, + m_CornersList[ic + 1].x, m_CornersList[ic + 1].y, + m_SideStyle[ic], &x, &y, &x2, &y2 ); } if( ok ) @@ -1534,7 +1544,7 @@ bool CPolyLine::TestPointInside( int px, int py ) // if the tested point is inside only one contour, it is inside the whole polygon // (in fact inside the main outline, and outside all holes). // if inside 2 contours (the main outline + an hole), it is outside the poly. - int polycount = GetNumContours(); + int polycount = GetContoursCount(); bool inside = false; for( int icont = 0; icont < polycount; icont++ ) { @@ -1542,7 +1552,7 @@ bool CPolyLine::TestPointInside( int px, int py ) int iend = GetContourEnd( icont ); // Test this polygon: - if( TestPointInsidePolygon( corner, istart, iend, px, py) ) // test point inside the current polygon + if( TestPointInsidePolygon( m_CornersList, istart, iend, px, py) ) // test point inside the current polygon inside = not inside; } @@ -1557,9 +1567,9 @@ void CPolyLine::Copy( CPolyLine* src ) m_hatchStyle = src->m_hatchStyle; m_hatchPitch = src->m_hatchPitch; // copy corners, using vector copy - corner = src->corner; + m_CornersList = src->m_CornersList; // copy side styles, using vector copy - side_style = src->side_style; + m_SideStyle = src->m_SideStyle; } @@ -1598,19 +1608,19 @@ void CPolyLine::MoveOrigin( int x_off, int y_off ) // void CPolyLine::SetX( int ic, int x ) { - corner[ic].x = x; + m_CornersList[ic].x = x; } void CPolyLine::SetY( int ic, int y ) { - corner[ic].y = y; + m_CornersList[ic].y = y; } void CPolyLine::SetEndContour( int ic, bool end_contour ) { - corner[ic].end_contour = end_contour; + m_CornersList[ic].end_contour = end_contour; } @@ -1676,7 +1686,7 @@ int CPolyLine::Distance( wxPoint aStart, wxPoint aEnd, int aWidth ) return 0; int distance = INT_MAX; - int polycount = GetNumContours(); + int polycount = GetContoursCount(); for( int icont = 0; icont < polycount; icont++ ) { @@ -1732,7 +1742,7 @@ int CPolyLine::Distance( const wxPoint& aPoint ) return 0; int distance = INT_MAX; - int polycount = GetNumContours(); + int polycount = GetContoursCount(); for( int icont = 0; icont < polycount; icont++ ) { diff --git a/polygon/PolyLine.h b/polygon/PolyLine.h index a27478dae4..468bf09f78 100644 --- a/polygon/PolyLine.h +++ b/polygon/PolyLine.h @@ -31,18 +31,6 @@ enum }; - -/** - * Function ArmBoolEng - * Initialise parameters used in kbool - * @param aBooleng = pointer to the Bool_Engine to initialise - * @param aConvertHoles = mode for holes when a boolean operation is made - * true: holes are linked into outer contours by double overlapping segments - * false: holes are not linked: in this mode contours are added clockwise - * and polygons added counter clockwise are holes (default) - */ -void ArmBoolEng( Bool_Engine* aBooleng, bool aConvertHoles = false ); - class CRect { public: @@ -86,22 +74,22 @@ class CPolyPt : public wxPoint { public: CPolyPt( int aX = 0, int aY = 0, bool aEnd = false, int aUtility = 0 ) : - wxPoint( aX, aY ), end_contour( aEnd ), utility( aUtility ) + wxPoint( aX, aY ), end_contour( aEnd ), m_utility( aUtility ) {} /// Pure copy constructor is here to dis-ambiguate from the /// specialized CPolyPt( const wxPoint& ) constructor version below. CPolyPt( const CPolyPt& aPt ) : - wxPoint( aPt.x, aPt.y ), end_contour( aPt.end_contour ), utility( aPt.utility ) + wxPoint( aPt.x, aPt.y ), end_contour( aPt.end_contour ), m_utility( aPt.m_utility ) {} CPolyPt( const wxPoint& aPoint ) : - wxPoint( aPoint ), end_contour( false ), utility( 0 ) + wxPoint( aPoint ), end_contour( false ), m_utility( 0 ) {} bool end_contour; - int utility; + int m_utility; bool operator == (const CPolyPt& cpt2 ) const { return (x == cpt2.x) && (y == cpt2.y) && (end_contour == cpt2.end_contour); } @@ -116,7 +104,7 @@ public: class CPolyLine { public: - enum side_style { STRAIGHT, ARC_CW, ARC_CCW }; // side styles + enum m_SideStyle { STRAIGHT, ARC_CW, ARC_CCW }; // side styles enum hatch_style { NO_HATCH, DIAGONAL_FULL, DIAGONAL_EDGE }; // hatch styles // constructors/destructor @@ -173,21 +161,21 @@ public: int GetNumCorners(); int GetNumSides(); int GetClosed(); - int GetNumContours(); + int GetContoursCount(); int GetContour( int ic ); int GetContourStart( int icont ); int GetContourEnd( int icont ); int GetContourSize( int icont ); - int GetX( int ic ) const { return corner[ic].x; } - int GetY( int ic ) const { return corner[ic].y; } + int GetX( int ic ) const { return m_CornersList[ic].x; } + int GetY( int ic ) const { return m_CornersList[ic].y; } - const wxPoint& GetPos( int ic ) const { return corner[ic]; } + const wxPoint& GetPos( int ic ) const { return m_CornersList[ic]; } int GetEndContour( int ic ); - int GetUtility( int ic ) { return corner[ic].utility; }; - void SetUtility( int ic, int utility ) { corner[ic].utility = utility; }; + int GetUtility( int ic ) { return m_CornersList[ic].m_utility; }; + void SetUtility( int ic, int utility ) { m_CornersList[ic].m_utility = utility; }; int GetSideStyle( int is ); int GetHatchPitch() { return m_hatchPitch; } int GetDefaultHatchPitchMils() { return 20; } // default hatch pitch value in mils @@ -301,18 +289,18 @@ public: private: int m_layer; // layer to draw on - int m_Width; // lines width when drawing. Provided but not really used + int m_width; // lines width when drawing. Provided but not really used enum hatch_style m_hatchStyle; // hatch style, see enum above int m_hatchPitch; // for DIAGONAL_EDGE hatched outlines, basic distance between 2 hatch lines // and the len of eacvh segment // for DIAGONAL_FULL, the pitch is twice this value - int utility; + int m_utility; // a flag used in some calculations Bool_Engine* m_Kbool_Poly_Engine; // polygons set in kbool engine data public: - std::vector corner; // array of points for corners - std::vector side_style; // array of styles for sides - std::vector m_HatchLines; // hatch lines + std::vector m_CornersList; // array of points for corners + std::vector m_SideStyle; // array of styles for sides + std::vector m_HatchLines; // hatch lines showing the polygon area }; #endif // #ifndef POLYLINE_H From 99b90d2fa35689201bb4908c41caf6e2e5f72f73 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Wed, 25 Jul 2012 20:46:25 +0200 Subject: [PATCH 2/2] More work on a better support of polygons in Kicad (code cleaning). --- eeschema/lib_arc.cpp | 12 +- eeschema/lib_arc.h | 10 +- pcbnew/autorouter/solve.cpp | 4 +- pcbnew/class_board.cpp | 4 +- pcbnew/class_track.cpp | 2 +- pcbnew/class_zone.h | 2 +- pcbnew/clean.cpp | 35 +- pcbnew/editrack.cpp | 4 +- pcbnew/move_or_drag_track.cpp | 8 +- pcbnew/pcbnew.h | 4 +- pcbnew/zone_filling_algorithm.cpp | 41 +- ...nvert_brd_items_to_polygons_with_Boost.cpp | 4 - pcbnew/zones_test_and_combine_areas.cpp | 53 - polygon/PolyLine.cpp | 1004 ++++++++++------- polygon/PolyLine.h | 227 ++-- {pcbnew => polygon}/polygons_defs.h | 0 16 files changed, 745 insertions(+), 669 deletions(-) rename {pcbnew => polygon}/polygons_defs.h (100%) diff --git a/eeschema/lib_arc.cpp b/eeschema/lib_arc.cpp index f1fcb5f319..489b7a07eb 100644 --- a/eeschema/lib_arc.cpp +++ b/eeschema/lib_arc.cpp @@ -561,15 +561,15 @@ void LIB_ARC::BeginEdit( int aEditMode, const wxPoint aPosition ) // Drag either the start, end point or the outline if( HitTestPoints( m_ArcStart, aPosition, MINIMUM_SELECTION_DISTANCE ) ) { - m_editSelectPoint = START; + m_editSelectPoint = ARC_STATUS_START; } else if( HitTestPoints( m_ArcEnd, aPosition, MINIMUM_SELECTION_DISTANCE ) ) { - m_editSelectPoint = END; + m_editSelectPoint = ARC_STATUS_END; } else { - m_editSelectPoint = OUTLINE; + m_editSelectPoint = ARC_STATUS_OUTLINE; } m_editState = 0; @@ -619,12 +619,12 @@ void LIB_ARC::calcEdit( const wxPoint& aPosition ) wxPoint newCenterPoint, startPos, endPos; // Choose the point of the arc to be adjusted - if( m_editSelectPoint == START ) + if( m_editSelectPoint == ARC_STATUS_START ) { startPos = aPosition; endPos = m_ArcEnd; } - else if( m_editSelectPoint == END ) + else if( m_editSelectPoint == ARC_STATUS_END ) { endPos = aPosition; startPos = m_ArcStart; @@ -658,7 +658,7 @@ void LIB_ARC::calcEdit( const wxPoint& aPosition ) newCenterPoint = m_Pos; } - if( m_editSelectPoint == START || m_editSelectPoint == END ) + if( m_editSelectPoint == ARC_STATUS_START || m_editSelectPoint == ARC_STATUS_END ) { // Compute the new center point when the start/end points are modified wxPoint middlePoint = wxPoint( (startPos.x + endPos.x) / 2, diff --git a/eeschema/lib_arc.h b/eeschema/lib_arc.h index ab179a98ef..139c55335a 100644 --- a/eeschema/lib_arc.h +++ b/eeschema/lib_arc.h @@ -37,15 +37,15 @@ class TRANSFORM; class LIB_ARC : public LIB_ITEM { - enum SELECT_T + enum SELECT_T // When creating an arc: status of arc { - START, - END, - OUTLINE, + ARC_STATUS_START, + ARC_STATUS_END, + ARC_STATUS_OUTLINE, }; int m_Radius; - int m_t1; /* First radius angle of the arc in 0.1 degrees. */ + int m_t1; // First radius angle of the arc in 0.1 degrees. int m_t2; /* Second radius angle of the arc in 0.1 degrees. */ wxPoint m_ArcStart; wxPoint m_ArcEnd; /* Arc end position. */ diff --git a/pcbnew/autorouter/solve.cpp b/pcbnew/autorouter/solve.cpp index c3c00a2c0a..17f9ae35f6 100644 --- a/pcbnew/autorouter/solve.cpp +++ b/pcbnew/autorouter/solve.cpp @@ -1302,12 +1302,12 @@ static void AddNewTrace( PCB_EDIT_FRAME* pcbframe, wxDC* DC ) g_CurrentTrackList.PushBack( newTrack ); } - g_FirstTrackSegment->start = pcbframe->GetBoard()->GetPad( g_FirstTrackSegment, START ); + g_FirstTrackSegment->start = pcbframe->GetBoard()->GetPad( g_FirstTrackSegment, FLG_START ); if( g_FirstTrackSegment->start ) g_FirstTrackSegment->SetState( BEGIN_ONPAD, ON ); - g_CurrentTrackSegment->end = pcbframe->GetBoard()->GetPad( g_CurrentTrackSegment, END ); + g_CurrentTrackSegment->end = pcbframe->GetBoard()->GetPad( g_CurrentTrackSegment, FLG_END ); if( g_CurrentTrackSegment->end ) g_CurrentTrackSegment->SetState( END_ONPAD, ON ); diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index a495faf219..2da338f002 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -1681,7 +1681,7 @@ D_PAD* BOARD::GetPad( TRACK* aTrace, int aEndPoint ) int aLayerMask = GetLayerMask( aTrace->GetLayer() ); - if( aEndPoint == START ) + if( aEndPoint == FLG_START ) { aPosition = aTrace->m_Start; } @@ -2271,7 +2271,7 @@ TRACK* BOARD::CreateLockPoint( wxPoint& aPosition, TRACK* aSegment, PICKED_ITEMS aSegment->end = newTrack; aSegment->SetState( END_ONPAD, OFF ); - D_PAD * pad = GetPad( newTrack, START ); + D_PAD * pad = GetPad( newTrack, FLG_START ); if ( pad ) { diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp index 788072f471..120a64e398 100644 --- a/pcbnew/class_track.cpp +++ b/pcbnew/class_track.cpp @@ -1282,7 +1282,7 @@ TRACK* TRACK::GetTrace( TRACK* aStartTrace, TRACK* aEndTrace, int aEndPoint ) int ii; int max_dist; - if( aEndPoint == START ) + if( aEndPoint == FLG_START ) position = m_Start; else position = m_End; diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index e6e33cc06b..048125c9c2 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -613,7 +613,7 @@ private: /* set of filled polygons used to draw a zone as a filled area. * from outlines (m_Poly) but unlike m_Poly these filled polygons have no hole - * (they are* all in one piece) In very simple cases m_FilledPolysList is same + * (they are all in one piece) In very simple cases m_FilledPolysList is same * as m_Poly. In less simple cases (when m_Poly has holes) m_FilledPolysList is * a polygon equivalent to m_Poly, without holes but with extra outline segment * connecting "holes" with external main outline. In complex cases an outline diff --git a/pcbnew/clean.cpp b/pcbnew/clean.cpp index 4f22db1182..b93b88081f 100644 --- a/pcbnew/clean.cpp +++ b/pcbnew/clean.cpp @@ -272,7 +272,7 @@ static void DeleteUnconnectedTracks( PCB_EDIT_FRAME* aFrame ) if( (type_end & START_ON_PAD ) == 0 ) { - other = segment->GetTrace( aFrame->GetBoard()->m_Track, NULL, START ); + other = segment->GetTrace( aFrame->GetBoard()->m_Track, NULL, FLG_START ); if( other == NULL ) // Test a connection to zones { @@ -306,7 +306,7 @@ static void DeleteUnconnectedTracks( PCB_EDIT_FRAME* aFrame ) segment->SetState( BUSY, ON ); SEGVIA* via = (SEGVIA*) other; - other = via->GetTrace( aFrame->GetBoard()->m_Track, NULL, START ); + other = via->GetTrace( aFrame->GetBoard()->m_Track, NULL, FLG_START ); if( other == NULL ) { @@ -327,7 +327,7 @@ static void DeleteUnconnectedTracks( PCB_EDIT_FRAME* aFrame ) // if not connected to a pad, test if segment's END is connected to another track if( (type_end & END_ON_PAD ) == 0 ) { - other = segment->GetTrace( aFrame->GetBoard()->m_Track, NULL, END ); + other = segment->GetTrace( aFrame->GetBoard()->m_Track, NULL, FLG_END ); if( other == NULL ) // Test a connection to zones { @@ -362,7 +362,7 @@ static void DeleteUnconnectedTracks( PCB_EDIT_FRAME* aFrame ) segment->SetState( BUSY, ON ); SEGVIA* via = (SEGVIA*) other; - other = via->GetTrace( aFrame->GetBoard()->m_Track, NULL, END ); + other = via->GetTrace( aFrame->GetBoard()->m_Track, NULL, FLG_END ); if( other == NULL ) { @@ -486,7 +486,7 @@ static void clean_segments( PCB_EDIT_FRAME* aFrame ) // search for a possible point that connects on the START point of the segment for( segStart = segment->Next(); ; ) { - segStart = segment->GetTrace( segStart, NULL, START ); + segStart = segment->GetTrace( segStart, NULL, FLG_START ); if( segStart ) { @@ -500,7 +500,7 @@ static void clean_segments( PCB_EDIT_FRAME* aFrame ) // We must have only one segment connected segStart->SetState( BUSY, ON ); - other = segment->GetTrace( aFrame->GetBoard()->m_Track, NULL, START ); + other = segment->GetTrace( aFrame->GetBoard()->m_Track, NULL, FLG_START ); segStart->SetState( BUSY, OFF ); if( other == NULL ) @@ -514,7 +514,7 @@ static void clean_segments( PCB_EDIT_FRAME* aFrame ) if( flag ) // We have the starting point of the segment is connected to an other segment { segDelete = MergeColinearSegmentIfPossible( aFrame->GetBoard(), segment, segStart, - START ); + FLG_START ); if( segDelete ) { @@ -526,7 +526,7 @@ static void clean_segments( PCB_EDIT_FRAME* aFrame ) // search for a possible point that connects on the END point of the segment: for( segEnd = segment->Next(); ; ) { - segEnd = segment->GetTrace( segEnd, NULL, END ); + segEnd = segment->GetTrace( segEnd, NULL, FLG_END ); if( segEnd ) { @@ -538,7 +538,7 @@ static void clean_segments( PCB_EDIT_FRAME* aFrame ) // We must have only one segment connected segEnd->SetState( BUSY, ON ); - other = segment->GetTrace( aFrame->GetBoard()->m_Track, NULL, END ); + other = segment->GetTrace( aFrame->GetBoard()->m_Track, NULL, FLG_END ); segEnd->SetState( BUSY, OFF ); if( other == NULL ) @@ -554,7 +554,8 @@ static void clean_segments( PCB_EDIT_FRAME* aFrame ) if( flag & 2 ) // We have the ending point of the segment is connected to an other segment { - segDelete = MergeColinearSegmentIfPossible( aFrame->GetBoard(), segment, segEnd, END ); + segDelete = MergeColinearSegmentIfPossible( aFrame->GetBoard(), + segment, segEnd, FLG_END ); if( segDelete ) { @@ -643,7 +644,7 @@ TRACK* MergeColinearSegmentIfPossible( BOARD* aPcb, TRACK* aTrackRef, TRACK* aCa * (this function) is called when there is only 2 connected segments, *and if this point is not on a pad, it can be removed and the 2 segments will be merged */ - if( aEndType == START ) + if( aEndType == FLG_START ) { // We must not have a pad, which is a always terminal point for a track if( aPcb->GetPadFast( aTrackRef->m_Start, aTrackRef->ReturnMaskLayer() ) ) @@ -712,7 +713,7 @@ bool PCB_EDIT_FRAME::RemoveMisConnectedTracks() } else { - other = segment->GetTrace( GetBoard()->m_Track, NULL, START ); + other = segment->GetTrace( GetBoard()->m_Track, NULL, FLG_START ); if( other ) net_code_s = other->GetNet(); @@ -730,7 +731,7 @@ bool PCB_EDIT_FRAME::RemoveMisConnectedTracks() } else { - other = segment->GetTrace( GetBoard()->m_Track, NULL, END ); + other = segment->GetTrace( GetBoard()->m_Track, NULL, FLG_END ); if( other ) net_code_e = other->GetNet(); @@ -871,14 +872,14 @@ void ConnectDanglingEndToPad( PCB_EDIT_FRAME* aFrame ) if( aFrame->GetCanvas()->GetAbortRequest() ) return; - pad = aFrame->GetBoard()->GetPad( segment, START ); + pad = aFrame->GetBoard()->GetPad( segment, FLG_START ); if( pad ) { // test if the track start point is not exactly starting on the pad if( segment->m_Start != pad->GetPosition() ) { - if( segment->GetTrace( aFrame->GetBoard()->m_Track, NULL, START ) == NULL ) + if( segment->GetTrace( aFrame->GetBoard()->m_Track, NULL, FLG_START ) == NULL ) { TRACK* newTrack = (TRACK*) segment->Clone(); @@ -893,14 +894,14 @@ void ConnectDanglingEndToPad( PCB_EDIT_FRAME* aFrame ) } } - pad = aFrame->GetBoard()->GetPad( segment, END ); + pad = aFrame->GetBoard()->GetPad( segment, FLG_END ); if( pad ) { // test if the track end point is not exactly on the pad if( segment->m_End != pad->GetPosition() ) { - if( segment->GetTrace( aFrame->GetBoard()->m_Track, NULL, END ) == NULL ) + if( segment->GetTrace( aFrame->GetBoard()->m_Track, NULL, FLG_END ) == NULL ) { TRACK* newTrack = (TRACK*)segment->Clone(); diff --git a/pcbnew/editrack.cpp b/pcbnew/editrack.cpp index 472e1ca18d..b43eeacf44 100644 --- a/pcbnew/editrack.cpp +++ b/pcbnew/editrack.cpp @@ -263,7 +263,7 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* aDC ) newTrack->SetState( BEGIN_ONPAD | END_ONPAD, OFF ); - D_PAD* pad = GetBoard()->GetPad( previousTrack, END ); + D_PAD* pad = GetBoard()->GetPad( previousTrack, FLG_END ); if( pad ) { @@ -1042,7 +1042,7 @@ void DeleteNullTrackSegments( BOARD* pcb, DLIST& aTrackList ) while( track != NULL ) { TRACK* next_track = track->Next(); - LockPoint = pcb->GetPad( track, END ); + LockPoint = pcb->GetPad( track, FLG_END ); if( LockPoint ) { diff --git a/pcbnew/move_or_drag_track.cpp b/pcbnew/move_or_drag_track.cpp index b72387ccfe..c58c4fdbc4 100644 --- a/pcbnew/move_or_drag_track.cpp +++ b/pcbnew/move_or_drag_track.cpp @@ -887,7 +887,7 @@ void PCB_EDIT_FRAME::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC s_StartSegmentPresent = s_EndSegmentPresent = true; if( ( track->start == NULL ) || ( track->start->Type() == PCB_TRACE_T ) ) - TrackToStartPoint = track->GetTrace( GetBoard()->m_Track, NULL, START ); + TrackToStartPoint = track->GetTrace( GetBoard()->m_Track, NULL, FLG_START ); // Test if more than one segment is connected to this point if( TrackToStartPoint ) @@ -895,14 +895,14 @@ void PCB_EDIT_FRAME::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC TrackToStartPoint->SetState( BUSY, ON ); if( ( TrackToStartPoint->Type() == PCB_VIA_T ) - || track->GetTrace( GetBoard()->m_Track, NULL, START ) ) + || track->GetTrace( GetBoard()->m_Track, NULL, FLG_START ) ) error = true; TrackToStartPoint->SetState( BUSY, OFF ); } if( ( track->end == NULL ) || ( track->end->Type() == PCB_TRACE_T ) ) - TrackToEndPoint = track->GetTrace( GetBoard()->m_Track, NULL, END ); + TrackToEndPoint = track->GetTrace( GetBoard()->m_Track, NULL, FLG_END ); // Test if more than one segment is connected to this point if( TrackToEndPoint ) @@ -910,7 +910,7 @@ void PCB_EDIT_FRAME::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC TrackToEndPoint->SetState( BUSY, ON ); if( (TrackToEndPoint->Type() == PCB_VIA_T) - || track->GetTrace( GetBoard()->m_Track, NULL, END ) ) + || track->GetTrace( GetBoard()->m_Track, NULL, FLG_END ) ) error = true; TrackToEndPoint->SetState( BUSY, OFF ); diff --git a/pcbnew/pcbnew.h b/pcbnew/pcbnew.h index bc5df44334..78624ab4fd 100644 --- a/pcbnew/pcbnew.h +++ b/pcbnew/pcbnew.h @@ -25,8 +25,8 @@ #define VISIBLE_ONLY (1 << 3) ///< if module not on a visible layer, do not select -#define START 0 /* Flag used in locate routines */ -#define END 1 +#define FLG_START 0 // Flag used in locate routines +#define FLG_END 1 // Flag used in locate routines #define DIM_ANCRE_MODULE 3 /* Anchor size (footprint center) */ #define DIM_ANCRE_TEXTE 2 /* Anchor size (Text center) */ diff --git a/pcbnew/zone_filling_algorithm.cpp b/pcbnew/zone_filling_algorithm.cpp index e829c37f96..0a29804f28 100644 --- a/pcbnew/zone_filling_algorithm.cpp +++ b/pcbnew/zone_filling_algorithm.cpp @@ -89,39 +89,12 @@ int ZONE_CONTAINER::BuildFilledPolysListData( BOARD* aPcb, std::vector break; } - m_smoothedPoly->MakeKboolPoly( -1, -1, NULL, true ); - int count = 0; - while( m_smoothedPoly->GetKboolEngine()->StartPolygonGet() ) - { - CPolyPt corner( 0, 0, false ); - while( m_smoothedPoly->GetKboolEngine()->PolygonHasMorePoints() ) - { - corner.x = (int) m_smoothedPoly->GetKboolEngine()->GetPolygonXPoint(); - corner.y = (int) m_smoothedPoly->GetKboolEngine()->GetPolygonYPoint(); - corner.end_contour = false; - if( aCornerBuffer ) - aCornerBuffer->push_back( corner ); - else - m_FilledPolysList.push_back( corner ); - count++; - } - - corner.end_contour = true; - if( aCornerBuffer ) - { - aCornerBuffer->pop_back(); - aCornerBuffer->push_back( corner ); - } - else - { - m_FilledPolysList.pop_back(); - m_FilledPolysList.push_back( corner ); - } - m_smoothedPoly->GetKboolEngine()->EndPolygonGet(); - } - - m_smoothedPoly->FreeKboolEngine(); - + if( aCornerBuffer ) + ConvertPolysListWithHolesToOnePolygon( m_smoothedPoly->m_CornersList, + *aCornerBuffer ); + else + ConvertPolysListWithHolesToOnePolygon( m_smoothedPoly->m_CornersList, + m_FilledPolysList ); /* For copper layers, we now must add holes in the Polygon list. * holes are pads and tracks with their clearance area */ @@ -134,7 +107,7 @@ int ZONE_CONTAINER::BuildFilledPolysListData( BOARD* aPcb, std::vector Fill_Zone_Areas_With_Segments( ); } - return count; + return 1; } // Sort function to build filled zones diff --git a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp index 48e1e418b5..85d9012b4d 100644 --- a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp +++ b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp @@ -524,10 +524,6 @@ int CopyPolygonsFromKiPolygonListToFilledPolysList( ZONE_CONTAINER* aZone, corner.x = point.x(); corner.y = point.y(); corner.end_contour = false; - - // Flag this corner if starting a hole connection segment: - // This is used by draw functions to draw only useful segments (and not extra segments) - // corner.utility = (aBoolengine->GetPolygonPointEdgeType() == KB_FALSE_EDGE) ? 1 : 0; polysList.push_back( corner ); count++; } diff --git a/pcbnew/zones_test_and_combine_areas.cpp b/pcbnew/zones_test_and_combine_areas.cpp index fd5092d0bf..02a6652739 100644 --- a/pcbnew/zones_test_and_combine_areas.cpp +++ b/pcbnew/zones_test_and_combine_areas.cpp @@ -31,7 +31,6 @@ */ #include -#include #include #include #include @@ -779,58 +778,6 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_ return 1; } -/** - * Function CopyPolysListToKiPolygonWithHole - * converts the outline contours aPolysList to a KI_POLYGON_WITH_HOLES - * - * @param aPolysList = the list of corners of contours - * @param aPolygoneWithHole = a KI_POLYGON_WITH_HOLES to populate - */ -void CopyPolysListToKiPolygonWithHole( const std::vector& aPolysList, - KI_POLYGON_WITH_HOLES& aPolygoneWithHole ) -{ - unsigned corners_count = aPolysList.size(); - - std::vector cornerslist; - KI_POLYGON poly; - - // Enter main outline: this is the first contour - unsigned ic = 0; - while( ic < corners_count ) - { - const CPolyPt& corner = aPolysList[ic++]; - cornerslist.push_back( KI_POLY_POINT( corner.x, corner.y ) ); - - if( corner.end_contour ) - break; - } - - aPolygoneWithHole.set( cornerslist.begin(), cornerslist.end() ); - - // Enter holes: they are next contours (when exist) - if( ic < corners_count ) - { - KI_POLYGON_SET holePolyList; - while( ic < corners_count ) - { - cornerslist.clear(); - - while( ic < corners_count ) - { - const CPolyPt& corner = aPolysList[ic++]; - cornerslist.push_back( KI_POLY_POINT( corner.x, corner.y ) ); - - if( corner.end_contour ) - break; - } - - bpl::set_points( poly, cornerslist.begin(), cornerslist.end() ); - holePolyList.push_back( poly ); - } - aPolygoneWithHole.set_holes( holePolyList.begin(), holePolyList.end() ); - } -} - /** * Function CombineAreas diff --git a/polygon/PolyLine.cpp b/polygon/PolyLine.cpp index 99fa36f76c..57d6190edf 100644 --- a/polygon/PolyLine.cpp +++ b/polygon/PolyLine.cpp @@ -16,10 +16,10 @@ CPolyLine::CPolyLine() { - m_hatchStyle = NO_HATCH; - m_hatchPitch = 0; - m_width = 0; - m_utility = 0; + m_hatchStyle = NO_HATCH; + m_hatchPitch = 0; + m_width = 0; + m_utility = 0; m_Kbool_Poly_Engine = NULL; } @@ -29,10 +29,12 @@ CPolyLine::CPolyLine() CPolyLine::~CPolyLine() { UnHatch(); + if( m_Kbool_Poly_Engine ) delete m_Kbool_Poly_Engine; } + /** * Function armBoolEng * Initialise parameters used in kbool @@ -56,11 +58,11 @@ static void armBoolEng( Bool_Engine* aBooleng, bool aConvertHoles = false ); * @param bRetainArcs == true, try to retain arcs in polys * @return number of external contours, or -1 if error */ -int CPolyLine::NormalizeWithKbool( std::vector * aExtraPolyList, bool bRetainArcs ) +int CPolyLine::NormalizeWithKbool( std::vector* aExtraPolyList, bool bRetainArcs ) { std::vector arc_array; std::vector hole_array; // list of holes - std::vector * hole; // used to store corners for a given hole + std::vector* hole; // used to store corners for a given hole CPolyLine* polyline; int n_ext_cont = 0; // CPolyLine count @@ -71,9 +73,9 @@ int CPolyLine::NormalizeWithKbool( std::vector * aExtraPolyList, boo * True holes are combined if possible */ if( bRetainArcs ) - MakeKboolPoly( -1, -1, &arc_array ); + MakeKboolPoly( &arc_array ); else - MakeKboolPoly( -1, -1, NULL ); + MakeKboolPoly( NULL ); UnHatch(); @@ -92,10 +94,11 @@ int CPolyLine::NormalizeWithKbool( std::vector * aExtraPolyList, boo { hole = new std::vector; hole_array.push_back( hole ); + while( m_Kbool_Poly_Engine->PolygonHasMorePoints() ) // store hole { - int x = (int) m_Kbool_Poly_Engine->GetPolygonXPoint(); - int y = (int) m_Kbool_Poly_Engine->GetPolygonYPoint(); + int x = (int) m_Kbool_Poly_Engine->GetPolygonXPoint(); + int y = (int) m_Kbool_Poly_Engine->GetPolygonYPoint(); hole->push_back( x ); hole->push_back( y ); } @@ -108,11 +111,13 @@ int CPolyLine::NormalizeWithKbool( std::vector * aExtraPolyList, boo m_CornersList.clear(); m_SideStyle.clear(); bool first = true; + while( m_Kbool_Poly_Engine->PolygonHasMorePoints() ) { // foreach point in the polygon - int x = (int) m_Kbool_Poly_Engine->GetPolygonXPoint(); - int y = (int) m_Kbool_Poly_Engine->GetPolygonYPoint(); + int x = (int) m_Kbool_Poly_Engine->GetPolygonXPoint(); + int y = (int) m_Kbool_Poly_Engine->GetPolygonYPoint(); + if( first ) { first = false; @@ -131,10 +136,12 @@ int CPolyLine::NormalizeWithKbool( std::vector * aExtraPolyList, boo polyline = new CPolyLine; // create new poly aExtraPolyList->push_back( polyline ); // put it in array bool first = true; + while( m_Kbool_Poly_Engine->PolygonHasMorePoints() ) // read next external contour { - int x = (int) m_Kbool_Poly_Engine->GetPolygonXPoint(); - int y = (int) m_Kbool_Poly_Engine->GetPolygonYPoint(); + int x = (int) m_Kbool_Poly_Engine->GetPolygonXPoint(); + int y = (int) m_Kbool_Poly_Engine->GetPolygonYPoint(); + if( first ) { first = false; @@ -153,8 +160,9 @@ int CPolyLine::NormalizeWithKbool( std::vector * aExtraPolyList, boo // now add cutouts to the corresponding CPolyLine(s) for( unsigned ii = 0; ii < hole_array.size(); ii++ ) { - hole = (std::vector *)hole_array[ii]; - polyline = NULL; + hole = (std::vector*)hole_array[ii]; + polyline = NULL; + if( n_ext_cont == 1 ) { polyline = this; @@ -164,8 +172,9 @@ int CPolyLine::NormalizeWithKbool( std::vector * aExtraPolyList, boo // find the polygon that contains this hole // testing one corner inside is enought because a hole is entirely inside the polygon // so we test only the first corner - int x = (*hole)[0]; - int y = (*hole)[1]; + int x = (*hole)[0]; + int y = (*hole)[1]; + if( TestPointInside( x, y ) ) polyline = this; else if( aExtraPolyList ) @@ -187,8 +196,8 @@ int CPolyLine::NormalizeWithKbool( std::vector * aExtraPolyList, boo { for( unsigned ii = 0; ii< (*hole).size(); ii++ ) { - int x = (*hole)[ii]; ii++; - int y = (*hole)[ii]; + int x = (*hole)[ii]; ii++; + int y = (*hole)[ii]; polyline->AppendCorner( x, y, STRAIGHT, false ); } @@ -204,76 +213,21 @@ int CPolyLine::NormalizeWithKbool( std::vector * aExtraPolyList, boo // free hole list for( unsigned ii = 0; ii < hole_array.size(); ii++ ) - delete (std::vector *)hole_array[ii]; + delete (std::vector*)hole_array[ii]; return n_ext_cont; } -/** - * Function AddPolygonsToBoolEng - * Add a CPolyLine to a kbool engine, preparing a boolean op between polygons - * @param aStart_contour: starting contour number (-1 = all, 0 is the outlines of zone, > 1 = holes in zone - * @param aEnd_contour: ending contour number (-1 = all after aStart_contour) - * @param arc_array: arc converted to poly segments (NULL if not exists) - * @param aBooleng : pointer on a bool engine (handle a set of polygons) - * @param aGroup : group to fill (aGroup = GROUP_A or GROUP_B) operations are made between GROUP_A and GROUP_B - */ -int CPolyLine::AddPolygonsToBoolEng( Bool_Engine* aBooleng, - GroupType aGroup, - int aStart_contour, - int aEnd_contour, - std::vector * arc_array ) -{ - int count = 0; - - if( (aGroup != GROUP_A) && (aGroup != GROUP_B ) ) - return 0; //Error ! - - /* Convert the current polyline contour to a kbool polygon: */ - MakeKboolPoly( aStart_contour, aEnd_contour, arc_array ); - - /* add the resulting kbool set of polygons to the current kcool engine */ - while( m_Kbool_Poly_Engine->StartPolygonGet() ) - { - if( aBooleng->StartPolygonAdd( GROUP_A ) ) - { - while( m_Kbool_Poly_Engine->PolygonHasMorePoints() ) - { - int x = (int) m_Kbool_Poly_Engine->GetPolygonXPoint(); - int y = (int) m_Kbool_Poly_Engine->GetPolygonYPoint(); - aBooleng->AddPoint( x, y ); - count++; - } - - aBooleng->EndPolygonAdd(); - } - m_Kbool_Poly_Engine->EndPolygonGet(); - } - - delete m_Kbool_Poly_Engine; - m_Kbool_Poly_Engine = NULL; - - return count; -} - - /** * Function MakeKboolPoly * fill a kbool engine with a closed polyline contour * approximates arcs with multiple straight-line segments - * @param aStart_contour: starting contour number (-1 = all, 0 is the outlines of zone, > 1 = holes in zone - * @param aEnd_contour: ending contour number (-1 = all after aStart_contour) * combining intersecting contours if possible * @param arc_array : return corners computed from arcs approximations in arc_array - * @param aConvertHoles = mode for holes when a boolean operation is made - * true: holes are linked into outer contours by double overlapping segments - * false: holes are not linked: in this mode contours are added clockwise - * and polygons added counter clockwise are holes (default) * @return error: 0 if Ok, 1 if error */ -int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector * arc_array, - bool aConvertHoles ) +int CPolyLine::MakeKboolPoly( std::vector* arc_array ) { if( m_Kbool_Poly_Engine ) { @@ -281,65 +235,40 @@ int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector< m_Kbool_Poly_Engine = NULL; } - int polycount = GetContoursCount(); - - if( !GetClosed() && (aStart_contour == (polycount - 1) || aStart_contour == -1) ) + if( !GetClosed() ) return 1; // error int n_arcs = 0; + int polycount = GetContoursCount(); + int last_contour = polycount - 1; - int first_contour = aStart_contour; - int last_contour = aEnd_contour; - if( aStart_contour == -1 ) - { - first_contour = 0; - last_contour = polycount - 1; - } - if( aEnd_contour == -1 ) - { - last_contour = polycount - 1; - } if( arc_array ) arc_array->clear(); + int iarc = 0; - for( int icont = first_contour; icont<=last_contour; icont++ ) + + for( int icont = 0; icont<=last_contour; icont++ ) { // Fill a kbool engine for this contour, // and combine it with previous contours Bool_Engine* booleng = new Bool_Engine(); - armBoolEng( booleng, aConvertHoles ); - - if( m_Kbool_Poly_Engine ) // a previous contour exists. Put it in new engine - { - while( m_Kbool_Poly_Engine->StartPolygonGet() ) - { - if( booleng->StartPolygonAdd( GROUP_A ) ) - { - while( m_Kbool_Poly_Engine->PolygonHasMorePoints() ) - { - int x = (int) m_Kbool_Poly_Engine->GetPolygonXPoint(); - int y = (int) m_Kbool_Poly_Engine->GetPolygonYPoint(); - booleng->AddPoint( x, y ); - } - - booleng->EndPolygonAdd(); - } - m_Kbool_Poly_Engine->EndPolygonGet(); - } - } + armBoolEng( booleng, false ); // first, calculate number of vertices in contour int n_vertices = 0; - int ic_st = GetContourStart( icont ); - int ic_end = GetContourEnd( icont ); + int ic_st = GetContourStart( icont ); + int ic_end = GetContourEnd( icont ); + if( !booleng->StartPolygonAdd( GROUP_B ) ) { wxASSERT( 0 ); - return 1; //error + return 1; // error } + for( int ic = ic_st; ic<=ic_end; ic++ ) { int style = m_SideStyle[ic]; + if( style == STRAIGHT ) n_vertices++; else @@ -353,22 +282,25 @@ int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector< // now enter this contour to booleng int ivtx = 0; + for( int ic = ic_st; ic<=ic_end; ic++ ) { - int style = m_SideStyle[ic]; - int x1 = m_CornersList[ic].x; - int y1 = m_CornersList[ic].y; + int style = m_SideStyle[ic]; + int x1 = m_CornersList[ic].x; + int y1 = m_CornersList[ic].y; int x2, y2; + if( ic < ic_end ) { - x2 = m_CornersList[ic + 1].x; - y2 = m_CornersList[ic + 1].y; + x2 = m_CornersList[ic + 1].x; + y2 = m_CornersList[ic + 1].y; } else { - x2 = m_CornersList[ic_st].x; - y2 = m_CornersList[ic_st].y; + x2 = m_CornersList[ic_st].x; + y2 = m_CornersList[ic_st].y; } + if( style == STRAIGHT ) { booleng->AddPoint( x1, y1 ); @@ -377,44 +309,45 @@ int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector< else { // style is arc_cw or arc_ccw - int n; // number of steps for arcs + int n; // number of steps for arcs n = CArc::ARC_STEPS; - double xo, yo, theta1, theta2, a, b; - a = fabs( (double) (x1 - x2) ); - b = fabs( (double) (y1 - y2) ); + double xo, yo, theta1, theta2, a, b; + a = fabs( (double) (x1 - x2) ); + b = fabs( (double) (y1 - y2) ); + if( style == CPolyLine::ARC_CW ) { // clockwise arc (ie.quadrant of ellipse) if( x2 > x1 && y2 > y1 ) { // first quadrant, draw second quadrant of ellipse - xo = x2; - yo = y1; - theta1 = M_PI; - theta2 = M_PI / 2.0; + xo = x2; + yo = y1; + theta1 = M_PI; + theta2 = M_PI / 2.0; } else if( x2 < x1 && y2 > y1 ) { // second quadrant, draw third quadrant of ellipse - xo = x1; - yo = y2; - theta1 = 3.0 * M_PI / 2.0; - theta2 = M_PI; + xo = x1; + yo = y2; + theta1 = 3.0 * M_PI / 2.0; + theta2 = M_PI; } else if( x2 < x1 && y2 < y1 ) { // third quadrant, draw fourth quadrant of ellipse - xo = x2; - yo = y1; - theta1 = 2.0 * M_PI; - theta2 = 3.0 * M_PI / 2.0; + xo = x2; + yo = y1; + theta1 = 2.0 * M_PI; + theta2 = 3.0 * M_PI / 2.0; } else { - xo = x1; // fourth quadrant, draw first quadrant of ellipse - yo = y2; - theta1 = M_PI / 2.0; - theta2 = 0.0; + xo = x1; // fourth quadrant, draw first quadrant of ellipse + yo = y2; + theta1 = M_PI / 2.0; + theta2 = 0.0; } } else @@ -422,31 +355,31 @@ int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector< // counter-clockwise arc if( x2 > x1 && y2 > y1 ) { - xo = x1; // first quadrant, draw fourth quadrant of ellipse - yo = y2; - theta1 = 3.0 * M_PI / 2.0; - theta2 = 2.0 * M_PI; + xo = x1; // first quadrant, draw fourth quadrant of ellipse + yo = y2; + theta1 = 3.0 * M_PI / 2.0; + theta2 = 2.0 * M_PI; } else if( x2 < x1 && y2 > y1 ) { - xo = x2; // second quadrant - yo = y1; - theta1 = 0.0; - theta2 = M_PI / 2.0; + xo = x2; // second quadrant + yo = y1; + theta1 = 0.0; + theta2 = M_PI / 2.0; } else if( x2 < x1 && y2 < y1 ) { - xo = x1; // third quadrant - yo = y2; - theta1 = M_PI / 2.0; - theta2 = M_PI; + xo = x1; // third quadrant + yo = y2; + theta1 = M_PI / 2.0; + theta2 = M_PI; } else { - xo = x2; // fourth quadrant - yo = y1; - theta1 = M_PI; - theta2 = 3.0 * M_PI / 2.0; + xo = x2; // fourth quadrant + yo = y1; + theta1 = M_PI; + theta2 = 3.0 * M_PI / 2.0; } } @@ -456,23 +389,26 @@ int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector< CArc new_arc; new_arc.style = style; new_arc.n_steps = n; - new_arc.xi = x1; - new_arc.yi = y1; - new_arc.xf = x2; - new_arc.yf = y2; + new_arc.xi = x1; + new_arc.yi = y1; + new_arc.xf = x2; + new_arc.yf = y2; arc_array->push_back( new_arc ); iarc++; } + for( int is = 0; isAddPoint( x, y ); ivtx++; } @@ -484,7 +420,7 @@ int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector< wxASSERT( 0 ); } - // close list added to the bool engine + // close list added to the bool engine booleng->EndPolygonAdd(); /* now combine polygon to the previous polygons. @@ -494,7 +430,7 @@ int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector< * Others polygons are substract to the outline and corners will be ordered counter clockwise * by the kbool engine */ - if( aStart_contour <= 0 && icont != 0 ) // substract hole to outside ( if the outline contour is take in account) + if( icont != 0 ) // substract hole to outside ( if the outline contour is take in account) { booleng->Do_Operation( BOOL_A_SUB_B ); } @@ -506,6 +442,7 @@ int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector< // now use result as new polygon (delete the old one if exists) if( m_Kbool_Poly_Engine ) delete m_Kbool_Poly_Engine; + m_Kbool_Poly_Engine = booleng; } @@ -528,55 +465,56 @@ void armBoolEng( Bool_Engine* aBooleng, bool aConvertHoles ) // input points are scaled up with GetDGrid() * GetGrid() // DGRID is only meant to make fractional parts of input data which - /* - The input data scaled up with DGrid is related to the accuracy the user has in his input data. - User data with a minimum accuracy of 0.001, means set the DGrid to 1000. - The input data may contain data with a minimum accuracy much smaller, but by setting the DGrid - everything smaller than 1/DGrid is rounded. + /* + * The input data scaled up with DGrid is related to the accuracy the user has in his input data. + * User data with a minimum accuracy of 0.001, means set the DGrid to 1000. + * The input data may contain data with a minimum accuracy much smaller, but by setting the DGrid + * everything smaller than 1/DGrid is rounded. + * + * DGRID is only meant to make fractional parts of input data which can be + * doubles, part of the integers used in vertexes within the boolean algorithm. + * And therefore DGRID bigger than 1 is not usefull, you would only loose accuracy. + * Within the algorithm all input data is multiplied with DGRID, and the result + * is rounded to an integer. + */ + double DGRID = 1000.0; // round coordinate X or Y value in calculations to this (initial value = 1000.0 in kbool example) + // kbool uses DGRID to convert float user units to integer + // kbool unit = (int)(user unit * DGRID) + // Note: in kicad, coordinates are already integer so DGRID could be set to 1 + // we can choose 1.0, + // but choose DGRID = 1000.0 solves some filling problems +// (perhaps because this allows a better precision in kbool internal calculations - DGRID is only meant to make fractional parts of input data which can be - doubles, part of the integers used in vertexes within the boolean algorithm. - And therefore DGRID bigger than 1 is not usefull, you would only loose accuracy. - Within the algorithm all input data is multiplied with DGRID, and the result - is rounded to an integer. - */ - double DGRID = 1000.0; // round coordinate X or Y value in calculations to this (initial value = 1000.0 in kbool example) - // kbool uses DGRID to convert float user units to integer - // kbool unit = (int)(user unit * DGRID) - // Note: in kicad, coordinates are already integer so DGRID could be set to 1 - // we can choose 1.0, - // but choose DGRID = 1000.0 solves some filling problems -// (perhaps because this allows a better precision in kbool internal calculations - - double MARGE = 1.0/DGRID; // snap with in this range points to lines in the intersection routines - // should always be >= 1/DGRID a MARGE >= 10/DGRID is ok - // this is also used to remove small segments and to decide when - // two segments are in line. ( initial value = 0.001 ) - // For kicad we choose MARGE = 1/DGRID + double MARGE = 1.0 / DGRID; // snap with in this range points to lines in the intersection routines + // should always be >= 1/DGRID a MARGE >= 10/DGRID is ok + // this is also used to remove small segments and to decide when + // two segments are in line. ( initial value = 0.001 ) + // For kicad we choose MARGE = 1/DGRID double CORRECTIONFACTOR = 0.0; // correct the polygons by this number: used in BOOL_CORRECTION operation // this operation shrinks a polygon if CORRECTIONFACTOR < 0 // or stretch it if CORRECTIONFACTOR > 0 // the size change is CORRECTIONFACTOR (holes are correctly handled) - double CORRECTIONABER = 1.0; // the accuracy for the rounded shapes used in correction - double ROUNDFACTOR = 1.5; // when will we round the correction shape to a circle - double SMOOTHABER = 10.0; // accuracy when smoothing a polygon - double MAXLINEMERGE = 1000.0; // leave as is, segments of this length in smoothen + double CORRECTIONABER = 1.0; // the accuracy for the rounded shapes used in correction + double ROUNDFACTOR = 1.5; // when will we round the correction shape to a circle + double SMOOTHABER = 10.0; // accuracy when smoothing a polygon + double MAXLINEMERGE = 1000.0; // leave as is, segments of this length in smoothen - /* - Grid makes sure that the integer data used within the algorithm has room for extra intersections - smaller than the smallest number within the input data. - The input data scaled up with DGrid is related to the accuracy the user has in his input data. - Another scaling with Grid is applied on top of it to create space in the integer number for - even smaller numbers. - */ - int GRID = (int) ( 10000.0 / DGRID ); // initial value = 10000 in kbool example but we use - // 10000/DGRID because the scaling is made by DGRID - // on integer pcbnew units and the global scaling - // ( GRID*DGRID) must be < 30000 to avoid overflow - // in calculations (made in long long in kbool) - if ( GRID <= 1 ) // Cannot be null! + /* + * Grid makes sure that the integer data used within the algorithm has room for extra intersections + * smaller than the smallest number within the input data. + * The input data scaled up with DGrid is related to the accuracy the user has in his input data. + * Another scaling with Grid is applied on top of it to create space in the integer number for + * even smaller numbers. + */ + int GRID = (int) ( 10000.0 / DGRID ); // initial value = 10000 in kbool example but we use + + // 10000/DGRID because the scaling is made by DGRID + // on integer pcbnew units and the global scaling + // ( GRID*DGRID) must be < 30000 to avoid overflow + // in calculations (made in long long in kbool) + if( GRID <= 1 ) // Cannot be null! GRID = 1; aBooleng->SetMarge( MARGE ); @@ -591,9 +529,9 @@ void armBoolEng( Bool_Engine* aBooleng, bool aConvertHoles ) if( aConvertHoles ) { -#if 1 // Can be set to 1 for kbool version >= 2.1, must be set to 0 for previous versions - // SetAllowNonTopHoleLinking() exists only in kbool >= 2.1 - aBooleng->SetAllowNonTopHoleLinking( false ); // Default = true, but i have problems (filling errors) when true +#if 1 // Can be set to 1 for kbool version >= 2.1, must be set to 0 for previous versions + // SetAllowNonTopHoleLinking() exists only in kbool >= 2.1 + aBooleng->SetAllowNonTopHoleLinking( false ); // Default = true, but i have problems (filling errors) when true #endif aBooleng->SetLinkHoles( true ); // holes will be connected by double overlapping segments aBooleng->SetOrientationEntryMode( false ); // all polygons are contours, not holes @@ -606,7 +544,7 @@ void armBoolEng( Bool_Engine* aBooleng, bool aConvertHoles ) } -int CPolyLine::NormalizeAreaOutlines( std::vector * pa, bool bRetainArcs ) +int CPolyLine::NormalizeAreaOutlines( std::vector* pa, bool bRetainArcs ) { return NormalizeWithKbool( pa, bRetainArcs ); } @@ -615,13 +553,14 @@ int CPolyLine::NormalizeAreaOutlines( std::vector * pa, bool bRetain // Restore arcs to a polygon where they were replaced with steps // If pa != NULL, also use polygons in pa array // -int CPolyLine::RestoreArcs( std::vector * arc_array, std::vector * pa ) +int CPolyLine::RestoreArcs( std::vector* arc_array, std::vector* pa ) { // get poly info int n_polys = 1; if( pa ) n_polys += pa->size(); + CPolyLine* poly; // undraw polys and clear m_utility flag for all corners @@ -631,7 +570,9 @@ int CPolyLine::RestoreArcs( std::vector * arc_array, std::vectorUnHatch(); + for( int ic = 0; icGetNumCorners(); ic++ ) poly->SetUtility( ic, 0 ); @@ -639,9 +580,10 @@ int CPolyLine::RestoreArcs( std::vector * arc_array, std::vectorsize(); iarc++ ) { int arc_xi = (*arc_array)[iarc].xi; @@ -659,52 +601,65 @@ int CPolyLine::RestoreArcs( std::vector * arc_array, std::vectorGetContoursCount(); + for( int icont = 0; icont < polycount; icont++ ) { - int ic_start = poly->GetContourStart( icont ); - int ic_end = poly->GetContourEnd( icont ); + int ic_start = poly->GetContourStart( icont ); + int ic_end = poly->GetContourEnd( icont ); + if( (ic_end - ic_start) > n_steps ) { for( int ic = ic_start; ic<=ic_end; ic++ ) { int ic_next = ic + 1; + if( ic_next > ic_end ) ic_next = ic_start; - int xi = poly->GetX( ic ); - int yi = poly->GetY( ic ); + + int xi = poly->GetX( ic ); + int yi = poly->GetY( ic ); + if( xi == arc_xi && yi == arc_yi ) { // test for forward arc int ic2 = ic + n_steps; + if( ic2 > ic_end ) ic2 = ic2 - ic_end + ic_start - 1; - int xf = poly->GetX( ic2 ); - int yf = poly->GetY( ic2 ); + + int xf = poly->GetX( ic2 ); + int yf = poly->GetY( ic2 ); + if( xf == arc_xf && yf == arc_yf ) { // arc from ic to ic2 - bFound = true; - arc_start = ic; - arc_end = ic2; + bFound = true; + arc_start = ic; + arc_end = ic2; } else { // try reverse arc ic2 = ic - n_steps; + if( ic2 < ic_start ) ic2 = ic2 - ic_start + ic_end + 1; - xf = poly->GetX( ic2 ); - yf = poly->GetY( ic2 ); + + xf = poly->GetX( ic2 ); + yf = poly->GetY( ic2 ); + if( xf == arc_xf && yf == arc_yf ) { // arc from ic2 to ic - bFound = true; - arc_start = ic2; - arc_end = ic; - style = 3 - style; + bFound = true; + arc_start = ic2; + arc_end = ic; + style = 3 - style; } } + if( bFound ) { poly->m_SideStyle[arc_start] = style; @@ -714,7 +669,9 @@ int CPolyLine::RestoreArcs( std::vector * arc_array, std::vector ic_end ) i = ic_start; + poly->SetUtility( i, 1 ); + if( i == ic_end ) i = ic_start; else @@ -724,10 +681,12 @@ int CPolyLine::RestoreArcs( std::vector * arc_array, std::vector * arc_array, std::vectorGetNumCorners() - 1; ic>=0; ic-- ) { if( poly->GetUtility( ic ) ) @@ -761,20 +721,20 @@ int CPolyLine::RestoreArcs( std::vector * arc_array, std::vector 0 && !m_CornersList[m_CornersList.size() - 1].end_contour ) m_SideStyle[m_CornersList.size() - 1] = style; + if( bDraw ) Hatch(); } @@ -810,9 +772,11 @@ void CPolyLine::Close( int style, bool bDraw ) { wxASSERT( 0 ); } + UnHatch(); m_SideStyle[m_CornersList.size() - 1] = style; m_CornersList[m_CornersList.size() - 1].end_contour = true; + if( bDraw ) Hatch(); } @@ -834,10 +798,10 @@ void CPolyLine::MoveCorner( int ic, int x, int y ) void CPolyLine::DeleteCorner( int ic, bool bDraw ) { UnHatch(); - int icont = GetContour( ic ); - int istart = GetContourStart( icont ); - int iend = GetContourEnd( icont ); - bool bClosed = icont < GetContoursCount() - 1 || GetClosed(); + int icont = GetContour( ic ); + int istart = GetContourStart( icont ); + int iend = GetContourEnd( icont ); + bool bClosed = icont < GetContoursCount() - 1 || GetClosed(); if( !bClosed ) { @@ -852,14 +816,17 @@ void CPolyLine::DeleteCorner( int ic, bool bDraw ) // closed contour m_CornersList.erase( m_CornersList.begin() + ic ); m_SideStyle.erase( m_SideStyle.begin() + ic ); + if( ic == iend ) m_CornersList[ic - 1].end_contour = true; } + if( bClosed && GetContourSize( icont ) < 3 ) { // delete the entire contour RemoveContour( icont ); } + if( bDraw ) Hatch(); } @@ -876,10 +843,11 @@ void CPolyLine::RemoveContour( int icont ) */ { UnHatch(); - int istart = GetContourStart( icont ); - int iend = GetContourEnd( icont ); + int istart = GetContourStart( icont ); + int iend = GetContourEnd( icont ); int polycount = GetContoursCount(); + if( icont == 0 && polycount == 1 ) { // remove the only contour @@ -900,6 +868,7 @@ void CPolyLine::RemoveContour( int icont ) m_SideStyle.erase( m_SideStyle.begin() + ic ); } } + Hatch(); } @@ -915,64 +884,66 @@ CPolyLine* CPolyLine::Chamfer( unsigned int aDistance ) } int polycount = GetContoursCount(); + for( int contour = 0; contour < polycount; contour++ ) { - unsigned int startIndex = GetContourStart( contour ); - unsigned int endIndex = GetContourEnd( contour ); + unsigned int startIndex = GetContourStart( contour ); + unsigned int endIndex = GetContourEnd( contour ); for( unsigned int index = startIndex; index <= endIndex; index++ ) { - int x1, y1, nx, ny; - long long xa, ya, xb, yb; + int x1, y1, nx, ny; + long long xa, ya, xb, yb; - x1 = m_CornersList[index].x; - y1 = m_CornersList[index].y; + x1 = m_CornersList[index].x; + y1 = m_CornersList[index].y; if( index == startIndex ) { - xa = m_CornersList[endIndex].x - x1; - ya = m_CornersList[endIndex].y - y1; + xa = m_CornersList[endIndex].x - x1; + ya = m_CornersList[endIndex].y - y1; } else { - xa = m_CornersList[index-1].x - x1; - ya = m_CornersList[index-1].y - y1; + xa = m_CornersList[index - 1].x - x1; + ya = m_CornersList[index - 1].y - y1; } if( index == endIndex ) { - xb = m_CornersList[startIndex].x - x1; - yb = m_CornersList[startIndex].y - y1; + xb = m_CornersList[startIndex].x - x1; + yb = m_CornersList[startIndex].y - y1; } else { - xb = m_CornersList[index+1].x - x1; - yb = m_CornersList[index+1].y - y1; + xb = m_CornersList[index + 1].x - x1; + yb = m_CornersList[index + 1].y - y1; } - unsigned int lena = (unsigned int)sqrt( (double)(xa*xa + ya*ya) ); - unsigned int lenb = (unsigned int)sqrt( (double)(xb*xb + yb*yb) ); - unsigned int distance = aDistance; + unsigned int lena = (unsigned int) sqrt( (double) (xa * xa + ya * ya) ); + unsigned int lenb = (unsigned int) sqrt( (double) (xb * xb + yb * yb) ); + unsigned int distance = aDistance; // Chamfer one half of an edge at most - if( 0.5*lena < distance ) - distance = (unsigned int)(0.5*(double)lena); + if( 0.5 * lena < distance ) + distance = (unsigned int) (0.5 * (double) lena); - if( 0.5*lenb < distance ) - distance = (unsigned int)(0.5*(double)lenb); + if( 0.5 * lenb < distance ) + distance = (unsigned int) (0.5 * (double) lenb); - nx = (int) ( (double) (distance*xa)/sqrt( (double) (xa*xa + ya*ya) ) ); - ny = (int) ( (double) (distance*ya)/sqrt( (double) (xa*xa + ya*ya) ) ); + nx = (int) ( (double) (distance * xa) / sqrt( (double) (xa * xa + ya * ya) ) ); + ny = (int) ( (double) (distance * ya) / sqrt( (double) (xa * xa + ya * ya) ) ); if( index == startIndex ) newPoly->Start( GetLayer(), x1 + nx, y1 + ny, GetHatchStyle() ); else newPoly->AppendCorner( x1 + nx, y1 + ny ); - nx = (int) ( (double) (distance*xb)/sqrt( (double) (xb*xb + yb*yb) ) ); - ny = (int) ( (double) (distance*yb)/sqrt( (double) (xb*xb + yb*yb) ) ); + nx = (int) ( (double) (distance * xb) / sqrt( (double) (xb * xb + yb * yb) ) ); + ny = (int) ( (double) (distance * yb) / sqrt( (double) (xb * xb + yb * yb) ) ); newPoly->AppendCorner( x1 + nx, y1 + ny ); } + newPoly->Close(); } @@ -991,114 +962,119 @@ CPolyLine* CPolyLine::Fillet( unsigned int aRadius, unsigned int aSegments ) } int polycount = GetContoursCount(); + for( int contour = 0; contour < polycount; contour++ ) { - unsigned int startIndex = GetContourStart( contour ); - unsigned int endIndex = GetContourEnd( contour ); + unsigned int startIndex = GetContourStart( contour ); + unsigned int endIndex = GetContourEnd( contour ); for( unsigned int index = startIndex; index <= endIndex; index++ ) { + int x1, y1; // Current vertex + long long xa, ya; // Previous vertex + long long xb, yb; // Next vertex + double nx, ny; - int x1, y1; // Current vertex - long long xa, ya; // Previous vertex - long long xb, yb; // Next vertex - double nx, ny; - - x1 = m_CornersList[index].x; - y1 = m_CornersList[index].y; + x1 = m_CornersList[index].x; + y1 = m_CornersList[index].y; if( index == startIndex ) { - xa = m_CornersList[endIndex].x - x1; - ya = m_CornersList[endIndex].y - y1; + xa = m_CornersList[endIndex].x - x1; + ya = m_CornersList[endIndex].y - y1; } else { - xa = m_CornersList[index-1].x - x1; - ya = m_CornersList[index-1].y - y1; + xa = m_CornersList[index - 1].x - x1; + ya = m_CornersList[index - 1].y - y1; } if( index == endIndex ) { - xb = m_CornersList[startIndex].x - x1; - yb = m_CornersList[startIndex].y - y1; + xb = m_CornersList[startIndex].x - x1; + yb = m_CornersList[startIndex].y - y1; } else { - xb = m_CornersList[index+1].x - x1; - yb = m_CornersList[index+1].y - y1; + xb = m_CornersList[index + 1].x - x1; + yb = m_CornersList[index + 1].y - y1; } - double lena = sqrt( (double) (xa*xa + ya*ya) ); - double lenb = sqrt( (double) (xb*xb + yb*yb) ); - double cosine = ( xa*xb + ya*yb )/( lena*lenb ); + double lena = sqrt( (double) (xa * xa + ya * ya) ); + double lenb = sqrt( (double) (xb * xb + yb * yb) ); + double cosine = ( xa * xb + ya * yb ) / ( lena * lenb ); - unsigned int radius = aRadius; - double denom = sqrt( 2.0/( 1+cosine )-1 ); + unsigned int radius = aRadius; + double denom = sqrt( 2.0 / ( 1 + cosine ) - 1 ); // Limit rounding distance to one half of an edge - if( 0.5*lena*denom < radius ) - radius = (unsigned int)(0.5*lena*denom); + if( 0.5 * lena * denom < radius ) + radius = (unsigned int) (0.5 * lena * denom); - if( 0.5*lenb*denom < radius ) - radius = (unsigned int)(0.5*lenb*denom); + if( 0.5 * lenb * denom < radius ) + radius = (unsigned int) (0.5 * lenb * denom); // Calculate fillet arc absolute center point (xc, yx) - double k = radius / sqrt( .5*( 1-cosine ) ); - double lenab = sqrt( ( xa/lena + xb/lenb )*( xa/lena + xb/lenb ) + - ( ya/lena + yb/lenb )*( ya/lena + yb/lenb ) ); - double xc = x1 + k*( xa/lena + xb/lenb )/lenab; - double yc = y1 + k*( ya/lena + yb/lenb )/lenab; + double k = radius / sqrt( .5 * ( 1 - cosine ) ); + double lenab = sqrt( ( xa / lena + xb / lenb ) * ( xa / lena + xb / lenb ) + + ( ya / lena + yb / lenb ) * ( ya / lena + yb / lenb ) ); + double xc = x1 + k * ( xa / lena + xb / lenb ) / lenab; + double yc = y1 + k * ( ya / lena + yb / lenb ) / lenab; // Calculate arc start and end vectors - k = radius / sqrt( 2/( 1+cosine )-1 ); - double xs = x1 + k*xa/lena - xc; - double ys = y1 + k*ya/lena - yc; - double xe = x1 + k*xb/lenb - xc; - double ye = y1 + k*yb/lenb - yc; + k = radius / sqrt( 2 / ( 1 + cosine ) - 1 ); + double xs = x1 + k * xa / lena - xc; + double ys = y1 + k * ya / lena - yc; + double xe = x1 + k * xb / lenb - xc; + double ye = y1 + k * yb / lenb - yc; // Cosine of arc angle - double argument = ( xs*xe + ys*ye ) / ( radius*radius ); + double argument = ( xs * xe + ys * ye ) / ( radius * radius ); if( argument < -1 ) // Just in case... argument = -1; else if( argument > 1 ) argument = 1; - double arcAngle = acos( argument ); + double arcAngle = acos( argument ); // Calculate the number of segments - double tempSegments = (double)aSegments * ( arcAngle / ( 2*M_PI ) ); + double tempSegments = (double) aSegments * ( arcAngle / ( 2 * M_PI ) ); - if( tempSegments - (int)tempSegments > 0 ) + if( tempSegments - (int) tempSegments > 0 ) tempSegments++; - unsigned int segments = (unsigned int) tempSegments; - double deltaAngle = arcAngle / segments; - double startAngle = atan2( -ys, xs ); + unsigned int segments = (unsigned int) tempSegments; + + double deltaAngle = arcAngle / segments; + double startAngle = atan2( -ys, xs ); // Flip arc for inner corners - if( xa*yb - ya*xb <= 0 ) + if( xa * yb - ya * xb <= 0 ) deltaAngle *= -1; - nx = xc + xs + 0.5; - ny = yc + ys + 0.5; + nx = xc + xs + 0.5; + ny = yc + ys + 0.5; + if( index == startIndex ) - newPoly->Start( GetLayer(), (int)nx, (int)ny, GetHatchStyle() ); + newPoly->Start( GetLayer(), (int) nx, (int) ny, GetHatchStyle() ); else - newPoly->AppendCorner( (int)nx, (int)ny ); + newPoly->AppendCorner( (int) nx, (int) ny ); unsigned int nVertices = 0; + for( unsigned int j = 0; j < segments; j++ ) { - nx = xc + cos( startAngle + (j+1)*deltaAngle )*radius + 0.5; - ny = yc - sin( startAngle + (j+1)*deltaAngle )*radius + 0.5; - newPoly->AppendCorner( (int)nx, (int)ny ); + nx = xc + cos( startAngle + (j + 1) * deltaAngle ) * radius + 0.5; + ny = yc - sin( startAngle + (j + 1) * deltaAngle ) * radius + 0.5; + newPoly->AppendCorner( (int) nx, (int) ny ); nVertices++; } } + newPoly->Close(); } + return newPoly; } @@ -1127,6 +1103,7 @@ void CPolyLine::RemoveAllContours( void ) void CPolyLine::InsertCorner( int ic, int x, int y ) { UnHatch(); + if( (unsigned) (ic) >= m_CornersList.size() ) { m_CornersList.push_back( CPolyPt( x, y ) ); @@ -1142,10 +1119,11 @@ void CPolyLine::InsertCorner( int ic, int x, int y ) { if( m_CornersList[ic].end_contour ) { - m_CornersList[ic + 1].end_contour = true; - m_CornersList[ic].end_contour = false; + m_CornersList[ic + 1].end_contour = true; + m_CornersList[ic].end_contour = false; } } + Hatch(); } @@ -1168,10 +1146,10 @@ CRect CPolyLine::GetBounds() { CRect r = GetCornerBounds(); - r.left -= m_width / 2; - r.right += m_width / 2; - r.bottom -= m_width / 2; - r.top += m_width / 2; + r.left -= m_width / 2; + r.right += m_width / 2; + r.bottom -= m_width / 2; + r.top += m_width / 2; return r; } @@ -1182,12 +1160,13 @@ CRect CPolyLine::GetCornerBounds() r.left = r.bottom = INT_MAX; r.right = r.top = INT_MIN; + for( unsigned i = 0; i max_x ) max_x = m_CornersList[ic].x; + if( m_CornersList[ic].y < min_y ) min_y = m_CornersList[ic].y; + if( m_CornersList[ic].y > max_y ) max_y = m_CornersList[ic].y; } // Calculate spacing betwwen 2 hatch lines - int spacing; + int spacing; + if( m_hatchStyle == DIAGONAL_EDGE ) spacing = m_hatchPitch; else spacing = m_hatchPitch * 2; // set the "lenght" of hatch lines (the lenght on horizontal axis) - double hatch_line_len = m_hatchPitch; + double hatch_line_len = m_hatchPitch; // To have a better look, give a slope depending on the layer - int layer = GetLayer(); - int slope_flag = (layer & 1) ? 1 : -1; // 1 or -1 - double slope = 0.707106 * slope_flag; // 45 degrees slope - int max_a, min_a; + int layer = GetLayer(); + int slope_flag = (layer & 1) ? 1 : -1; // 1 or -1 + double slope = 0.707106 * slope_flag; // 45 degrees slope + int max_a, min_a; + if( slope_flag == 1 ) { - max_a = (int) (max_y - slope * min_x); - min_a = (int) (min_y - slope * max_x); + max_a = (int) (max_y - slope * min_x); + min_a = (int) (min_y - slope * max_x); } else { - max_a = (int) (max_y - slope * max_x); - min_a = (int) (min_y - slope * min_x); + max_a = (int) (max_y - slope * max_x); + min_a = (int) (min_y - slope * min_x); } + min_a = (min_a / spacing) * spacing; // calculate an offset depending on layer number, @@ -1427,7 +1426,7 @@ void CPolyLine::Hatch() static std::vector pointbuffer; pointbuffer.clear(); - pointbuffer.reserve(MAXPTS+2); + pointbuffer.reserve( MAXPTS + 2 ); for( int a = min_a; a < max_a; a += spacing ) { @@ -1439,38 +1438,43 @@ void CPolyLine::Hatch() // we skip this line (should not occur) pointbuffer.clear(); int i_start_contour = 0; + for( int ic = 0; ic= MAXPTS ) // overflow { wxASSERT( 0 ); @@ -1495,6 +1499,7 @@ void CPolyLine::Hatch() for( unsigned ip = 0; ip < pointbuffer.size(); ip += 2 ) { double dx = pointbuffer[ip + 1].x - pointbuffer[ip].x; + // Push only one line for diagonal hatch, // or for small lines < twice the line len // else push 2 small lines @@ -1504,18 +1509,18 @@ void CPolyLine::Hatch() } else { - double dy = pointbuffer[ip + 1].y - pointbuffer[ip].y; - double slope = dy / dx; + double dy = pointbuffer[ip + 1].y - pointbuffer[ip].y; + double slope = dy / dx; if( dx > 0 ) dx = hatch_line_len; else dx = -hatch_line_len; - double x1 = pointbuffer[ip].x + dx; - double x2 = pointbuffer[ip + 1].x - dx; - double y1 = pointbuffer[ip].y + dx * slope; - double y2 = pointbuffer[ip + 1].y - dx * slope; + double x1 = pointbuffer[ip].x + dx; + double x2 = pointbuffer[ip + 1].x - dx; + double y1 = pointbuffer[ip].y + dx * slope; + double y2 = pointbuffer[ip + 1].y - dx * slope; m_HatchLines.push_back( CSegment( pointbuffer[ip].x, pointbuffer[ip].y, @@ -1544,28 +1549,30 @@ bool CPolyLine::TestPointInside( int px, int py ) // if the tested point is inside only one contour, it is inside the whole polygon // (in fact inside the main outline, and outside all holes). // if inside 2 contours (the main outline + an hole), it is outside the poly. - int polycount = GetContoursCount(); - bool inside = false; + int polycount = GetContoursCount(); + bool inside = false; + for( int icont = 0; icont < polycount; icont++ ) { - int istart = GetContourStart( icont ); - int iend = GetContourEnd( icont ); + int istart = GetContourStart( icont ); + int iend = GetContourEnd( icont ); // Test this polygon: - if( TestPointInsidePolygon( m_CornersList, istart, iend, px, py) ) // test point inside the current polygon + if( TestPointInsidePolygon( m_CornersList, istart, iend, px, py ) ) // test point inside the current polygon inside = not inside; } return inside; } + // copy data from another poly, but don't draw it // void CPolyLine::Copy( CPolyLine* src ) { UnHatch(); - m_hatchStyle = src->m_hatchStyle; - m_hatchPitch = src->m_hatchPitch; + m_hatchStyle = src->m_hatchStyle; + m_hatchPitch = src->m_hatchPitch; // copy corners, using vector copy m_CornersList = src->m_CornersList; // copy side styles, using vector copy @@ -1583,8 +1590,9 @@ bool CPolyLine::IsCutoutContour( int icont ) { int ncont = GetContour( icont ); - if( ncont == 0 ) // the first contour is the main outline, not an hole + if( ncont == 0 ) // the first contour is the main outline, not an hole return false; + return true; } @@ -1592,6 +1600,7 @@ bool CPolyLine::IsCutoutContour( int icont ) void CPolyLine::MoveOrigin( int x_off, int y_off ) { UnHatch(); + for( int ic = 0; ic < GetNumCorners(); ic++ ) { SetX( ic, GetX( ic ) + x_off ); @@ -1603,8 +1612,8 @@ void CPolyLine::MoveOrigin( int x_off, int y_off ) // Set various parameters: -// the calling function should UnHatch() before calling them, -// and Draw() after +// the calling function should UnHatch() before calling them, +// and Draw() after // void CPolyLine::SetX( int ic, int x ) { @@ -1627,19 +1636,19 @@ void CPolyLine::SetEndContour( int ic, bool end_contour ) void CPolyLine::AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num ) { // get radius - double r = sqrt( (double) (xi - xc) * (xi - xc) + (double) (yi - yc) * (yi - yc) ); + double r = sqrt( (double) (xi - xc) * (xi - xc) + (double) (yi - yc) * (yi - yc) ); // get angles of start and finish - double th_i = atan2( (double) (yi - yc), (double) (xi - xc) ); - double th_f = atan2( (double) (yf - yc), (double) (xf - xc) ); - double th_d = (th_f - th_i) / (num - 1); - double theta = th_i; + double th_i = atan2( (double) (yi - yc), (double) (xi - xc) ); + double th_f = atan2( (double) (yf - yc), (double) (xf - xc) ); + double th_d = (th_f - th_i) / (num - 1); + double theta = th_i; // generate arc for( int ic = 0; ic bezier_points; - bezier_points = Bezier2Poly(x1,y1,x2,y2,x3,y3); - for( unsigned int i = 0; i < bezier_points.size() ; i++) - AppendCorner( bezier_points[i].x, bezier_points[i].y); + bezier_points = Bezier2Poly( x1, y1, x2, y2, x3, y3 ); + + for( unsigned int i = 0; i < bezier_points.size(); i++ ) + AppendCorner( bezier_points[i].x, bezier_points[i].y ); } -void CPolyLine::AppendBezier(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) + +void CPolyLine::AppendBezier( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 ) { std::vector bezier_points; - bezier_points = Bezier2Poly(x1,y1,x2,y2,x3,y3,x4,y4); - for( unsigned int i = 0; i < bezier_points.size() ; i++) - AppendCorner( bezier_points[i].x, bezier_points[i].y); + bezier_points = Bezier2Poly( x1, y1, x2, y2, x3, y3, x4, y4 ); + + for( unsigned int i = 0; i < bezier_points.size(); i++ ) + AppendCorner( bezier_points[i].x, bezier_points[i].y ); } @@ -1685,13 +1698,13 @@ int CPolyLine::Distance( wxPoint aStart, wxPoint aEnd, int aWidth ) if( TestPointInside( aStart.x, aStart.y ) ) return 0; - int distance = INT_MAX; - int polycount = GetContoursCount(); + int distance = INT_MAX; + int polycount = GetContoursCount(); for( int icont = 0; icont < polycount; icont++ ) { - int ic_start = GetContourStart( icont ); - int ic_end = GetContourEnd( icont ); + int ic_start = GetContourStart( icont ); + int ic_end = GetContourEnd( icont ); // now test spacing between area outline and segment for( int ic2 = ic_start; ic2 <= ic_end; ic2++ ) @@ -1715,10 +1728,12 @@ int CPolyLine::Distance( wxPoint aStart, wxPoint aEnd, int aWidth ) int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2, bstyle, 0, aStart.x, aStart.y, aEnd.x, aEnd.y, CPolyLine::STRAIGHT, aWidth, - 1, // min clearance, should be > 0 + 1, // min clearance, should be > 0 NULL, NULL ); + if( distance > d ) distance = d; + if( distance <= 0 ) return 0; } @@ -1727,6 +1742,7 @@ int CPolyLine::Distance( wxPoint aStart, wxPoint aEnd, int aWidth ) return distance; } + /* * Function Distance * Calculates the distance between a point and polygon (with holes): @@ -1741,13 +1757,13 @@ int CPolyLine::Distance( const wxPoint& aPoint ) if( TestPointInside( aPoint.x, aPoint.y ) ) return 0; - int distance = INT_MAX; - int polycount = GetContoursCount(); + int distance = INT_MAX; + int polycount = GetContoursCount(); for( int icont = 0; icont < polycount; icont++ ) { - int ic_start = GetContourStart( icont ); - int ic_end = GetContourEnd( icont ); + int ic_start = GetContourStart( icont ); + int ic_end = GetContourEnd( icont ); // now test spacing between area outline and segment for( int ic2 = ic_start; ic2 <= ic_end; ic2++ ) @@ -1770,11 +1786,12 @@ int CPolyLine::Distance( const wxPoint& aPoint ) // Here we expect only straight lines for vertices // (no arcs, not yet supported in Pcbnew) int d = KiROUND( GetPointToLineSegmentDistance( aPoint.x, aPoint.y, - bx1, by1, bx2, by2 ) ); + bx1, by1, bx2, by2 ) ); if( distance > d ) distance = d; + if( distance <= 0 ) return 0; } @@ -1782,3 +1799,152 @@ int CPolyLine::Distance( const wxPoint& aPoint ) return distance; } + + +/** + * Function CopyPolysListToKiPolygonWithHole + * converts the outline contours aPolysList to a KI_POLYGON_WITH_HOLES + * + * @param aPolysList = the list of corners of contours + * @param aPolygoneWithHole = a KI_POLYGON_WITH_HOLES to populate + */ +void CopyPolysListToKiPolygonWithHole( const std::vector& aPolysList, + KI_POLYGON_WITH_HOLES& aPolygoneWithHole ) +{ + unsigned corners_count = aPolysList.size(); + + std::vector cornerslist; + KI_POLYGON poly; + + // Enter main outline: this is the first contour + unsigned ic = 0; + + while( ic < corners_count ) + { + const CPolyPt& corner = aPolysList[ic++]; + cornerslist.push_back( KI_POLY_POINT( corner.x, corner.y ) ); + + if( corner.end_contour ) + break; + } + + aPolygoneWithHole.set( cornerslist.begin(), cornerslist.end() ); + + // Enter holes: they are next contours (when exist) + if( ic < corners_count ) + { + KI_POLYGON_SET holePolyList; + + while( ic < corners_count ) + { + cornerslist.clear(); + + while( ic < corners_count ) + { + const CPolyPt& corner = aPolysList[ic++]; + cornerslist.push_back( KI_POLY_POINT( corner.x, corner.y ) ); + + if( corner.end_contour ) + break; + } + + bpl::set_points( poly, cornerslist.begin(), cornerslist.end() ); + holePolyList.push_back( poly ); + } + + aPolygoneWithHole.set_holes( holePolyList.begin(), holePolyList.end() ); + } +} + +/** + * Function ConvertPolysListWithHolesToOnePolygon + * converts the outline contours aPolysListWithHoles with holes to one polygon + * with no holes (only one contour) + * holes are linked to main outlines by overlap segments, to give only one polygon + * + * @param aPolysListWithHoles = the list of corners of contours (haing holes + * @param aOnePolyList = a polygon with no holes + */ +void ConvertPolysListWithHolesToOnePolygon( const std::vector& aPolysListWithHoles, + std::vector& aOnePolyList ) +{ + unsigned corners_count = aPolysListWithHoles.size(); + int polycount = 0; + + for( unsigned ii = 0; ii < corners_count; ii++ ) + { + const CPolyPt& corner = aPolysListWithHoles[ii]; + + if( corner.end_contour ) + polycount++; + } + + // If polycount<= 1, there is no holes found. + if( polycount<= 1 ) + { + aOnePolyList = aPolysListWithHoles; + return; + } + + // Holes are found: convert them to only one polygon with overlap segments + KI_POLYGON_SET polysholes; + KI_POLYGON_SET mainpoly; + KI_POLYGON poly_tmp; + std::vector cornerslist; + corners_count = aPolysListWithHoles.size(); + + unsigned ic = 0; + // enter main outline + while( ic < corners_count ) + { + const CPolyPt& corner = aPolysListWithHoles[ic++]; + cornerslist.push_back( KI_POLY_POINT( corner.x, corner.y ) ); + + if( corner.end_contour ) + break; + } + bpl::set_points( poly_tmp, cornerslist.begin(), cornerslist.end() ); + mainpoly.push_back( poly_tmp ); + + while( ic < corners_count ) + { + cornerslist.clear(); + { + while( ic < corners_count ) + { + const CPolyPt& corner = aPolysListWithHoles[ic++]; + cornerslist.push_back( KI_POLY_POINT( corner.x, corner.y ) ); + + if( corner.end_contour ) + break; + } + + bpl::set_points( poly_tmp, cornerslist.begin(), cornerslist.end() ); + polysholes.push_back( poly_tmp ); + } + } + + mainpoly -= polysholes; + + // copy polygon with no holes to destination + // We should have only one polygon in list + wxASSERT( mainpoly.size() != 1 ); + + { + KI_POLYGON& poly_nohole = mainpoly[0]; + CPolyPt corner( 0, 0, false ); + + for( unsigned jj = 0; jj < poly_nohole.size(); jj++ ) + { + KI_POLY_POINT point = *(poly_nohole.begin() + jj); + corner.x = point.x(); + corner.y = point.y(); + corner.end_contour = false; + aOnePolyList.push_back( corner ); + } + + corner.end_contour = true; + aOnePolyList.pop_back(); + aOnePolyList.push_back( corner ); + } +} diff --git a/polygon/PolyLine.h b/polygon/PolyLine.h index 468bf09f78..4bf31a5213 100644 --- a/polygon/PolyLine.h +++ b/polygon/PolyLine.h @@ -19,11 +19,12 @@ #include #include -#include +#include // for wxPoint definition + +#include // inflection modes for DS_LINE and DS_LINE_VERTEX, used in math_for_graphics.cpp -enum -{ +enum { IM_NONE = 0, IM_90_45, IM_45_90, @@ -44,15 +45,16 @@ public: wxPoint m_End; CSegment() { }; - CSegment( const wxPoint & aStart, const wxPoint & aEnd ) + CSegment( const wxPoint& aStart, const wxPoint& aEnd ) { m_Start = aStart; - m_End = aEnd; + m_End = aEnd; } + CSegment( int x0, int y0, int x1, int y1 ) { - m_Start.x = x0; m_Start.y = y0; - m_End.x = x1; m_End.y = y1; + m_Start.x = x0; m_Start.y = y0; + m_End.x = x1; m_End.y = y1; } }; @@ -63,10 +65,10 @@ class CArc { public: enum { ARC_STEPS = 16 }; // arc approximation step is 16 segm / 90 degres - int style; - int xi, yi, xf, yf; - int n_steps; // number of straight-line segments in gpc_poly - bool bFound; + int style; + int xi, yi, xf, yf; + int n_steps; // number of straight-line segments in gpc_poly + bool bFound; }; @@ -77,8 +79,8 @@ public: wxPoint( aX, aY ), end_contour( aEnd ), m_utility( aUtility ) {} - /// Pure copy constructor is here to dis-ambiguate from the - /// specialized CPolyPt( const wxPoint& ) constructor version below. + // / Pure copy constructor is here to dis-ambiguate from the + // / specialized CPolyPt( const wxPoint& ) constructor version below. CPolyPt( const CPolyPt& aPt ) : wxPoint( aPt.x, aPt.y ), end_contour( aPt.end_contour ), m_utility( aPt.m_utility ) {} @@ -88,13 +90,13 @@ public: {} - bool end_contour; - int m_utility; + bool end_contour; + int m_utility; - bool operator == (const CPolyPt& cpt2 ) const + bool operator ==( const CPolyPt& cpt2 ) const { return (x == cpt2.x) && (y == cpt2.y) && (end_contour == cpt2.end_contour); } - bool operator != (CPolyPt& cpt2 ) const + bool operator !=( CPolyPt& cpt2 ) const { return (x != cpt2.x) || (y != cpt2.y) || (end_contour != cpt2.end_contour); } }; @@ -112,13 +114,13 @@ public: ~CPolyLine(); // functions for modifying polyline - void Start( int layer, int x, int y, int hatch ); - void AppendCorner( int x, int y, int style = STRAIGHT, bool bDraw = false ); - void InsertCorner( int ic, int x, int y ); - void DeleteCorner( int ic, bool bDraw = false ); - void MoveCorner( int ic, int x, int y ); - void Close( int style = STRAIGHT, bool bDraw = false ); - void RemoveContour( int icont ); + void Start( int layer, int x, int y, int hatch ); + void AppendCorner( int x, int y, int style = STRAIGHT, bool bDraw = false ); + void InsertCorner( int ic, int x, int y ); + void DeleteCorner( int ic, bool bDraw = false ); + void MoveCorner( int ic, int x, int y ); + void Close( int style = STRAIGHT, bool bDraw = false ); + void RemoveContour( int icont ); /** * Function Chamfer @@ -126,7 +128,7 @@ public: * @param aDistance is the chamfering distance. * @return CPolyLine* - Pointer to new polygon. */ - CPolyLine* Chamfer( unsigned int aDistance ); + CPolyLine* Chamfer( unsigned int aDistance ); /** * Function Fillet @@ -135,108 +137,88 @@ public: * @param aSegments is the number of segments / fillet. * @return CPolyLine* - Pointer to new polygon. */ - CPolyLine* Fillet( unsigned int aRadius, unsigned int aSegments ); + CPolyLine* Fillet( unsigned int aRadius, unsigned int aSegments ); - void RemoveAllContours( void ); + void RemoveAllContours( void ); // Remove or create hatch - void UnHatch(); - void Hatch(); + void UnHatch(); + void Hatch(); // Transform functions - void MoveOrigin( int x_off, int y_off ); + void MoveOrigin( int x_off, int y_off ); // misc. functions - CRect GetBounds(); - CRect GetCornerBounds(); - CRect GetCornerBounds( int icont ); - void Copy( CPolyLine* src ); - bool TestPointInside( int x, int y ); - bool IsCutoutContour( int icont ); - void AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num ); + CRect GetBounds(); + CRect GetCornerBounds(); + CRect GetCornerBounds( int icont ); + void Copy( CPolyLine* src ); + bool TestPointInside( int x, int y ); + bool IsCutoutContour( int icont ); + void AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num ); // access functions void SetLayer( int aLayer ) { m_layer = aLayer; } int GetLayer() { return m_layer; } - int GetNumCorners(); - int GetNumSides(); - int GetClosed(); - int GetContoursCount(); - int GetContour( int ic ); - int GetContourStart( int icont ); - int GetContourEnd( int icont ); - int GetContourSize( int icont ); + int GetNumCorners(); + int GetNumSides(); + int GetClosed(); + int GetContoursCount(); + int GetContour( int ic ); + int GetContourStart( int icont ); + int GetContourEnd( int icont ); + int GetContourSize( int icont ); int GetX( int ic ) const { return m_CornersList[ic].x; } int GetY( int ic ) const { return m_CornersList[ic].y; } const wxPoint& GetPos( int ic ) const { return m_CornersList[ic]; } - int GetEndContour( int ic ); + int GetEndContour( int ic ); int GetUtility( int ic ) { return m_CornersList[ic].m_utility; }; void SetUtility( int ic, int utility ) { m_CornersList[ic].m_utility = utility; }; - int GetSideStyle( int is ); + int GetSideStyle( int is ); + int GetHatchPitch() { return m_hatchPitch; } - int GetDefaultHatchPitchMils() { return 20; } // default hatch pitch value in mils + int GetDefaultHatchPitchMils() { return 20; } // default hatch pitch value in mils enum hatch_style GetHatchStyle() { return m_hatchStyle; } void SetHatch( int hatch, int pitch ) - { - SetHatchPitch( pitch ); - m_hatchStyle = (enum hatch_style ) hatch; - Hatch(); - } - void SetX( int ic, int x ); - void SetY( int ic, int y ); - void SetEndContour( int ic, bool end_contour ); - void SetSideStyle( int is, int style ); + { + SetHatchPitch( pitch ); + m_hatchStyle = (enum hatch_style) hatch; + Hatch(); + } + + void SetX( int ic, int x ); + void SetY( int ic, int y ); + void SetEndContour( int ic, bool end_contour ); + void SetSideStyle( int is, int style ); + void SetHatchStyle( enum hatch_style style ) - { - m_hatchStyle = style; - } + { + m_hatchStyle = style; + } + void SetHatchPitch( int pitch ) { m_hatchPitch = pitch; } - int RestoreArcs( std::vector * arc_array, std::vector * pa = NULL ); + int RestoreArcs( std::vector* arc_array, std::vector* pa = NULL ); - int NormalizeAreaOutlines( std::vector * pa = NULL, - bool bRetainArcs = false ); + int NormalizeAreaOutlines( std::vector* pa = NULL, + bool bRetainArcs = false ); // KBOOL functions - /** - * Function AddPolygonsToBoolEng - * and edges contours to a kbool engine, preparing a boolean op between polygons - * @param aStart_contour: starting contour number (-1 = all, 0 is the outlines of zone, > 1 = holes in zone - * @param aEnd_contour: ending contour number (-1 = all after aStart_contour) - * @param arc_array: arc connverted to poly (NULL if not exists) - * @param aBooleng : pointer on a bool engine (handle a set of polygons) - * @param aGroup : group to fill (aGroup = GROUP_A or GROUP_B) operations are made between GROUP_A and GROUP_B - */ - int AddPolygonsToBoolEng( Bool_Engine* aBooleng, - GroupType aGroup, - int aStart_contour = -1, - int aEnd_contour = -1, - std::vector * arc_array = NULL ); - /** * Function MakeKboolPoly * fill a kbool engine with a closed polyline contour * approximates arcs with multiple straight-line segments - * @param aStart_contour: starting contour number (-1 = all, 0 is the outlines of zone, > 1 = holes in zone - * @param aEnd_contour: ending contour number (-1 = all after aStart_contour) * combining intersecting contours if possible * @param arc_array : return data on arcs in arc_array - * @param aConvertHoles = mode for holes when a boolean operation is made - * true: holes are linked into outer contours by double overlapping segments - * false: holes are not linked: in this mode contours are added clockwise - * and polygons added counter clockwise are holes (default) * @return error: 0 if Ok, 1 if error */ - int MakeKboolPoly( int aStart_contour = -1, - int aEnd_contour = -1, - std::vector * arc_array = NULL, - bool aConvertHoles = false); + int MakeKboolPoly( std::vector* arc_array = NULL ); /** * Function NormalizeWithKbool @@ -250,22 +232,11 @@ public: * @param bRetainArcs == false, try to retain arcs in polys * @return number of external contours, or -1 if error */ - int NormalizeWithKbool( std::vector * aExtraPolyList, bool bRetainArcs ); - - /** - * Function GetKboolEngine - * @return the current used Kbool Engine (after normalization using kbool) - */ - Bool_Engine* GetKboolEngine( ) { return m_Kbool_Poly_Engine; } - /** - * Function FreeKboolEngine - * delete the current used Kbool Engine (free memory after normalization using kbool) - */ - void FreeKboolEngine( ) { delete m_Kbool_Poly_Engine; m_Kbool_Poly_Engine = NULL; } + int NormalizeWithKbool( std::vector* aExtraPolyList, bool bRetainArcs ); // Bezier Support - void AppendBezier(int x1, int y1, int x2, int y2, int x3, int y3); - void AppendBezier(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4); + void AppendBezier( int x1, int y1, int x2, int y2, int x3, int y3 ); + void AppendBezier( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 ); /** * Function Distance @@ -274,7 +245,7 @@ public: * @return int = distance between the point and outline. * 0 if the point is inside */ - int Distance( const wxPoint& aPoint ); + int Distance( const wxPoint& aPoint ); /** * Function Distance @@ -285,22 +256,44 @@ public: * @return int = distance between the segment and outline. * 0 if segment intersects or is inside */ - int Distance( wxPoint aStart, wxPoint aEnd, int aWidth ); + int Distance( wxPoint aStart, wxPoint aEnd, int aWidth ); private: - int m_layer; // layer to draw on - int m_width; // lines width when drawing. Provided but not really used - enum hatch_style m_hatchStyle; // hatch style, see enum above - int m_hatchPitch; // for DIAGONAL_EDGE hatched outlines, basic distance between 2 hatch lines - // and the len of eacvh segment - // for DIAGONAL_FULL, the pitch is twice this value - int m_utility; // a flag used in some calculations - Bool_Engine* m_Kbool_Poly_Engine; // polygons set in kbool engine data - + int m_layer; // layer to draw on + int m_width; // lines width when drawing. Provided but not really used + enum hatch_style m_hatchStyle; // hatch style, see enum above + int m_hatchPitch; // for DIAGONAL_EDGE hatched outlines, basic distance between 2 hatch lines + // and the len of eacvh segment + // for DIAGONAL_FULL, the pitch is twice this value + int m_utility; // a flag used in some calculations + Bool_Engine* m_Kbool_Poly_Engine; // polygons set in kbool engine data public: - std::vector m_CornersList; // array of points for corners - std::vector m_SideStyle; // array of styles for sides - std::vector m_HatchLines; // hatch lines showing the polygon area + std::vector m_CornersList; // array of points for corners + std::vector m_SideStyle; // array of styles for sides + std::vector m_HatchLines; // hatch lines showing the polygon area }; -#endif // #ifndef POLYLINE_H +/** + * Function CopyPolysListToKiPolygonWithHole + * converts the outline contours aPolysList to a KI_POLYGON_WITH_HOLES + * + * @param aPolysList = the list of corners of contours + * @param aPolygoneWithHole = a KI_POLYGON_WITH_HOLES to populate + */ +void CopyPolysListToKiPolygonWithHole( const std::vector& aPolysList, + KI_POLYGON_WITH_HOLES& aPolygoneWithHole ); + + +/** + * Function ConvertPolysListWithHolesToOnePolygon + * converts the outline contours aPolysListWithHoles with holes to one polygon + * with no holes (only one contour) + * holes are linked to main outlines by overlap segments, to give only one polygon + * + * @param aPolysListWithHoles = the list of corners of contours (haing holes + * @param aOnePolyList = a polygon with no holes + */ +void ConvertPolysListWithHolesToOnePolygon( const std::vector& aPolysListWithHoles, + std::vector& aOnePolyList ); + +#endif // #ifndef POLYLINE_H diff --git a/pcbnew/polygons_defs.h b/polygon/polygons_defs.h similarity index 100% rename from pcbnew/polygons_defs.h rename to polygon/polygons_defs.h