More work courtyard overlap detection: better code.

This commit is contained in:
jean-pierre charras 2017-03-20 13:05:38 +01:00
parent 77c1b1b4ea
commit ecdfa404cb
3 changed files with 147 additions and 31 deletions

View File

@ -2874,13 +2874,14 @@ BOARD_ITEM* BOARD::Duplicate( const BOARD_ITEM* aItem,
* All contours should be closed, i.e. are valid vertices for a closed polygon
* return true if success, false if a contour is not valid
*/
#include <specctra.h>
extern bool BuildBoardPolygonOutlines( BOARD* aBoard,
SHAPE_POLY_SET& aOutlines,
SHAPE_POLY_SET& aHoles,
wxString* aErrorText );
bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines,
SHAPE_POLY_SET& aHoles,
wxString* aErrorText )
{
// the SPECCTRA_DB function to extract board outlines:
DSN::SPECCTRA_DB dummy;
return dummy.GetBoardPolygonOutlines( this, aOutlines,
aHoles, aErrorText );
return BuildBoardPolygonOutlines( this, aOutlines, aHoles, aErrorText );
}

View File

@ -1,10 +1,10 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2015 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -1223,7 +1223,7 @@ double MODULE::PadCoverageRatio() const
// see convert_drawsegment_list_to_polygon.cpp:
extern bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
SHAPE_POLY_SET& aPolygons);
SHAPE_POLY_SET& aPolygons, wxString* aErrorText);
bool MODULE::BuildPolyCourtyard()
{
@ -1250,10 +1250,18 @@ bool MODULE::BuildPolyCourtyard()
if( !list_front.size() && !list_back.size() )
return true;
bool success = ConvertOutlineToPolygon( list_front, m_poly_courtyard_front );
wxString error_msg;
bool success = ConvertOutlineToPolygon( list_front, m_poly_courtyard_front, &error_msg );
if( success )
success = ConvertOutlineToPolygon( list_back, m_poly_courtyard_back );
success = ConvertOutlineToPolygon( list_back, m_poly_courtyard_back, &error_msg );
if( !error_msg.IsEmpty() )
{
error_msg.Prepend( GetReference() + ": " );
wxLogMessage( error_msg );
}
return success;
}

View File

@ -175,13 +175,17 @@ static DRAWSEGMENT* findPoint( const wxPoint& aPoint, std::vector< DRAWSEGMENT*
* These closed inner outlines are considered as holes in the main outline
* @param aSegList the initial list of drawsegments (only lines, circles and arcs).
* @param aPolygons will contain the complex polygon.
* @param aErrorText is a wxString to return error message.
*/
bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList, SHAPE_POLY_SET& aPolygons)
bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
SHAPE_POLY_SET& aPolygons, wxString* aErrorText)
{
if( aSegList.size() == 0 )
return true;
wxString msg;
// Make a working copy of aSegList, because the list is modified during calculations
std::vector< DRAWSEGMENT* > segList = aSegList;
@ -367,13 +371,15 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList, SHAPE_POLY_
break;
default:
if( aErrorText )
{
wxLogMessage( _( "Unsupported DRAWSEGMENT type %s" ),
msg.Printf( _( "Unsupported DRAWSEGMENT type %s" ),
GetChars( BOARD_ITEM::ShowShape( graphic->GetShape() ) ) );
return false;
*aErrorText << msg << "\n";
}
break;
return false;
}
// Get next closest segment.
@ -392,12 +398,18 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList, SHAPE_POLY_
}
else
{
wxLogMessage(
_( "Unable to find the next boundary segment with an endpoint of (%s mm, %s mm). "
"graphic outline must form a contiguous, closed polygon." ),
GetChars( FROM_UTF8( BOARD_ITEM::FormatInternalUnits( prevPt.x ).c_str() ) ),
GetChars( FROM_UTF8( BOARD_ITEM::FormatInternalUnits( prevPt.y ).c_str() ) )
);
if( aErrorText )
{
msg.Printf(
_( "Unable to find the next boundary segment with an endpoint of (%s mm, %s mm). "
"graphic outline must form a contiguous, closed polygon." ),
GetChars( FROM_UTF8( BOARD_ITEM::FormatInternalUnits( prevPt.x ).c_str() ) ),
GetChars( FROM_UTF8( BOARD_ITEM::FormatInternalUnits( prevPt.y ).c_str() ) )
);
*aErrorText << msg << "\n";
}
return false;
}
break;
@ -497,7 +509,7 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList, SHAPE_POLY_
wxPoint nextPt;
for( int step = 1; step<=steps; ++step )
for( int step = 1; step <= steps; ++step )
{
double rotation = ( angle * step ) / steps;
@ -512,14 +524,16 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList, SHAPE_POLY_
break;
default:
if( aErrorText )
{
wxLogMessage(
msg.Printf(
_( "Unsupported DRAWSEGMENT type %s" ),
GetChars( BOARD_ITEM::ShowShape( graphic->GetShape() ) ) );
return false;
*aErrorText << msg << "\n";
}
break;
return false;
}
// Get next closest segment.
@ -538,12 +552,17 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList, SHAPE_POLY_
}
else
{
wxLogMessage(
_( "Unable to find the next graphic segment with an endpoint of (%s mm, %s mm).\n"
"Edit graphics, making them contiguous polygons each." ),
GetChars( FROM_UTF8( BOARD_ITEM::FormatInternalUnits( prevPt.x ).c_str() ) ),
GetChars( FROM_UTF8( BOARD_ITEM::FormatInternalUnits( prevPt.y ).c_str() ) )
);
if( aErrorText )
{
msg.Printf(
_( "Unable to find the next graphic segment with an endpoint of (%s mm, %s mm).\n"
"Edit graphics, making them contiguous polygons each." ),
GetChars( FROM_UTF8( BOARD_ITEM::FormatInternalUnits( prevPt.x ).c_str() ) ),
GetChars( FROM_UTF8( BOARD_ITEM::FormatInternalUnits( prevPt.y ).c_str() ) )
);
*aErrorText << msg << "\n";
}
return false;
}
@ -555,3 +574,91 @@ bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList, SHAPE_POLY_
return true;
}
#include <class_board.h>
#include <collectors.h>
/* This function is used to extract a board outlines (3D view, automatic zones build ...)
* Any closed outline inside the main outline is a hole
* All contours should be closed, i.e. valid closed polygon vertices
*/
bool BuildBoardPolygonOutlines( BOARD* aBoard,
SHAPE_POLY_SET& aOutlines,
SHAPE_POLY_SET& aHoles,
wxString* aErrorText )
{
PCB_TYPE_COLLECTOR items;
// Get all the DRAWSEGMENTS and module graphics into 'items',
// then keep only those on layer == Edge_Cuts.
static const KICAD_T scan_graphics[] = { PCB_LINE_T, PCB_MODULE_EDGE_T, EOT };
items.Collect( aBoard, scan_graphics );
// Make a working copy of aSegList, because the list is modified during calculations
std::vector< DRAWSEGMENT* > segList;
for( int ii = 0; ii < items.GetCount(); ii++ )
{
if( items[ii]->GetLayer() == Edge_Cuts )
segList.push_back( static_cast< DRAWSEGMENT* >( items[ii] ) );
}
bool success = ConvertOutlineToPolygon( segList, aOutlines, aErrorText );
// Now move holes in aHoles
// only one main outline is expected
if( success && aOutlines.OutlineCount() )
{
int outlineId = 0;
int holecount = aOutlines.HoleCount( outlineId );
if( holecount )
{
for( int ii = 0; ii < holecount; ++ii )
{
aHoles.AddOutline( aOutlines.Hole( outlineId, ii ) );
}
// Remove holes from aOutlines:
SHAPE_POLY_SET::POLYGON& polygon = aOutlines.Polygon( outlineId );
polygon.erase( polygon.begin()+1, polygon.end() );
}
}
else
{
// Creates a valid polygon outline is not possible.
// So uses the board edge cuts bounding box to create a
// rectangular outline
// (when no edge cuts items, fillBOUNDARY build a contour
// from global bounding box
EDA_RECT bbbox = aBoard->GetBoardEdgesBoundingBox();
// Ensure non null area. If happen, gives a minimal size.
if( ( bbbox.GetWidth() ) == 0 || ( bbbox.GetHeight() == 0 ) )
bbbox.Inflate( Millimeter2iu( 1.0 ) );
aOutlines.RemoveAllContours();
aOutlines.NewOutline();
wxPoint corner;
corner.x = bbbox.GetOrigin().x;
corner.y = bbbox.GetOrigin().y;
aOutlines.Append( corner.x, corner.y );
corner.x = bbbox.GetOrigin().x;
corner.y = bbbox.GetEnd().y;
aOutlines.Append( corner.x, corner.y );
corner.x = bbbox.GetEnd().x;
corner.y = bbbox.GetEnd().y;
aOutlines.Append( corner.x, corner.y );
corner.x = bbbox.GetEnd().x;
corner.y = bbbox.GetOrigin().y;
aOutlines.Append( corner.x, corner.y );
}
return success;
}