Commit 1c9433fb authored by Miguel Angel Ajo's avatar Miguel Angel Ajo

merged divertion

parents a8e4f8b0 99b90d2f
......@@ -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;
......
......@@ -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,
......
......@@ -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. */
......
......@@ -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 );
......
......@@ -167,19 +167,19 @@ void ZONE_CONTAINER::TransformShapeWithClearanceToPolygon( std::vector <CPolyPt>
// 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<KPolyPoint> cornerslist;
KI_POLYGON_SET polyset_zone_solid_areas;
std::vector<KI_POLY_POINT> 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 <CPolyPt>
// 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;
......
......@@ -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 )
{
......
......@@ -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;
......
......@@ -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();
......
......@@ -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
......
......@@ -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();
......
......@@ -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<TRACK>& aTrackList )
while( track != NULL )
{
TRACK* next_track = track->Next();
LockPoint = pcb->GetPad( track, END );
LockPoint = pcb->GetPad( track, FLG_END );
if( LockPoint )
{
......
......@@ -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() )
......
......@@ -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" );
......
......@@ -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 );
......
......@@ -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) */
......
/*
* file polygons_defs.h
* definitions to use boost::polygon in KiCad.
*/
#ifndef _POLYGONS_DEFS_H_
#define _POLYGONS_DEFS_H_
#include <boost/polygon/polygon.hpp>
// Define some types used here from boost::polygon
namespace bpl = boost::polygon; // bpl = boost polygon library
using namespace bpl::operators; // +, -, =, ...
typedef int coordinate_type;
typedef bpl::polygon_data<int> KPolygon;
typedef std::vector<KPolygon> KPolygonSet;
typedef bpl::point_data<int> KPolyPoint;
#endif // #ifndef _POLYGONS_DEFS_H_
......@@ -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( ; ndx<count; ++ndx )
{
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 );
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; ndx<count; ++ndx )
{
if( item->m_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( ; ndx<count; ++ndx )
{
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 );
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; ndx<count; ++ndx )
{
if( item->m_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) );
}
}
......
......@@ -89,39 +89,12 @@ int ZONE_CONTAINER::BuildFilledPolysListData( BOARD* aPcb, std::vector <CPolyPt>
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 <CPolyPt>
Fill_Zone_Areas_With_Segments( );
}
return count;
return 1;
}
// Sort function to build filled zones
......@@ -188,7 +161,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;
......
......@@ -81,14 +81,14 @@ extern void CreateThermalReliefPadPolygon( std::vector<CPolyPt>& aCornerBuffer,
int aThermalRot );
// Local Functions: helper function to calculate solid areas
static void AddPolygonCornersToKPolygonList( std::vector <CPolyPt>& aCornersBuffer,
KPolygonSet& aKPolyList );
static void AddPolygonCornersToKiPolygonList( std::vector <CPolyPt>& 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 <CPolyPt>& aCornersBuffer,
KPolygonSet& aKPolyList )
void AddPolygonCornersToKiPolygonList( std::vector <CPolyPt>& aCornersBuffer,
KI_POLYGON_SET& aKiPolyList )
{
unsigned ii;
std::vector<KPolyPoint> cornerslist;
std::vector<KI_POLY_POINT> cornerslist;
int polycount = 0;
......@@ -485,49 +485,45 @@ void AddPolygonCornersToKPolygonList( std::vector <CPolyPt>& 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<CPolyPt> 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;
// 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++;
}
......@@ -542,10 +538,10 @@ int CopyPolygonsFromKPolygonListToFilledPolysList( ZONE_CONTAINER* aZone,
}
int CopyPolygonsFromFilledPolysListTotKPolygonList( ZONE_CONTAINER* aZone,
KPolygonSet& aKPolyList )
int CopyPolygonsFromFilledPolysListToKiPolygonList( ZONE_CONTAINER* aZone,
KI_POLYGON_SET& aKiPolyList )
{
std::vector<CPolyPt> polysList = aZone->GetFilledPolysList();
const std::vector<CPolyPt>& polysList = aZone->GetFilledPolysList();
unsigned corners_count = polysList.size();
int count = 0;
unsigned ic = 0;
......@@ -554,35 +550,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<KPolyPoint> cornerslist;
aKiPolyList.reserve( polycount );
std::vector<KI_POLY_POINT> 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 );
}
}
......
......@@ -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;
......
......@@ -142,7 +142,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<CRect> cr;
......@@ -550,7 +550,7 @@ bool BOARD::TestAreaIntersections( ZONE_CONTAINER* area_to_test )
continue;
// test for intersecting segments
for( int icont1 = 0; icont1<poly1->GetNumContours(); icont1++ )
for( int icont1 = 0; icont1<poly1->GetContoursCount(); icont1++ )
{
int is1 = poly1->GetContourStart( icont1 );
int ie1 = poly1->GetContourEnd( icont1 );
......@@ -574,7 +574,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 +668,7 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_
bool bInt = false;
bool bArcInt = false;
for( int icont1 = 0; icont1<poly1->GetNumContours(); icont1++ )
for( int icont1 = 0; icont1<poly1->GetContoursCount(); icont1++ )
{
int is1 = poly1->GetContourStart( icont1 );
int ie1 = poly1->GetContourEnd( icont1 );
......@@ -692,7 +692,7 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_
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 );
......@@ -781,142 +781,84 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_
/**
* 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<CArc> arc_array1;
std::vector<CArc> arc_array2;
bool keep_area_to_combine = false;
Bool_Engine* booleng = new Bool_Engine();
ArmBoolEng( booleng );
// std::vector<CArc> arc_array1;
// std::vector<CArc> arc_array2;
bool keep_area_to_combine = false; // TODO test if areas intersect
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 );
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;
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 );
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() )
{
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->Close();
}
// 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_ref->m_Poly->Start( area_ref->GetLayer(), corner->x(), corner->y(),
area_ref->m_Poly->GetHatchStyle() );
while( ++corner != areaRefPoly.end() )
{
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();
}
area_ref->m_Poly->AppendCorner( corner->x(), corner->y() );
}
#endif
// add holes
bool show_error = true;
area_ref->m_Poly->Close();
while( booleng->StartPolygonGet() )
// add holes (set of polygons)
KI_POLYGON_WITH_HOLES::iterator_holes_type hole = areaRefPoly.begin_holes();
while( hole != areaRefPoly.end_holes() )
{
// we expect all vertex are holes inside the main outline
if( booleng->GetPolygonPointEdgeType() != KB_INSIDE_EDGE )
KI_POLYGON::iterator_type hole_corner = hole->begin();
// create area with external contour: Recreate only area edges, NOT holes
while( hole_corner != hole->end() )
{
if( show_error ) // show this error only once, if happens
DisplayError( NULL,
wxT( "BOARD::CombineAreas() error: unexpected outside contour descriptor" ) );
show_error = false;
continue;
area_ref->m_Poly->AppendCorner( hole_corner->x(), hole_corner->y() );
hole_corner++;
}
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();
hole++;
}
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 +966,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 +990,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 +1070,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 +1083,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 +1131,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 );
......
......@@ -16,10 +16,10 @@
CPolyLine::CPolyLine()
{
m_hatchStyle = NO_HATCH;
m_hatchPitch = 0;
m_Width = 0;
utility = 0;
m_hatchStyle = NO_HATCH;
m_hatchPitch = 0;
m_width = 0;
m_utility = 0;
m_Kbool_Poly_Engine = NULL;
}
......@@ -29,11 +29,23 @@ CPolyLine::CPolyLine()
CPolyLine::~CPolyLine()
{
UnHatch();
if( m_Kbool_Poly_Engine )
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
* Use the Kbool Library to clip contours: if outlines are crossing, the self-crossing polygon
......@@ -46,11 +58,11 @@ CPolyLine::~CPolyLine()
* @param bRetainArcs == true, try to retain arcs in polys
* @return number of external contours, or -1 if error
*/
int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*> * aExtraPolyList, bool bRetainArcs )
int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*>* aExtraPolyList, bool bRetainArcs )
{
std::vector<CArc> arc_array;
std::vector <void*> hole_array; // list of holes
std::vector<int> * hole; // used to store corners for a given hole
std::vector<int>* hole; // used to store corners for a given hole
CPolyLine* polyline;
int n_ext_cont = 0; // CPolyLine count
......@@ -61,9 +73,9 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*> * 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();
......@@ -82,10 +94,11 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*> * aExtraPolyList, boo
{
hole = new std::vector<int>;
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 );
}
......@@ -95,14 +108,16 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*> * 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() )
{
// 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;
......@@ -121,10 +136,12 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*> * 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;
......@@ -143,8 +160,9 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*> * aExtraPolyList, boo
// now add cutouts to the corresponding CPolyLine(s)
for( unsigned ii = 0; ii < hole_array.size(); ii++ )
{
hole = (std::vector<int> *)hole_array[ii];
polyline = NULL;
hole = (std::vector<int>*)hole_array[ii];
polyline = NULL;
if( n_ext_cont == 1 )
{
polyline = this;
......@@ -154,8 +172,9 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*> * 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 )
......@@ -177,8 +196,8 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*> * 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 );
}
......@@ -194,76 +213,21 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*> * aExtraPolyList, boo
// free hole list
for( unsigned ii = 0; ii < hole_array.size(); ii++ )
delete (std::vector<int> *)hole_array[ii];
delete (std::vector<int>*)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<CArc> * 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<CArc> * arc_array,
bool aConvertHoles )
int CPolyLine::MakeKboolPoly( std::vector<CArc>* arc_array )
{
if( m_Kbool_Poly_Engine )
{
......@@ -271,65 +235,40 @@ int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector<
m_Kbool_Poly_Engine = NULL;
}
int polycount = GetNumContours();
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 = side_style[ic];
int style = m_SideStyle[ic];
if( style == STRAIGHT )
n_vertices++;
else
......@@ -343,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 = 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 )
{
booleng->AddPoint( x1, y1 );
......@@ -367,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
......@@ -412,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;
}
}
......@@ -446,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; is<n; is++ )
{
double theta = theta1 + ( (theta2 - theta1) * (double) is ) / n;
double x = xo + a* cos( theta );
double y = yo + b* sin( theta );
double theta = theta1 + ( (theta2 - theta1) * (double) is ) / n;
double x = xo + a* cos( theta );
double y = yo + b* sin( theta );
if( is == 0 )
{
x = x1;
y = y1;
x = x1;
y = y1;
}
booleng->AddPoint( x, y );
ivtx++;
}
......@@ -474,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.
......@@ -484,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 );
}
......@@ -496,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;
}
......@@ -504,69 +451,70 @@ 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
// 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.
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
/*
* 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
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
/*
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!
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 = 1;
aBooleng->SetMarge( MARGE );
......@@ -581,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
......@@ -596,7 +544,7 @@ void ArmBoolEng( Bool_Engine* aBooleng, bool aConvertHoles )
}
int CPolyLine::NormalizeAreaOutlines( std::vector<CPolyLine*> * pa, bool bRetainArcs )
int CPolyLine::NormalizeAreaOutlines( std::vector<CPolyLine*>* pa, bool bRetainArcs )
{
return NormalizeWithKbool( pa, bRetainArcs );
}
......@@ -605,33 +553,37 @@ int CPolyLine::NormalizeAreaOutlines( std::vector<CPolyLine*> * 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<CArc> * arc_array, std::vector<CPolyLine*> * pa )
int CPolyLine::RestoreArcs( std::vector<CArc>* arc_array, std::vector<CPolyLine*>* pa )
{
// get poly info
int n_polys = 1;
if( pa )
n_polys += pa->size();
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<n_polys; ip++ )
{
if( ip == 0 )
poly = this;
else
poly = (*pa)[ip - 1];
poly->UnHatch();
for( int ic = 0; ic<poly->GetNumCorners(); ic++ )
poly->SetUtility( ic, 0 );
// clear utility flag
// clear m_utility flag
}
// find arcs and replace them
bool bFound;
int arc_start = 0;
int arc_end = 0;
bool bFound;
int arc_start = 0;
int arc_end = 0;
for( unsigned iarc = 0; iarc<arc_array->size(); iarc++ )
{
int arc_xi = (*arc_array)[iarc].xi;
......@@ -649,62 +601,77 @@ int CPolyLine::RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine
poly = this;
else
poly = (*pa)[ip - 1];
int polycount = poly->GetNumContours();
int polycount = poly->GetContoursCount();
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->side_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; )
{
if( i > ic_end )
i = ic_start;
poly->SetUtility( i, 1 );
if( i == ic_end )
i = ic_start;
else
......@@ -714,10 +681,12 @@ int CPolyLine::RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine
break;
}
}
if( bFound )
break;
}
}
if( bFound )
break;
}
......@@ -734,6 +703,7 @@ int CPolyLine::RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine
poly = this;
else
poly = (*pa)[ip - 1];
for( int ic = poly->GetNumCorners() - 1; ic>=0; ic-- )
{
if( poly->GetUtility( ic ) )
......@@ -751,26 +721,26 @@ int CPolyLine::RestoreArcs( std::vector<CArc> * arc_array, std::vector<CPolyLine
// if sel_box = 0, don't create selection elements at all
//
// if polyline is board outline, enter with:
// id.type = ID_BOARD
// id.st = ID_BOARD_OUTLINE
// id.i = 0
// ptr = NULL
// id.type = ID_BOARD
// id.st = ID_BOARD_OUTLINE
// id.i = 0
// ptr = NULL
//
// if polyline is copper area, enter with:
// id.type = ID_NET;
// id.st = ID_AREA
// id.i = index to area
// ptr = pointer to net
// id.type = ID_NET;
// id.st = ID_AREA
// id.i = index to area
// ptr = pointer to net
//
void CPolyLine::Start( int layer, int x, int y, int hatch )
{
m_layer = layer;
m_layer = layer;
SetHatchStyle( (enum hatch_style) 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 +753,12 @@ 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();
}
......@@ -800,9 +772,11 @@ 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 +787,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();
}
......@@ -824,32 +798,35 @@ 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 < GetNumContours() - 1 || GetClosed();
int icont = GetContour( ic );
int istart = GetContourStart( icont );
int iend = GetContourEnd( icont );
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 )
{
// delete the entire contour
RemoveContour( icont );
}
if( bDraw )
Hatch();
}
......@@ -866,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();
int polycount = GetNumContours();
if( icont == 0 && polycount == 1 )
{
// remove the only contour
......@@ -878,18 +856,19 @@ 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,65 +883,67 @@ 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 );
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 = 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) );
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();
}
......@@ -980,115 +961,120 @@ 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 );
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 = 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) );
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;
}
......@@ -1103,8 +1089,8 @@ void CPolyLine::RemoveAllContours( void )
* Others params are not chnaged
*/
{
corner.clear();
side_style.clear();
m_CornersList.clear();
m_SideStyle.clear();
}
......@@ -1117,25 +1103,27 @@ 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 +1138,7 @@ void CPolyLine::UnHatch()
int CPolyLine::GetEndContour( int ic )
{
return corner[ic].end_contour;
return m_CornersList[ic].end_contour;
}
......@@ -1158,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;
}
......@@ -1172,12 +1160,13 @@ CRect CPolyLine::GetCornerBounds()
r.left = r.bottom = INT_MAX;
r.right = r.top = INT_MIN;
for( unsigned i = 0; i<corner.size(); i++ )
for( unsigned i = 0; i<m_CornersList.size(); i++ )
{
r.left = min( r.left, corner[i].x );
r.right = max( r.right, corner[i].x );
r.bottom = min( r.bottom, corner[i].y );
r.top = max( r.top, corner[i].y );
r.left = min( r.left, m_CornersList[i].x );
r.right = max( r.right, m_CornersList[i].x );
r.bottom = min( r.bottom, m_CornersList[i].y );
r.top = max( r.top, m_CornersList[i].y );
}
return r;
......@@ -1190,14 +1179,15 @@ CRect CPolyLine::GetCornerBounds( int icont )
r.left = r.bottom = INT_MAX;
r.right = r.top = INT_MIN;
int istart = GetContourStart( icont );
int iend = GetContourEnd( icont );
int istart = GetContourStart( icont );
int iend = GetContourEnd( icont );
for( int i = istart; i<=iend; i++ )
{
r.left = min( r.left, corner[i].x );
r.right = max( r.right, corner[i].x );
r.bottom = min( r.bottom, corner[i].y );
r.top = max( r.top, corner[i].y );
r.left = min( r.left, m_CornersList[i].x );
r.right = max( r.right, m_CornersList[i].x );
r.bottom = min( r.bottom, m_CornersList[i].y );
r.top = max( r.top, m_CornersList[i].y );
}
return r;
......@@ -1206,32 +1196,35 @@ CRect CPolyLine::GetCornerBounds( int icont )
int CPolyLine::GetNumCorners()
{
return corner.size();
return m_CornersList.size();
}
int CPolyLine::GetNumSides()
{
if( GetClosed() )
return corner.size();
return m_CornersList.size();
else
return corner.size() - 1;
return m_CornersList.size() - 1;
}
int CPolyLine::GetNumContours()
int CPolyLine::GetContoursCount()
{
int ncont = 0;
if( !corner.size() )
if( !m_CornersList.size() )
return 0;
for( unsigned ic = 0; ic<corner.size(); ic++ )
if( corner[ic].end_contour )
for( unsigned ic = 0; ic < m_CornersList.size(); ic++ )
if( m_CornersList[ic].end_contour )
ncont++;
if( !corner[corner.size() - 1].end_contour )
if( !m_CornersList[m_CornersList.size() - 1].end_contour )
ncont++;
return ncont;
}
......@@ -1242,7 +1235,7 @@ int CPolyLine::GetContour( int ic )
for( int i = 0; i<ic; i++ )
{
if( corner[i].end_contour )
if( m_CornersList[i].end_contour )
ncont++;
}
......@@ -1256,11 +1249,13 @@ int CPolyLine::GetContourStart( int icont )
return 0;
int ncont = 0;
for( unsigned i = 0; i<corner.size(); i++ )
for( unsigned i = 0; i<m_CornersList.size(); i++ )
{
if( corner[i].end_contour )
if( m_CornersList[i].end_contour )
{
ncont++;
if( ncont == icont )
return i + 1;
}
......@@ -1276,16 +1271,18 @@ int CPolyLine::GetContourEnd( int icont )
if( icont < 0 )
return 0;
if( icont == GetNumContours() - 1 )
return corner.size() - 1;
if( icont == GetContoursCount() - 1 )
return m_CornersList.size() - 1;
int ncont = 0;
for( unsigned i = 0; i<corner.size(); i++ )
for( unsigned i = 0; i<m_CornersList.size(); i++ )
{
if( corner[i].end_contour )
if( m_CornersList[i].end_contour )
{
if( ncont == icont )
return i;
ncont++;
}
}
......@@ -1305,50 +1302,55 @@ void CPolyLine::SetSideStyle( int is, int style )
{
UnHatch();
wxPoint p1, p2;
if( is == (int) (corner.size() - 1) )
if( is == (int) (m_CornersList.size() - 1) )
{
p1.x = corner[corner.size() - 1].x;
p1.y = corner[corner.size() - 1].y;
p2.x = corner[0].x;
p2.y = corner[0].y;
p1.x = m_CornersList[m_CornersList.size() - 1].x;
p1.y = m_CornersList[m_CornersList.size() - 1].y;
p2.x = m_CornersList[0].x;
p2.y = m_CornersList[0].y;
}
else
{
p1.x = corner[is].x;
p1.y = corner[is].y;
p2.x = corner[is + 1].x;
p2.y = corner[is + 1].y;
p1.x = m_CornersList[is].x;
p1.y = m_CornersList[is].y;
p2.x = m_CornersList[is + 1].x;
p2.y = m_CornersList[is + 1].y;
}
if( p1.x == p2.x || p1.y == p2.y )
side_style[is] = STRAIGHT;
m_SideStyle[is] = STRAIGHT;
else
side_style[is] = style;
m_SideStyle[is] = style;
Hatch();
}
int CPolyLine::GetSideStyle( int is )
{
return side_style[is];
return m_SideStyle[is];
}
int CPolyLine::GetClosed()
{
if( corner.size() == 0 )
if( m_CornersList.size() == 0 )
return 0;
else
return corner[corner.size() - 1].end_contour;
return m_CornersList[m_CornersList.size() - 1].end_contour;
}
// Creates hatch lines inside the outline of the complex polygon
//
// sort function used in ::Hatch to sort points by descending wxPoint.x values
bool sort_ends_by_descending_X( const wxPoint& ref, const wxPoint& tst )
bool sort_ends_by_descending_X( const wxPoint& ref, const wxPoint& tst )
{
return tst.x < ref.x;
}
void CPolyLine::Hatch()
{
m_HatchLines.clear();
......@@ -1356,51 +1358,58 @@ void CPolyLine::Hatch()
if( m_hatchStyle == NO_HATCH || m_hatchPitch == 0 )
return;
if( !GetClosed() ) // If not closed, the poly is beeing created and not finalised. Not not hatch
if( !GetClosed() ) // If not closed, the poly is beeing created and not finalised. Not not hatch
return;
// define range for hatch lines
int min_x = corner[0].x;
int max_x = corner[0].x;
int min_y = corner[0].y;
int max_y = corner[0].y;
for( unsigned ic = 1; ic < corner.size(); ic++ )
int min_x = m_CornersList[0].x;
int max_x = m_CornersList[0].x;
int min_y = m_CornersList[0].y;
int max_y = m_CornersList[0].y;
for( unsigned ic = 1; ic < m_CornersList.size(); ic++ )
{
if( corner[ic].x < min_x )
min_x = corner[ic].x;
if( corner[ic].x > 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
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,
......@@ -1409,7 +1418,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
......@@ -1417,7 +1426,7 @@ void CPolyLine::Hatch()
static std::vector <wxPoint> pointbuffer;
pointbuffer.clear();
pointbuffer.reserve(MAXPTS+2);
pointbuffer.reserve( MAXPTS + 2 );
for( int a = min_a; a < max_a; a += spacing )
{
......@@ -1429,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<nc; ic++ )
{
double x, y, x2, y2;
int ok;
if( corner[ic].end_contour || ( ic == (int) (corner.size() - 1) ) )
double x, y, x2, y2;
int ok;
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],
&x, &y, &x2, &y2 );
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],
&x, &y, &x2, &y2 );
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 )
{
wxPoint point( (int) x, (int) y);
wxPoint point( (int) x, (int) y );
pointbuffer.push_back( point );
}
if( ok == 2 )
{
wxPoint point( (int) x2, (int) y2);
wxPoint point( (int) x2, (int) y2 );
pointbuffer.push_back( point );
}
if( pointbuffer.size() >= MAXPTS ) // overflow
{
wxASSERT( 0 );
......@@ -1485,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
......@@ -1494,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,
......@@ -1534,32 +1549,34 @@ 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();
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( 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;
}
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
corner = src->corner;
m_CornersList = src->m_CornersList;
// copy side styles, using vector copy
side_style = src->side_style;
m_SideStyle = src->m_SideStyle;
}
......@@ -1573,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;
}
......@@ -1582,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 );
......@@ -1593,43 +1612,43 @@ 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 )
{
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;
}
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<num; ic++ )
{
int x = KiROUND( xc + r * cos( theta ) );
int y = KiROUND( yc + r * sin( theta ) );
int x = KiROUND( xc + r * cos( theta ) );
int y = KiROUND( yc + r * sin( theta ) );
AppendCorner( x, y, STRAIGHT, 0 );
theta += th_d;
}
......@@ -1637,23 +1656,27 @@ void CPolyLine::AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int n
Close( STRAIGHT );
}
// Bezier Support
void CPolyLine::AppendBezier(int x1, int y1, int x2, int y2, int x3, int y3)
void CPolyLine::AppendBezier( int x1, int y1, int x2, int y2, int x3, int y3 )
{
std::vector<wxPoint> 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<wxPoint> 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 );
}
......@@ -1675,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 = GetNumContours();
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++ )
......@@ -1705,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;
}
......@@ -1717,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):
......@@ -1731,13 +1757,13 @@ int CPolyLine::Distance( const wxPoint& aPoint )
if( TestPointInside( aPoint.x, aPoint.y ) )
return 0;
int distance = INT_MAX;
int polycount = GetNumContours();
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++ )
......@@ -1760,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;
}
......@@ -1772,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<CPolyPt>& aPolysList,
KI_POLYGON_WITH_HOLES& aPolygoneWithHole )
{
unsigned corners_count = aPolysList.size();
std::vector<KI_POLY_POINT> 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<CPolyPt>& aPolysListWithHoles,
std::vector<CPolyPt>& 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<KI_POLY_POINT> 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 );
}
}
......@@ -19,11 +19,12 @@
#include <kbool/include/kbool/booleng.h>
#include <pad_shapes.h>
#include <wx/gdicmn.h>
#include <wx/gdicmn.h> // for wxPoint definition
#include <polygons_defs.h>
// 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,
......@@ -31,18 +32,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:
......@@ -56,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;
}
};
......@@ -75,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;
};
......@@ -86,27 +76,27 @@ 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.
// / 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;
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); }
};
......@@ -116,7 +106,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
......@@ -124,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
......@@ -138,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
......@@ -147,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 GetNumContours();
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; }
int GetX( int ic ) const { return corner[ic].x; }
int GetY( int ic ) const { return corner[ic].y; }
const wxPoint& GetPos( int ic ) const { return m_CornersList[ic]; }
const wxPoint& GetPos( int ic ) const { return corner[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 GetUtility( int ic ) { return corner[ic].utility; };
void SetUtility( int ic, int utility ) { corner[ic].utility = utility; };
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<CArc> * arc_array, std::vector<CPolyLine*> * pa = NULL );
int RestoreArcs( std::vector<CArc>* arc_array, std::vector<CPolyLine*>* pa = NULL );
int NormalizeAreaOutlines( std::vector<CPolyLine*> * pa = NULL,
bool bRetainArcs = false );
int NormalizeAreaOutlines( std::vector<CPolyLine*>* 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<CArc> * 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<CArc> * arc_array = NULL,
bool aConvertHoles = false);
int MakeKboolPoly( std::vector<CArc>* arc_array = NULL );
/**
* Function NormalizeWithKbool
......@@ -262,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<CPolyLine*> * 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<CPolyLine*>* 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
......@@ -286,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
......@@ -297,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 utility;
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 <CPolyPt> corner; // array of points for corners
std::vector <int> side_style; // array of styles for sides
std::vector <CSegment> m_HatchLines; // hatch lines
std::vector <CPolyPt> m_CornersList; // array of points for corners
std::vector <int> m_SideStyle; // array of styles for sides
std::vector <CSegment> 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<CPolyPt>& 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<CPolyPt>& aPolysListWithHoles,
std::vector<CPolyPt>& aOnePolyList );
#endif // #ifndef POLYLINE_H
/*
* file polygons_defs.h
* definitions to use boost::polygon in KiCad.
*/
#ifndef _POLYGONS_DEFS_H_
#define _POLYGONS_DEFS_H_
#include <boost/polygon/polygon.hpp>
// Define some types used here from boost::polygon
namespace bpl = boost::polygon; // bpl = boost polygon library
using namespace bpl::operators; // +, -, =, ...
// Definitions needed by boost::polygon
typedef int coordinate_type;
/**
* 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<int> 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> 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<int> 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<int> 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> KI_POLYGON_WITH_HOLES_SET;
#endif // #ifndef _POLYGONS_DEFS_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment