Separate creation of polygons for open and closed shapes.

This allows us to create a bounding hull from an open shape-line-chain,
which is useful for defining milled slots.
This commit is contained in:
Jeff Young 2022-11-27 18:29:41 +00:00
parent 740e193871
commit ec9c6a8053
5 changed files with 96 additions and 20 deletions

View File

@ -138,6 +138,38 @@ double EDA_SHAPE::GetLength() const
}
bool EDA_SHAPE::IsClosed() const
{
switch( m_shape )
{
case SHAPE_T::CIRCLE:
case SHAPE_T::RECT:
return true;
case SHAPE_T::ARC:
case SHAPE_T::SEGMENT:
return false;
case SHAPE_T::POLY:
if( m_poly.IsEmpty() )
return false;
else
return m_poly.Outline( 0 ).IsClosed();
case SHAPE_T::BEZIER:
if( m_bezierPoints.size() < 3 )
return false;
else
return m_bezierPoints[0] == m_bezierPoints[ m_bezierPoints.size() - 1 ];
default:
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
return false;
}
}
void EDA_SHAPE::move( const VECTOR2I& aMoveVector )
{
switch ( m_shape )

View File

@ -100,6 +100,8 @@ public:
void SetFillMode( FILL_T aFill ) { m_fill = aFill; }
FILL_T GetFillMode() const { return m_fill; }
bool IsClosed() const;
COLOR4D GetFillColor() const { return m_fillColor; }
void SetFillColor( const COLOR4D& aColor ) { m_fillColor = aColor; }

View File

@ -34,6 +34,7 @@ namespace PNS
// Settings for the CONVERT_TOOL.
struct CONVERT_SETTINGS
{
bool m_StrokeHulls;
bool m_IgnoreLineWidths;
bool m_DeleteOriginals;
};

View File

@ -45,6 +45,7 @@
#include <tools/pcb_actions.h>
#include <tools/pcb_selection_tool.h>
#include <trigo.h>
#include <macros.h>
#include <zone.h>
#include "convert_tool.h"
@ -203,7 +204,6 @@ int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent )
PCB_LAYER_ID destLayer = m_frame->GetActiveLayer();
FOOTPRINT* parentFootprint = nullptr;
bool foundChainedSegs = false;
bool foundFilledShape = false;
PCB_SELECTION& selection = m_selectionTool->RequestSelection(
[]( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
@ -219,23 +219,28 @@ int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent )
polys.clear();
for( EDA_ITEM* item : selection )
{
item->ClearTempFlags();
if( item->Type() == PCB_SHAPE_T || item->Type() == PCB_FP_SHAPE_T )
foundFilledShape = static_cast<PCB_SHAPE*>( item )->IsFilled();
}
SHAPE_POLY_SET polySet;
SHAPE_POLY_SET temp;
if( convertSettings.m_IgnoreLineWidths )
polySet.Append( makePolysFromClosedGraphics( selection.GetItems(),
convertSettings.m_IgnoreLineWidths ) );
temp = makePolysFromChainedSegs( selection.GetItems() );
if( !temp.IsEmpty() )
{
polySet.Append( makePolysFromChainedSegs( selection.GetItems() ) );
foundChainedSegs = polySet.OutlineCount() > 0;
polySet.Append( temp );
foundChainedSegs = true;
}
else
{
for( EDA_ITEM* item : selection )
item->ClearTempFlags();
}
polySet.Append( makePolysFromGraphics( selection.GetItems(),
convertSettings.m_IgnoreLineWidths ) );
polySet.Append( makePolysFromOpenGraphics( selection.GetItems() ) );
if( polySet.IsEmpty() )
return false;
@ -257,8 +262,8 @@ int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent )
// to true.
// We also use the pre-flight to keep from putting up any of the dialogs if there's nothing
// to convert.
convertSettings.m_IgnoreLineWidths = true;
convertSettings.m_DeleteOriginals = false;
convertSettings.m_IgnoreLineWidths = false;
convertSettings.m_DeleteOriginals = true;
if( !getPolys() )
return 0;
@ -294,7 +299,6 @@ int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent )
PCB_SHAPE* graphic = isFootprint ? new FP_SHAPE( parentFootprint ) : new PCB_SHAPE;
graphic->SetShape( SHAPE_T::POLY );
graphic->SetFilled( !convertSettings.m_IgnoreLineWidths || foundFilledShape );
graphic->SetStroke( STROKE_PARAMS( 0, PLOT_DASH_TYPE::SOLID, COLOR4D::UNSPECIFIED ) );
graphic->SetLayer( destLayer );
graphic->SetPolyShape( poly );
@ -572,7 +576,42 @@ SHAPE_POLY_SET CONVERT_TOOL::makePolysFromChainedSegs( const std::deque<EDA_ITEM
}
SHAPE_POLY_SET CONVERT_TOOL::makePolysFromGraphics( const std::deque<EDA_ITEM*>& aItems,
SHAPE_POLY_SET CONVERT_TOOL::makePolysFromOpenGraphics( const std::deque<EDA_ITEM*>& aItems )
{
BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings();
SHAPE_POLY_SET poly;
for( EDA_ITEM* item : aItems )
{
if( item->GetFlags() & SKIP_STRUCT )
continue;
switch( item->Type() )
{
case PCB_SHAPE_T:
case PCB_FP_SHAPE_T:
{
PCB_SHAPE* temp = static_cast<PCB_SHAPE*>( item->Clone() );
if( temp->IsClosed() )
continue;
temp->TransformShapeToPolygon( poly, UNDEFINED_LAYER, 0, bds.m_MaxError, ERROR_INSIDE,
false );
item->SetFlags( SKIP_STRUCT );
break;
}
default:
continue;
}
}
return poly;
}
SHAPE_POLY_SET CONVERT_TOOL::makePolysFromClosedGraphics( const std::deque<EDA_ITEM*>& aItems,
bool aIgnoreLineWidths )
{
BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings();
@ -590,9 +629,10 @@ SHAPE_POLY_SET CONVERT_TOOL::makePolysFromGraphics( const std::deque<EDA_ITEM*>&
{
PCB_SHAPE* temp = static_cast<PCB_SHAPE*>( item->Clone() );
if( aIgnoreLineWidths )
temp->SetFilled( true );
if( !temp->IsClosed() )
continue;
temp->SetFilled( true );
temp->TransformShapeToPolygon( poly, UNDEFINED_LAYER, 0, bds.m_MaxError, ERROR_INSIDE,
aIgnoreLineWidths );
item->SetFlags( SKIP_STRUCT );

View File

@ -90,7 +90,8 @@ private:
* @param aItems is a list of items to process.
* @return a #SHAPE_POLY_SET containing any polygons that were created.
*/
SHAPE_POLY_SET makePolysFromGraphics( const std::deque<EDA_ITEM*>& aItems,
SHAPE_POLY_SET makePolysFromOpenGraphics( const std::deque<EDA_ITEM*>& aItems );
SHAPE_POLY_SET makePolysFromClosedGraphics( const std::deque<EDA_ITEM*>& aItems,
bool aIgnoreLineWidths );
PCB_SELECTION_TOOL* m_selectionTool;