141 lines
3.7 KiB
C++
141 lines
3.7 KiB
C++
/*
|
|
* KiRouter - a push-and-(sometimes-)shove PCB router
|
|
*
|
|
* Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
|
*
|
|
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
|
*
|
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "pns_item.h"
|
|
#include "pns_hole.h"
|
|
#include "pns_node.h"
|
|
#include "pns_utils.h"
|
|
|
|
#include <geometry/shape_circle.h>
|
|
#include <geometry/shape_line_chain.h>
|
|
#include <geometry/shape_compound.h>
|
|
#include <geometry/shape_poly_set.h>
|
|
|
|
namespace PNS
|
|
{
|
|
|
|
HOLE::~HOLE()
|
|
{
|
|
delete m_holeShape;
|
|
}
|
|
|
|
|
|
HOLE* HOLE::Clone() const
|
|
{
|
|
HOLE* h = new HOLE( nullptr, m_holeShape->Clone() );
|
|
|
|
h->SetNet( Net() );
|
|
h->SetLayers( Layers() );
|
|
h->SetOwner( nullptr );
|
|
|
|
h->m_rank = m_rank;
|
|
h->m_marker = m_marker;
|
|
h->m_parent = m_parent;
|
|
h->m_isVirtual = m_isVirtual;
|
|
|
|
return h;
|
|
}
|
|
|
|
|
|
const SHAPE_LINE_CHAIN HOLE::Hull( int aClearance, int aWalkaroundThickness, int aLayer ) const
|
|
{
|
|
if( !m_holeShape )
|
|
return SHAPE_LINE_CHAIN();
|
|
|
|
if( m_holeShape->Type() == SH_CIRCLE )
|
|
{
|
|
auto cir = static_cast<SHAPE_CIRCLE*>( m_holeShape );
|
|
int cl = ( aClearance + aWalkaroundThickness / 2 );
|
|
int width = cir->GetRadius() * 2;
|
|
|
|
// Chamfer = width * ( 1 - sqrt(2)/2 ) for equilateral octagon
|
|
return OctagonalHull( cir->GetCenter() - VECTOR2I( width / 2, width / 2 ),
|
|
VECTOR2I( width, width ), cl,
|
|
( 2 * cl + width ) * ( 1.0 - M_SQRT1_2 ) );
|
|
}
|
|
else if( m_holeShape->Type() == SH_COMPOUND )
|
|
{
|
|
SHAPE_COMPOUND* cmpnd = static_cast<SHAPE_COMPOUND*>( m_holeShape );
|
|
|
|
if( cmpnd->Shapes().size() == 1 )
|
|
{
|
|
return BuildHullForPrimitiveShape( cmpnd->Shapes()[0], aClearance,
|
|
aWalkaroundThickness );
|
|
}
|
|
else
|
|
{
|
|
SHAPE_POLY_SET hullSet;
|
|
|
|
for( SHAPE* shape : cmpnd->Shapes() )
|
|
{
|
|
hullSet.AddOutline(
|
|
BuildHullForPrimitiveShape( shape, aClearance, aWalkaroundThickness ) );
|
|
}
|
|
|
|
hullSet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
|
return hullSet.Outline( 0 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return BuildHullForPrimitiveShape( m_holeShape, aClearance, aWalkaroundThickness );
|
|
}
|
|
}
|
|
|
|
|
|
int HOLE::Radius() const
|
|
{
|
|
assert( m_holeShape->Type() == SH_CIRCLE );
|
|
|
|
return static_cast<const SHAPE_CIRCLE*>( m_holeShape )->GetRadius();
|
|
}
|
|
|
|
|
|
void HOLE::SetCenter( const VECTOR2I& aCenter )
|
|
{
|
|
assert( m_holeShape->Type() == SH_CIRCLE );
|
|
static_cast<SHAPE_CIRCLE*>( m_holeShape )->SetCenter( aCenter );
|
|
}
|
|
|
|
|
|
void HOLE::SetRadius( int aRadius )
|
|
{
|
|
assert( m_holeShape->Type() == SH_CIRCLE );
|
|
static_cast<SHAPE_CIRCLE*>( m_holeShape )->SetRadius( aRadius );
|
|
}
|
|
|
|
|
|
void HOLE::Move( const VECTOR2I& delta )
|
|
{
|
|
m_holeShape->Move( delta );
|
|
}
|
|
|
|
|
|
HOLE* HOLE::MakeCircularHole( const VECTOR2I& pos, int radius )
|
|
{
|
|
SHAPE_CIRCLE* circle = new SHAPE_CIRCLE( pos, radius );
|
|
HOLE* hole = new HOLE( nullptr, circle );
|
|
|
|
hole->SetLayers( LAYER_RANGE( F_Cu, B_Cu ) );
|
|
return hole;
|
|
}
|
|
|
|
}; // namespace PNS
|