Fix issues in zones creation (DRC and merging) I created in 3658.1

This commit is contained in:
jean-pierre charras 2012-07-30 09:40:25 +02:00
parent 1c9433fb31
commit f96d557e73
13 changed files with 263 additions and 116 deletions

View File

@ -46,6 +46,7 @@
#include <pcbnew.h> #include <pcbnew.h>
#include <zones.h> #include <zones.h>
#include <math_for_graphics.h>
ZONE_CONTAINER::ZONE_CONTAINER( BOARD* aBoard ) : ZONE_CONTAINER::ZONE_CONTAINER( BOARD* aBoard ) :
@ -912,7 +913,7 @@ void ZONE_CONTAINER::AddPolygon( std::vector< wxPoint >& aPolygon )
AppendCorner( aPolygon[i] ); AppendCorner( aPolygon[i] );
} }
m_Poly->Close(); m_Poly->CloseLastContour();
} }

View File

@ -429,7 +429,7 @@ public:
return m_Poly->GetHatchStyle(); return m_Poly->GetHatchStyle();
} }
void SetHatchStyle( CPolyLine::hatch_style aStyle ) void SetHatchStyle( CPolyLine::HATCH_STYLE aStyle )
{ {
m_Poly->SetHatchStyle( aStyle ); m_Poly->SetHatchStyle( aStyle );
} }

View File

@ -99,7 +99,6 @@ void ZONE_SETTINGS::ExportSetting( ZONE_CONTAINER& aTarget, bool aFullExport ) c
aTarget.m_FillMode = m_FillMode; aTarget.m_FillMode = m_FillMode;
aTarget.m_ZoneClearance = m_ZoneClearance; aTarget.m_ZoneClearance = m_ZoneClearance;
aTarget.m_ZoneMinThickness = m_ZoneMinThickness; aTarget.m_ZoneMinThickness = m_ZoneMinThickness;
aTarget.m_Poly->SetHatch( m_Zone_HatchingStyle, Mils2iu( 20 ) );
aTarget.m_ArcToSegmentsCount = m_ArcToSegmentsCount; aTarget.m_ArcToSegmentsCount = m_ArcToSegmentsCount;
aTarget.m_ThermalReliefGap = m_ThermalReliefGap; aTarget.m_ThermalReliefGap = m_ThermalReliefGap;
aTarget.m_ThermalReliefCopperBridge = m_ThermalReliefCopperBridge; aTarget.m_ThermalReliefCopperBridge = m_ThermalReliefCopperBridge;
@ -118,4 +117,8 @@ void ZONE_SETTINGS::ExportSetting( ZONE_CONTAINER& aTarget, bool aFullExport ) c
aTarget.SetLayer( m_CurrentZone_Layer ); aTarget.SetLayer( m_CurrentZone_Layer );
aTarget.m_Poly->SetLayer( m_CurrentZone_Layer ); aTarget.m_Poly->SetLayer( m_CurrentZone_Layer );
} }
// call SetHatch last, because hatch lines will be rebuilt,
// using new parameters values
aTarget.m_Poly->SetHatch( m_Zone_HatchingStyle, Mils2iu( 20 ), true );
} }

View File

@ -44,6 +44,7 @@
#include <class_track.h> #include <class_track.h>
#include <class_zone.h> #include <class_zone.h>
#include <class_marker_pcb.h> #include <class_marker_pcb.h>
#include <math_for_graphics.h>
/* compare 2 trapezoids (can be rectangle) and return true if distance > aDist /* compare 2 trapezoids (can be rectangle) and return true if distance > aDist

View File

@ -1404,17 +1404,18 @@ void EAGLE_PLUGIN::loadPlain( CPTREE& aGraphics )
zone->SetLayer( layer ); zone->SetLayer( layer );
zone->SetNet( 0 ); zone->SetNet( 0 );
int outline_hatch = CPolyLine::DIAGONAL_EDGE; CPolyLine::HATCH_STYLE outline_hatch = CPolyLine::DIAGONAL_EDGE;
zone->m_Poly->Start( layer, kicad_x( r.x1 ), kicad_y( r.y1 ), outline_hatch ); zone->m_Poly->Start( layer, kicad_x( r.x1 ), kicad_y( r.y1 ), outline_hatch );
zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y1 ) ) ); zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y1 ) ) );
zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y2 ) ) ); zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y2 ) ) );
zone->AppendCorner( wxPoint( kicad_x( r.x1 ), kicad_y( r.y2 ) ) ); zone->AppendCorner( wxPoint( kicad_x( r.x1 ), kicad_y( r.y2 ) ) );
zone->m_Poly->Close(); zone->m_Poly->CloseLastContour();
// this is not my fault: // this is not my fault:
zone->m_Poly->SetHatch( outline_hatch, zone->m_Poly->SetHatch( outline_hatch,
Mils2iu( zone->m_Poly->GetDefaultHatchPitchMils() ) ); Mils2iu( zone->m_Poly->GetDefaultHatchPitchMils() ),
true );
} }
m_xpath->pop(); m_xpath->pop();
} }
@ -2360,7 +2361,7 @@ void EAGLE_PLUGIN::loadSignals( CPTREE& aSignals )
zone->SetNet( netCode ); zone->SetNet( netCode );
zone->SetNetName( netName ); zone->SetNetName( netName );
int outline_hatch = CPolyLine::DIAGONAL_EDGE; CPolyLine::HATCH_STYLE outline_hatch = CPolyLine::DIAGONAL_EDGE;
bool first = true; bool first = true;
for( CITER vi = it->second.begin(); vi != it->second.end(); ++vi ) for( CITER vi = it->second.begin(); vi != it->second.end(); ++vi )
@ -2380,10 +2381,11 @@ void EAGLE_PLUGIN::loadSignals( CPTREE& aSignals )
zone->AppendCorner( wxPoint( kicad_x( v.x ), kicad_y( v.y ) ) ); zone->AppendCorner( wxPoint( kicad_x( v.x ), kicad_y( v.y ) ) );
} }
zone->m_Poly->Close(); zone->m_Poly->CloseLastContour();
zone->m_Poly->SetHatch( outline_hatch, zone->m_Poly->SetHatch( outline_hatch,
Mils2iu( zone->m_Poly->GetDefaultHatchPitchMils() ) ); Mils2iu( zone->m_Poly->GetDefaultHatchPitchMils() ),
true );
// clearances, etc. // clearances, etc.
zone->SetArcSegCount( 32 ); // @todo: should be a constructor default? zone->SetArcSegCount( 32 ); // @todo: should be a constructor default?

View File

@ -2109,7 +2109,7 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER()
{ {
auto_ptr<ZONE_CONTAINER> zc( new ZONE_CONTAINER( m_board ) ); auto_ptr<ZONE_CONTAINER> zc( new ZONE_CONTAINER( m_board ) );
int outline_hatch = CPolyLine::NO_HATCH; CPolyLine::HATCH_STYLE outline_hatch = CPolyLine::NO_HATCH;
bool sawCorner = false; bool sawCorner = false;
char buf[1024]; char buf[1024];
@ -2133,7 +2133,7 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER()
sawCorner = true; sawCorner = true;
if( flag ) if( flag )
zc->m_Poly->Close(); zc->m_Poly->CloseLastContour();
} }
else if( TESTLINE( "ZInfo" ) ) // general info found else if( TESTLINE( "ZInfo" ) ) // general info found
@ -2350,9 +2350,11 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER()
zc->SetNet( 0 ); zc->SetNet( 0 );
} }
// Hatch here, after outlines corners are read
// Set hatch here, after outlines corners are read // Set hatch here, after outlines corners are read
zc->m_Poly->SetHatch( outline_hatch, zc->m_Poly->SetHatch( outline_hatch,
Mils2iu( zc->m_Poly->GetDefaultHatchPitchMils() ) ); Mils2iu( CPolyLine::GetDefaultHatchPitchMils() ),
true );
m_board->Add( zc.release() ); m_board->Add( zc.release() );
} }

View File

@ -2292,8 +2292,8 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR )
wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
wxT( " as ZONE_CONTAINER." ) ); wxT( " as ZONE_CONTAINER." ) );
int hatchStyle = CPolyLine::NO_HATCH; // Fix compile warning CPolyLine::HATCH_STYLE hatchStyle = CPolyLine::NO_HATCH;
int hatchPitch = 0; // Fix compile warning int hatchPitch = Mils2iu( CPolyLine::GetDefaultHatchPitchMils() );
wxPoint pt; wxPoint pt;
T token; T token;
@ -2587,7 +2587,7 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR )
} }
// Set hatch here, after outlines corners are read // Set hatch here, after outlines corners are read
zone->m_Poly->SetHatch( hatchStyle, hatchPitch ); zone->m_Poly->SetHatch( hatchStyle, hatchPitch, true );
} }
if( pts.size() ) if( pts.size() )

View File

@ -679,8 +679,12 @@ int PCB_EDIT_FRAME::Begin_Zone( wxDC* DC )
if( !Drc_On || !zone->IsOnCopperLayer() || ( m_drc->Drc( zone, ii - 1 ) == OK_DRC ) ) if( !Drc_On || !zone->IsOnCopperLayer() || ( m_drc->Drc( zone, ii - 1 ) == OK_DRC ) )
{ {
// Ok, we can add a new corner // Ok, we can add a new corner
if( m_canvas->IsMouseCaptured() )
m_canvas->CallMouseCapture( DC, wxPoint(0,0), false );
zone->AppendCorner( GetScreen()->GetCrossHairPosition() ); zone->AppendCorner( GetScreen()->GetCrossHairPosition() );
SetCurItem( zone ); // calls DisplayInfo(). SetCurItem( zone ); // calls DisplayInfo().
if( m_canvas->IsMouseCaptured() )
m_canvas->CallMouseCapture( DC, wxPoint(0,0), false );
} }
} }
} }
@ -738,7 +742,7 @@ bool PCB_EDIT_FRAME::End_Zone( wxDC* DC )
// Put new zone in list // Put new zone in list
if( !s_CurrentZone ) if( !s_CurrentZone )
{ {
zone->m_Poly->Close(); // Close the current corner list zone->m_Poly->CloseLastContour(); // Close the current corner list
GetBoard()->Add( zone ); GetBoard()->Add( zone );
GetBoard()->m_CurrentZoneContour = NULL; GetBoard()->m_CurrentZoneContour = NULL;
@ -753,7 +757,7 @@ bool PCB_EDIT_FRAME::End_Zone( wxDC* DC )
s_CurrentZone->AppendCorner( zone->GetCornerPosition( ii ) ); s_CurrentZone->AppendCorner( zone->GetCornerPosition( ii ) );
} }
s_CurrentZone->m_Poly->Close(); // Close the current corner list s_CurrentZone->m_Poly->CloseLastContour(); // Close the current corner list
zone->RemoveAllContours(); // All corners are copied in s_CurrentZone. Free corner list. zone->RemoveAllContours(); // All corners are copied in s_CurrentZone. Free corner list.
zone = s_CurrentZone; zone = s_CurrentZone;
} }

View File

@ -41,6 +41,7 @@
#include <pcbnew.h> #include <pcbnew.h>
#include <drc_stuff.h> #include <drc_stuff.h>
#include <math_for_graphics.h>
static bool bDontShowSelfIntersectionArcsWarning; static bool bDontShowSelfIntersectionArcsWarning;
@ -311,19 +312,15 @@ int BOARD::ClipAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList,
str += wxT( "This may result in splitting the area.\n" ); str += wxT( "This may result in splitting the area.\n" );
str += wxT( "If the area is complex, this may take a few seconds." ); str += wxT( "If the area is complex, this may take a few seconds." );
wxMessageBox( str ); wxMessageBox( str );
// bDontShowSelfIntersectionWarning = dlg.bDontShowBoxState;
} }
} }
//** TODO test for cutouts outside of area
//** if( test == 1 )
{ {
std::vector<CPolyLine*>* pa = new std::vector<CPolyLine*>; std::vector<CPolyLine*>* pa = new std::vector<CPolyLine*>;
curr_polygon->UnHatch(); curr_polygon->UnHatch();
int n_poly = aCurrArea->m_Poly->NormalizeAreaOutlines( pa, bRetainArcs ); int n_poly = aCurrArea->m_Poly->NormalizeAreaOutlines( pa, bRetainArcs );
// i.e if clipping has created some polygons, we must add these new copper areas. // If clipping has created some polygons, we must add these new copper areas.
if( n_poly > 1 ) if( n_poly > 1 )
{ {
ZONE_CONTAINER* NewArea; ZONE_CONTAINER* NewArea;
@ -803,10 +800,10 @@ int BOARD::CombineAreas( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_r
} }
// polygons intersect, combine them // polygons intersect, combine them
// std::vector<CArc> arc_array1; // TODO: test here if areas intersect and combine only if so
// std::vector<CArc> arc_array2;
bool keep_area_to_combine = false; // TODO test if areas intersect
#if 0
// do not set to 1 (not fully working): only for me (JP. Charras) until this code is finished
KI_POLYGON_WITH_HOLES areaRefPoly; KI_POLYGON_WITH_HOLES areaRefPoly;
KI_POLYGON_WITH_HOLES areaToMergePoly; KI_POLYGON_WITH_HOLES areaToMergePoly;
CopyPolysListToKiPolygonWithHole( area_ref->m_Poly->m_CornersList, areaRefPoly ); CopyPolysListToKiPolygonWithHole( area_ref->m_Poly->m_CornersList, areaRefPoly );
@ -814,14 +811,12 @@ int BOARD::CombineAreas( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_r
KI_POLYGON_WITH_HOLES_SET mergedOutlines; KI_POLYGON_WITH_HOLES_SET mergedOutlines;
mergedOutlines.push_back( areaRefPoly ); mergedOutlines.push_back( areaRefPoly );
mergedOutlines += areaToMergePoly; mergedOutlines |= areaToMergePoly;
// We should have only one polygon with holes in mergedOutlines // We can have more than one polygon with holes in mergedOutlines
// or the 2 initial outlines do not intersect // depending on the complexity of outlines
if( mergedOutlines.size() > 1 )
return 0;
areaRefPoly = mergedOutlines[0]; areaRefPoly = mergedOutlines[0]; // TODO: read and create all created polygons
area_ref->m_Poly->RemoveAllContours(); area_ref->m_Poly->RemoveAllContours();
KI_POLYGON_WITH_HOLES::iterator_type corner = areaRefPoly.begin(); KI_POLYGON_WITH_HOLES::iterator_type corner = areaRefPoly.begin();
@ -833,7 +828,7 @@ int BOARD::CombineAreas( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_r
area_ref->m_Poly->AppendCorner( corner->x(), corner->y() ); area_ref->m_Poly->AppendCorner( corner->x(), corner->y() );
} }
area_ref->m_Poly->Close(); area_ref->m_Poly->CloseLastContour();
// add holes (set of polygons) // add holes (set of polygons)
KI_POLYGON_WITH_HOLES::iterator_holes_type hole = areaRefPoly.begin_holes(); KI_POLYGON_WITH_HOLES::iterator_holes_type hole = areaRefPoly.begin_holes();
@ -846,17 +841,83 @@ int BOARD::CombineAreas( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_r
area_ref->m_Poly->AppendCorner( hole_corner->x(), hole_corner->y() ); area_ref->m_Poly->AppendCorner( hole_corner->x(), hole_corner->y() );
hole_corner++; hole_corner++;
} }
area_ref->m_Poly->Close(); area_ref->m_Poly->CloseLastContour();
hole++; hole++;
} }
#else
void armBoolEng( Bool_Engine* aBooleng, bool aConvertHoles = false );
Bool_Engine* booleng = new Bool_Engine();
armBoolEng( booleng );
area_ref->m_Poly->AddPolygonsToBoolEng( booleng, GROUP_A );
area_to_combine->m_Poly->AddPolygonsToBoolEng(booleng, GROUP_B );
booleng->Do_Operation( BOOL_OR );
// create area with external contour: Recreate only area edges, NOT holes
if( booleng->StartPolygonGet() )
{
if( booleng->GetPolygonPointEdgeType() == KB_INSIDE_EDGE )
{
DisplayError( NULL, wxT( "BOARD::CombineAreas() error: unexpected hole descriptor" ) );
}
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->CloseLastContour();
}
// 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->CloseLastContour();
booleng->EndPolygonGet();
}
#endif
if( !keep_area_to_combine )
RemoveArea( aDeletedList, area_to_combine ); RemoveArea( aDeletedList, area_to_combine );
area_ref->utility = 1; area_ref->utility = 1;
// area_ref->m_Poly->RestoreArcs( &arc_array1 );
// area_ref->m_Poly->RestoreArcs( &arc_array2 );
area_ref->m_Poly->Hatch(); area_ref->m_Poly->Hatch();
return 1; return 1;
@ -917,6 +978,11 @@ int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_E
// ZONE_CONTAINER::GetClearance(). // ZONE_CONTAINER::GetClearance().
int zone2zoneClearance = Area_Ref->GetClearance( area_to_test ); int zone2zoneClearance = Area_Ref->GetClearance( area_to_test );
// Keepout areas have no clearance, so set zone2zoneClearance to 1
// ( zone2zoneClearance = 0 can create problems in test functions)
if( Area_Ref->GetIsKeepout() )
zone2zoneClearance = 1;
// test for some corners of Area_Ref inside area_to_test // test for some corners of Area_Ref inside area_to_test
for( int ic = 0; ic < refSmoothedPoly->GetNumCorners(); ic++ ) for( int ic = 0; ic < refSmoothedPoly->GetNumCorners(); ic++ )
{ {
@ -1114,6 +1180,11 @@ bool DRC::doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex )
if( area_to_test->GetIsKeepout() != aArea->GetIsKeepout() ) if( area_to_test->GetIsKeepout() != aArea->GetIsKeepout() )
continue; continue;
// For keepout, there is no clearance, so use a minimal value for it
// use 1, not 0 as value to avoid some issues in tests
if( area_to_test->GetIsKeepout() )
zone_clearance = 1;
// test for ending line inside area_to_test // test for ending line inside area_to_test
if( area_to_test->m_Poly->TestPointInside( end.x, end.y ) ) if( area_to_test->m_Poly->TestPointInside( end.x, end.y ) )
{ {
@ -1159,7 +1230,7 @@ bool DRC::doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex )
0, 0,
ax1, ay1, ax2, ay2, astyle, ax1, ay1, ax2, ay2, astyle,
0, 0,
0, zone_clearance,
&x, &y ); &x, &y );
if( d < zone_clearance ) if( d < zone_clearance )

View File

@ -13,11 +13,13 @@
#include <PolyLine.h> #include <PolyLine.h>
#include <bezier_curves.h> #include <bezier_curves.h>
#include <polygon_test_point_inside.h> #include <polygon_test_point_inside.h>
#include <math_for_graphics.h>
CPolyLine::CPolyLine() CPolyLine::CPolyLine()
{ {
m_hatchStyle = NO_HATCH; m_hatchStyle = NO_HATCH;
m_hatchPitch = 0; m_hatchPitch = 0;
m_layer = 0;
m_width = 0; m_width = 0;
m_utility = 0; m_utility = 0;
m_Kbool_Poly_Engine = NULL; m_Kbool_Poly_Engine = NULL;
@ -44,7 +46,7 @@ CPolyLine::~CPolyLine()
* false: holes are not linked: in this mode contours are added clockwise * false: holes are not linked: in this mode contours are added clockwise
* and polygons added counter clockwise are holes (default) * and polygons added counter clockwise are holes (default)
*/ */
static void armBoolEng( Bool_Engine* aBooleng, bool aConvertHoles = false ); void armBoolEng( Bool_Engine* aBooleng, bool aConvertHoles = false );
/** /**
* Function NormalizeWithKbool * Function NormalizeWithKbool
@ -128,12 +130,15 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*>* aExtraPolyList, bool
} }
m_Kbool_Poly_Engine->EndPolygonGet(); m_Kbool_Poly_Engine->EndPolygonGet();
Close(); CloseLastContour();
n_ext_cont++; n_ext_cont++;
} }
else if( aExtraPolyList ) // a new outside contour is found: create a new CPolyLine else if( aExtraPolyList ) // a new outside contour is found: create a new CPolyLine
{ {
polyline = new CPolyLine; // create new poly polyline = new CPolyLine;
polyline->SetLayer( GetLayer() );
polyline->SetHatchStyle( GetHatchStyle() );
polyline->SetHatchPitch( GetHatchPitch() );
aExtraPolyList->push_back( polyline ); // put it in array aExtraPolyList->push_back( polyline ); // put it in array
bool first = true; bool first = true;
@ -152,7 +157,7 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*>* aExtraPolyList, bool
} }
m_Kbool_Poly_Engine->EndPolygonGet(); m_Kbool_Poly_Engine->EndPolygonGet();
polyline->Close( STRAIGHT, false ); polyline->CloseLastContour();
n_ext_cont++; n_ext_cont++;
} }
} }
@ -201,7 +206,7 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*>* aExtraPolyList, bool
polyline->AppendCorner( x, y, STRAIGHT, false ); polyline->AppendCorner( x, y, STRAIGHT, false );
} }
polyline->Close( STRAIGHT, false ); polyline->CloseLastContour();
} }
} }
@ -219,6 +224,42 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*>* aExtraPolyList, bool
} }
/**
* Function AddPolygonsToBoolEng
* Add a CPolyLine to a kbool engine, preparing a boolean op between polygons
* @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 count = 0;
/* Convert the current polyline contour to a kbool polygon: */
MakeKboolPoly();
/* 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 * Function MakeKboolPoly
* fill a kbool engine with a closed polyline contour * fill a kbool engine with a closed polyline contour
@ -254,6 +295,25 @@ int CPolyLine::MakeKboolPoly( std::vector<CArc>* arc_array )
Bool_Engine* booleng = new Bool_Engine(); Bool_Engine* booleng = new Bool_Engine();
armBoolEng( booleng, false ); armBoolEng( booleng, false );
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();
}
}
// first, calculate number of vertices in contour // first, calculate number of vertices in contour
int n_vertices = 0; int n_vertices = 0;
int ic_st = GetContourStart( icont ); int ic_st = GetContourStart( icont );
@ -735,7 +795,7 @@ int CPolyLine::RestoreArcs( std::vector<CArc>* arc_array, std::vector<CPolyLine*
void CPolyLine::Start( int layer, int x, int y, int hatch ) void CPolyLine::Start( int layer, int x, int y, int hatch )
{ {
m_layer = layer; m_layer = layer;
SetHatchStyle( (enum hatch_style) hatch ); SetHatchStyle( (enum HATCH_STYLE) hatch );
CPolyPt poly_pt( x, y ); CPolyPt poly_pt( x, y );
poly_pt.end_contour = false; poly_pt.end_contour = false;
@ -766,19 +826,9 @@ void CPolyLine::AppendCorner( int x, int y, int style, bool bDraw )
// close last polyline contour // close last polyline contour
// //
void CPolyLine::Close( int style, bool bDraw ) void CPolyLine::CloseLastContour()
{ {
if( GetClosed() )
{
wxASSERT( 0 );
}
UnHatch();
m_SideStyle[m_CornersList.size() - 1] = style;
m_CornersList[m_CornersList.size() - 1].end_contour = true; m_CornersList[m_CornersList.size() - 1].end_contour = true;
if( bDraw )
Hatch();
} }
@ -944,7 +994,7 @@ CPolyLine* CPolyLine::Chamfer( unsigned int aDistance )
newPoly->AppendCorner( x1 + nx, y1 + ny ); newPoly->AppendCorner( x1 + nx, y1 + ny );
} }
newPoly->Close(); newPoly->CloseLastContour();
} }
return newPoly; return newPoly;
@ -1072,7 +1122,7 @@ CPolyLine* CPolyLine::Fillet( unsigned int aRadius, unsigned int aSegments )
} }
} }
newPoly->Close(); newPoly->CloseLastContour();
} }
return newPoly; return newPoly;
@ -1632,11 +1682,13 @@ void CPolyLine::SetEndContour( int ic, bool end_contour )
m_CornersList[ic].end_contour = end_contour; m_CornersList[ic].end_contour = end_contour;
} }
/*
* AppendArc adds segments to current contour to approximate the given arc
*/
void CPolyLine::AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num ) void CPolyLine::AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num )
{ {
// get radius // get radius
double r = sqrt( (double) (xi - xc) * (xi - xc) + (double) (yi - yc) * (yi - yc) ); double radius = hypot( (double) (xi - xc), (double) (yi - yc) );
// get angles of start and finish // get angles of start and finish
double th_i = atan2( (double) (yi - yc), (double) (xi - xc) ); double th_i = atan2( (double) (yi - yc), (double) (xi - xc) );
@ -1647,13 +1699,13 @@ void CPolyLine::AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int n
// generate arc // generate arc
for( int ic = 0; ic < num; ic++ ) for( int ic = 0; ic < num; ic++ )
{ {
int x = KiROUND( xc + r * cos( theta ) ); int x = KiROUND( xc + radius * cos( theta ) );
int y = KiROUND( yc + r * sin( theta ) ); int y = KiROUND( yc + radius * sin( theta ) );
AppendCorner( x, y, STRAIGHT, 0 ); AppendCorner( x, y, STRAIGHT, 0 );
theta += th_d; theta += th_d;
} }
Close( STRAIGHT ); CloseLastContour();
} }

View File

@ -58,9 +58,6 @@ public:
} }
}; };
#include <math_for_graphics.h>
class CArc class CArc
{ {
public: public:
@ -107,7 +104,7 @@ class CPolyLine
{ {
public: public:
enum m_SideStyle { 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 enum HATCH_STYLE { NO_HATCH, DIAGONAL_FULL, DIAGONAL_EDGE }; // hatch styles
// constructors/destructor // constructors/destructor
CPolyLine(); CPolyLine();
@ -119,7 +116,7 @@ public:
void InsertCorner( int ic, int x, int y ); void InsertCorner( int ic, int x, int y );
void DeleteCorner( int ic, bool bDraw = false ); void DeleteCorner( int ic, bool bDraw = false );
void MoveCorner( int ic, int x, int y ); void MoveCorner( int ic, int x, int y );
void Close( int style = STRAIGHT, bool bDraw = false ); void CloseLastContour();
void RemoveContour( int icont ); void RemoveContour( int icont );
/** /**
@ -155,6 +152,11 @@ public:
void Copy( CPolyLine* src ); void Copy( CPolyLine* src );
bool TestPointInside( int x, int y ); bool TestPointInside( int x, int y );
bool IsCutoutContour( int icont ); bool IsCutoutContour( int icont );
/**
* Function AppendArc.
* Adds segments to current contour to approximate the given arc
*/
void AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num ); void AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num );
// access functions // access functions
@ -181,13 +183,14 @@ public:
int GetSideStyle( int is ); int GetSideStyle( int is );
int GetHatchPitch() { return m_hatchPitch; } int GetHatchPitch() { return m_hatchPitch; }
int GetDefaultHatchPitchMils() { return 20; } // default hatch pitch value in mils static int GetDefaultHatchPitchMils() { return 20; } // default hatch pitch value in mils
enum hatch_style GetHatchStyle() { return m_hatchStyle; } enum HATCH_STYLE GetHatchStyle() { return m_hatchStyle; }
void SetHatch( int hatch, int pitch ) void SetHatch( int aHatchStyle, int aHatchPitch, bool aRebuildHatch )
{ {
SetHatchPitch( pitch ); SetHatchPitch( aHatchPitch );
m_hatchStyle = (enum hatch_style) hatch; m_hatchStyle = (enum HATCH_STYLE) aHatchStyle;
if( aRebuildHatch )
Hatch(); Hatch();
} }
@ -196,7 +199,7 @@ public:
void SetEndContour( int ic, bool end_contour ); void SetEndContour( int ic, bool end_contour );
void SetSideStyle( int is, int style ); void SetSideStyle( int is, int style );
void SetHatchStyle( enum hatch_style style ) void SetHatchStyle( enum HATCH_STYLE style )
{ {
m_hatchStyle = style; m_hatchStyle = style;
} }
@ -210,6 +213,14 @@ public:
// KBOOL functions // KBOOL functions
/**
* Function AddPolygonsToBoolEng
* Add a CPolyLine to a kbool engine, preparing a boolean op between polygons
* @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 );
/** /**
* Function MakeKboolPoly * Function MakeKboolPoly
* fill a kbool engine with a closed polyline contour * fill a kbool engine with a closed polyline contour
@ -261,7 +272,7 @@ public:
private: private:
int m_layer; // layer to draw on 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 enum HATCH_STYLE m_hatchStyle; // hatch style, see enum above
int m_hatchPitch; // for DIAGONAL_EDGE hatched outlines, basic distance between 2 hatch lines int m_hatchPitch; // for DIAGONAL_EDGE hatched outlines, basic distance between 2 hatch lines
// and the len of eacvh segment // and the len of eacvh segment
// for DIAGONAL_FULL, the pitch is twice this value // for DIAGONAL_FULL, the pitch is twice this value

View File

@ -9,9 +9,23 @@
#include <fctsys.h> #include <fctsys.h>
#include <PolyLine.h> #include <PolyLine.h>
#include <math_for_graphics.h>
#define NM_PER_MIL 25400 #define NM_PER_MIL 25400
typedef struct PointTag
{
double X,Y;
} PointT;
typedef struct EllipseTag
{
PointT Center; /* ellipse center */
double xrad, yrad; // radii on x and y
double theta1, theta2; // start and end angle for arc
} EllipseKH;
double Distance( double x1, double y1, double x2, double y2 ) double Distance( double x1, double y1, double x2, double y2 )
{ {
double dx = x1 - x2; double dx = x1 - x2;
@ -21,6 +35,13 @@ double Distance( double x1, double y1, double x2, double y2 )
} }
static int GetArcIntersections( EllipseKH * el1, EllipseKH * el2,
double * x1=NULL, double * y1=NULL,
double * x2=NULL, double * y2=NULL );
static bool InRange( double x, double xi, double xf );
/** /**
* Function TestLineHit * Function TestLineHit
* test for hit on line segment i.e. a point within a given distance from segment * test for hit on line segment i.e. a point within a given distance from segment
@ -862,26 +883,26 @@ bool FindLineEllipseIntersections( double a, double b, double c, double d, doubl
// Get clearance between 2 segments // Get clearance between 2 segments
// Returns point in segment closest to other segment in x, y // Returns point in segment closest to other segment in x, y
// in clearance > max_cl, just returns max_cl and doesn't return x,y // in clearance > max_cl, just returns max_cl+1 and doesn't return x,y
// //
int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int style1, int w1, int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int style1, int w1,
int x2i, int y2i, int x2f, int y2f, int style2, int w2, int x2i, int y2i, int x2f, int y2f, int style2, int w2,
int max_cl, int* x, int* y ) int max_cl, int* x, int* y )
{ {
// check clearance between bounding rectangles // check clearance between bounding rectangles
int test = max_cl + w1 / 2 + w2 / 2; int min_dist = max_cl + ( (w1 + w2) / 2 );
if( min( x1i, x1f ) - max( x2i, x2f ) > test ) if( min( x1i, x1f ) - max( x2i, x2f ) > min_dist )
return max_cl; return max_cl+1;
if( min( x2i, x2f ) - max( x1i, x1f ) > test ) if( min( x2i, x2f ) - max( x1i, x1f ) > min_dist )
return max_cl; return max_cl+1;
if( min( y1i, y1f ) - max( y2i, y2f ) > test ) if( min( y1i, y1f ) - max( y2i, y2f ) > min_dist )
return max_cl; return max_cl+1;
if( min( y2i, y2f ) - max( y1i, y1f ) > test ) if( min( y2i, y2f ) - max( y1i, y1f ) > min_dist )
return max_cl; return max_cl+1;
if( style1 == CPolyLine::STRAIGHT && style1 == CPolyLine::STRAIGHT ) if( style1 == CPolyLine::STRAIGHT && style1 == CPolyLine::STRAIGHT )
{ {
@ -890,7 +911,9 @@ int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int style1,
double dd; double dd;
TestForIntersectionOfStraightLineSegments( x1i, y1i, x1f, y1f, TestForIntersectionOfStraightLineSegments( x1i, y1i, x1f, y1f,
x2i, y2i, x2f, y2f, &xx, &yy, &dd ); x2i, y2i, x2f, y2f, &xx, &yy, &dd );
int d = max( 0, (int) dd - w1 / 2 - w2 / 2 ); int d = (int) dd - ( (w1 + w2) / 2 );
if( d < 0 )
d = 0;
if( x ) if( x )
*x = xx; *x = xx;
@ -905,10 +928,10 @@ int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int style1,
// see if segments intersect // see if segments intersect
double xr[2]; double xr[2];
double yr[2]; double yr[2];
test = int count =
FindSegmentIntersections( x1i, y1i, x1f, y1f, style1, x2i, y2i, x2f, y2f, style2, xr, yr ); FindSegmentIntersections( x1i, y1i, x1f, y1f, style1, x2i, y2i, x2f, y2f, style2, xr, yr );
if( test ) if( count )
{ {
if( x ) if( x )
*x = (int) xr[0]; *x = (int) xr[0];

View File

@ -1,22 +1,5 @@
// math stuff for graphics, from FreePCB // math stuff for graphics, from FreePCB
#ifndef abs
#define abs(x) (((x) >=0) ? (x) : (-(x)))
#endif
typedef struct PointTag
{
double X,Y;
} PointT;
typedef struct EllipseTag
{
PointT Center; /* ellipse center */
double xrad, yrad; // radii on x and y
double theta1, theta2; // start and end angle for arc
} EllipseKH;
// math stuff for graphics // math stuff for graphics
bool Quadratic( double a, double b, double c, double *x1, double *x2 ); bool Quadratic( double a, double b, double c, double *x1, double *x2 );
@ -70,11 +53,5 @@ int GetClearanceBetweenSegments( int x1i, int y1i, int x1f, int y1f, int style1,
double GetPointToLineSegmentDistance( int x, int y, int xi, int yi, int xf, int yf ); double GetPointToLineSegmentDistance( int x, int y, int xi, int yi, int xf, int yf );
double GetPointToLineDistance( double a, double b, int x, int y, double * xp=NULL, double * yp=NULL ); double GetPointToLineDistance( double a, double b, int x, int y, double * xp=NULL, double * yp=NULL );
bool InRange( double x, double xi, double xf );
double Distance( double x1, double y1, double x2, double y2 ); double Distance( double x1, double y1, double x2, double y2 );
int GetArcIntersections( EllipseKH * el1, EllipseKH * el2,
double * x1=NULL, double * y1=NULL,
double * x2=NULL, double * y2=NULL );