2016-07-19 17:35:25 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
|
|
|
* Copyright (C) 1992-2016 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
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, you may find one here:
|
|
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @file create_layer_poly.cpp
|
|
|
|
* @brief This file implements the creation of the pcb board items in the poly
|
|
|
|
* contours format. It is based on the function found in the files:
|
|
|
|
* board_items_to_polygon_shape_transform.cpp
|
|
|
|
* board_items_to_polygon_shape_transform.cpp
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "cinfo3d_visu.h"
|
|
|
|
#include <convert_basic_shapes_to_polygon.h>
|
|
|
|
#include <class_edge_mod.h>
|
|
|
|
#include <class_module.h>
|
|
|
|
|
|
|
|
|
|
|
|
// This is the same function as in board_items_to_polygon_shape_transform.cpp
|
|
|
|
// but it adds the rect/trapezoid shapes with a different winding
|
|
|
|
void CINFO3D_VISU::buildPadShapePolygon( const D_PAD* aPad,
|
|
|
|
SHAPE_POLY_SET& aCornerBuffer,
|
|
|
|
wxSize aInflateValue,
|
|
|
|
int aSegmentsPerCircle,
|
|
|
|
double aCorrectionFactor ) const
|
|
|
|
{
|
|
|
|
wxPoint corners[4];
|
|
|
|
wxPoint PadShapePos = aPad->ShapePos(); /* Note: for pad having a shape offset,
|
|
|
|
* the pad position is NOT the shape position */
|
|
|
|
switch( aPad->GetShape() )
|
|
|
|
{
|
|
|
|
case PAD_SHAPE_CIRCLE:
|
|
|
|
case PAD_SHAPE_OVAL:
|
|
|
|
case PAD_SHAPE_ROUNDRECT:
|
2018-08-29 07:13:07 +00:00
|
|
|
case PAD_SHAPE_CHAMFERED_RECT:
|
2018-04-28 18:31:50 +00:00
|
|
|
{
|
|
|
|
// We are using TransformShapeWithClearanceToPolygon to build the shape.
|
|
|
|
// Currently, this method uses only the same inflate value for X and Y dirs.
|
|
|
|
// so because here this is not the case, we use a inflated dummy pad to build
|
|
|
|
// the polygonal shape
|
|
|
|
// TODO: remove this dummy pad when TransformShapeWithClearanceToPolygon will use
|
|
|
|
// a wxSize to inflate the pad size
|
|
|
|
D_PAD dummy( *aPad );
|
|
|
|
wxSize new_size = aPad->GetSize() + aInflateValue + aInflateValue;
|
|
|
|
dummy.SetSize( new_size );
|
|
|
|
dummy.TransformShapeWithClearanceToPolygon( aCornerBuffer, 0,
|
2016-07-19 17:35:25 +00:00
|
|
|
aSegmentsPerCircle, aCorrectionFactor );
|
2018-04-28 18:31:50 +00:00
|
|
|
}
|
2016-07-19 17:35:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PAD_SHAPE_TRAPEZOID:
|
|
|
|
case PAD_SHAPE_RECT:
|
|
|
|
{
|
|
|
|
SHAPE_LINE_CHAIN aLineChain;
|
|
|
|
|
|
|
|
aPad->BuildPadPolygon( corners, aInflateValue, aPad->GetOrientation() );
|
|
|
|
|
|
|
|
for( int ii = 0; ii < 4; ++ii )
|
|
|
|
{
|
|
|
|
corners[3-ii] += PadShapePos; // Shift origin to position
|
|
|
|
aLineChain.Append( corners[3-ii].x, corners[3-ii].y );
|
|
|
|
}
|
|
|
|
|
|
|
|
aLineChain.SetClosed( true );
|
|
|
|
|
|
|
|
aCornerBuffer.AddOutline( aLineChain );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2017-01-13 17:51:22 +00:00
|
|
|
case PAD_SHAPE_CUSTOM:
|
|
|
|
{
|
|
|
|
SHAPE_POLY_SET polyList; // Will contain the pad outlines in board coordinates
|
|
|
|
polyList.Append( aPad->GetCustomShapeAsPolygon() );
|
2017-09-20 08:28:52 +00:00
|
|
|
aPad->CustomShapeAsPolygonToBoardPosition( &polyList, aPad->ShapePos(), aPad->GetOrientation() );
|
2017-01-13 17:51:22 +00:00
|
|
|
aCornerBuffer.Append( polyList );
|
|
|
|
}
|
2016-07-19 17:35:25 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CINFO3D_VISU::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
|
|
|
|
SHAPE_POLY_SET& aCornerBuffer,
|
|
|
|
int aWidth ) const
|
|
|
|
{
|
|
|
|
if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) // Draw a ring
|
|
|
|
{
|
|
|
|
unsigned int nr_sides_per_circle = GetNrSegmentsCircle( ( aPad->GetSize().x / 2 +
|
|
|
|
aWidth / 2 ) * 2 );
|
|
|
|
|
|
|
|
TransformRingToPolygon( aCornerBuffer, aPad->ShapePos(),
|
|
|
|
aPad->GetSize().x / 2, nr_sides_per_circle, aWidth );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-01-13 17:51:22 +00:00
|
|
|
|
2016-07-19 17:35:25 +00:00
|
|
|
// For other shapes, draw polygon outlines
|
|
|
|
SHAPE_POLY_SET corners;
|
|
|
|
|
|
|
|
unsigned int nr_sides_per_circle = GetNrSegmentsCircle( glm::min( aPad->GetSize().x,
|
|
|
|
aPad->GetSize().y) );
|
|
|
|
buildPadShapePolygon( aPad, corners, wxSize( 0, 0 ),
|
2017-01-13 17:51:22 +00:00
|
|
|
nr_sides_per_circle,
|
|
|
|
GetCircleCorrectionFactor( nr_sides_per_circle ) );
|
2016-07-19 17:35:25 +00:00
|
|
|
|
|
|
|
// Add outlines as thick segments in polygon buffer
|
|
|
|
|
|
|
|
const SHAPE_LINE_CHAIN& path = corners.COutline( 0 );
|
|
|
|
|
|
|
|
for( int ii = 0; ii < path.PointCount(); ++ii )
|
|
|
|
{
|
|
|
|
const VECTOR2I& a = path.CPoint( ii );
|
|
|
|
const VECTOR2I& b = path.CPoint( ii + 1 );
|
|
|
|
|
|
|
|
TransformRoundedEndsSegmentToPolygon( aCornerBuffer,
|
|
|
|
wxPoint( a.x, a.y ),
|
|
|
|
wxPoint( b.x, b.y ),
|
|
|
|
nr_sides_per_circle,
|
|
|
|
aWidth );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Based on the same function name in board_items_to_polyshape_transform.cpp
|
|
|
|
// It was implemented here to allow dynamic segments count per pad shape
|
2017-03-13 03:19:33 +00:00
|
|
|
void CINFO3D_VISU::transformPadsShapesWithClearanceToPolygon( const DLIST<D_PAD>& aPads, PCB_LAYER_ID aLayer,
|
2016-07-19 17:35:25 +00:00
|
|
|
SHAPE_POLY_SET& aCornerBuffer,
|
|
|
|
int aInflateValue,
|
|
|
|
bool aSkipNPTHPadsWihNoCopper ) const
|
|
|
|
{
|
|
|
|
const D_PAD* pad = aPads;
|
|
|
|
|
|
|
|
wxSize margin;
|
|
|
|
for( ; pad != NULL; pad = pad->Next() )
|
|
|
|
{
|
|
|
|
if( !pad->IsOnLayer(aLayer) )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// NPTH pads are not drawn on layers if the shape size and pos is the same
|
|
|
|
// as their hole:
|
|
|
|
if( aSkipNPTHPadsWihNoCopper && (pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED) )
|
|
|
|
{
|
|
|
|
if( (pad->GetDrillSize() == pad->GetSize()) &&
|
|
|
|
(pad->GetOffset() == wxPoint( 0, 0 )) )
|
|
|
|
{
|
|
|
|
switch( pad->GetShape() )
|
|
|
|
{
|
|
|
|
case PAD_SHAPE_CIRCLE:
|
|
|
|
if( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PAD_SHAPE_OVAL:
|
|
|
|
if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE )
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch( aLayer )
|
|
|
|
{
|
|
|
|
case F_Mask:
|
|
|
|
case B_Mask:
|
|
|
|
margin.x = margin.y = pad->GetSolderMaskMargin() + aInflateValue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case F_Paste:
|
|
|
|
case B_Paste:
|
|
|
|
margin = pad->GetSolderPasteMargin();
|
|
|
|
margin.x += aInflateValue;
|
|
|
|
margin.y += aInflateValue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
margin.x = margin.y = aInflateValue;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int aCircleToSegmentsCount = GetNrSegmentsCircle( pad->GetSize().x );
|
|
|
|
double aCorrectionFactor = GetCircleCorrectionFactor( aCircleToSegmentsCount );
|
|
|
|
|
|
|
|
buildPadShapePolygon( pad, aCornerBuffer, margin,
|
|
|
|
aCircleToSegmentsCount, aCorrectionFactor );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CINFO3D_VISU::transformGraphicModuleEdgeToPolygonSet( const MODULE *aModule,
|
2017-03-13 03:19:33 +00:00
|
|
|
PCB_LAYER_ID aLayer,
|
2016-07-19 17:35:25 +00:00
|
|
|
SHAPE_POLY_SET& aCornerBuffer ) const
|
|
|
|
{
|
2017-04-25 09:06:24 +00:00
|
|
|
for( const EDA_ITEM* item = aModule->GraphicalItemsList();
|
2016-07-19 17:35:25 +00:00
|
|
|
item != NULL;
|
|
|
|
item = item->Next() )
|
|
|
|
{
|
|
|
|
switch( item->Type() )
|
|
|
|
{
|
|
|
|
case PCB_MODULE_EDGE_T:
|
|
|
|
{
|
|
|
|
EDGE_MODULE*outline = (EDGE_MODULE*) item;
|
|
|
|
|
|
|
|
if( outline->GetLayer() != aLayer )
|
|
|
|
break;
|
|
|
|
|
|
|
|
unsigned int aCircleToSegmentsCount =
|
|
|
|
GetNrSegmentsCircle( outline->GetBoundingBox().GetSizeMax() );
|
|
|
|
|
|
|
|
double aCorrectionFactor = GetCircleCorrectionFactor( aCircleToSegmentsCount );
|
|
|
|
|
|
|
|
outline->TransformShapeWithClearanceToPolygon( aCornerBuffer,
|
|
|
|
0,
|
|
|
|
aCircleToSegmentsCount,
|
|
|
|
aCorrectionFactor );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|