router: support for board outline
This commit is contained in:
parent
2faf1a1ed3
commit
271363f822
|
@ -353,6 +353,7 @@ set( COMMON_SRCS
|
|||
geometry/seg.cpp
|
||||
geometry/shape.cpp
|
||||
geometry/shape_collisions.cpp
|
||||
geometry/shape_arc.cpp
|
||||
geometry/shape_file_io.cpp
|
||||
geometry/shape_line_chain.cpp
|
||||
geometry/shape_poly_set.cpp
|
||||
|
|
|
@ -785,7 +785,7 @@ void OPENGL_GAL::drawTriangulatedPolyset( const SHAPE_POLY_SET& aPolySet )
|
|||
{
|
||||
auto triPoly = aPolySet.TriangulatedPolygon( j );
|
||||
|
||||
for ( int i = 0; i < triPoly->GetTriangleCount(); i++ )
|
||||
for( int i = 0; i < triPoly->GetTriangleCount(); i++ )
|
||||
{
|
||||
VECTOR2I a, b, c;
|
||||
triPoly->GetTriangle( i ,a,b,c);
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 CERN
|
||||
* @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 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
|
||||
*/
|
||||
|
||||
#include <geometry/shape_arc.h>
|
||||
#include <geometry/shape_line_chain.h>
|
||||
|
||||
bool SHAPE_ARC::Collide( const SEG& aSeg, int aClearance ) const
|
||||
{
|
||||
int minDist = aClearance + m_width / 2;
|
||||
auto centerDist = aSeg.Distance( m_pc );
|
||||
|
||||
if( centerDist < minDist )
|
||||
return true;
|
||||
|
||||
auto ab = (aSeg.B - aSeg.A );
|
||||
auto ac = ( m_pc - aSeg.A );
|
||||
|
||||
auto lenAbSq = ab.SquaredEuclideanNorm();
|
||||
|
||||
auto lambda = (double) ac.Dot( ab ) / (double) lenAbSq;
|
||||
|
||||
|
||||
if( lambda >= 0.0 && lambda <= 1.0 )
|
||||
{
|
||||
VECTOR2I p;
|
||||
|
||||
p.x = (double) aSeg.A.x * lambda + (double) aSeg.B.x * (1.0 - lambda);
|
||||
p.y = (double) aSeg.A.y * lambda + (double) aSeg.B.y * (1.0 - lambda);
|
||||
|
||||
auto p0pdist = ( m_p0 - p ).EuclideanNorm();
|
||||
|
||||
if( p0pdist < minDist )
|
||||
return true;
|
||||
|
||||
auto p1pdist = ( m_p1 - p ).EuclideanNorm();
|
||||
|
||||
if( p1pdist < minDist )
|
||||
return true;
|
||||
}
|
||||
|
||||
auto p0dist = aSeg.Distance( m_p0 );
|
||||
|
||||
if( p0dist > minDist )
|
||||
return true;
|
||||
|
||||
auto p1dist = aSeg.Distance( m_p1 );
|
||||
|
||||
if( p1dist > minDist )
|
||||
return false;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SHAPE_ARC::ConstructFromCorners( VECTOR2I aP0, VECTOR2I aP1, double aCenterAngle )
|
||||
{
|
||||
VECTOR2D mid = ( VECTOR2D( aP0 ) + VECTOR2D( aP1 ) ) * 0.5;
|
||||
VECTOR2D chord = VECTOR2D( aP1 ) - VECTOR2D( aP0 );
|
||||
double c = (aP1 - aP0).EuclideanNorm() / 2;
|
||||
VECTOR2D d = chord.Rotate( M_PI / 2.0 ).Resize( c );
|
||||
|
||||
m_pc = mid + d * ( 1.0 / tan( aCenterAngle / 2.0 * M_PI / 180.0 ) );
|
||||
m_p0 = aP0;
|
||||
m_p1 = aP1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SHAPE_ARC::ConstructFromCornerAndAngles( VECTOR2I aP0,
|
||||
double aStartAngle,
|
||||
double aCenterAngle,
|
||||
double aRadius )
|
||||
{
|
||||
m_p0 = aP0;
|
||||
auto d1 = VECTOR2D( 1.0, 0.0 ).Rotate( aStartAngle * M_PI / 180.0 ) * aRadius;
|
||||
auto d2 =
|
||||
VECTOR2D( 1.0, 0.0 ).Rotate( (aStartAngle + aCenterAngle) * M_PI / 180.0 ) * aRadius;
|
||||
|
||||
m_pc = m_p0 - (VECTOR2I) d1;
|
||||
m_p1 = m_pc + (VECTOR2I) d2;
|
||||
|
||||
if( aCenterAngle < 0 )
|
||||
std::swap( m_p0, m_p1 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SHAPE_ARC::Collide( const VECTOR2I& aP, int aClearance ) const
|
||||
{
|
||||
assert( false );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
double SHAPE_ARC::GetStartAngle() const
|
||||
{
|
||||
VECTOR2D d( m_p0 - m_pc );
|
||||
|
||||
return 180.0 / M_PI * atan2( d.y, d.x );
|
||||
}
|
||||
|
||||
|
||||
double SHAPE_ARC::GetEndAngle() const
|
||||
{
|
||||
VECTOR2D d( m_p1 - m_pc );
|
||||
|
||||
return 180.0 / M_PI * atan2( d.y, d.x );
|
||||
}
|
||||
|
||||
|
||||
double SHAPE_ARC::GetCentralAngle() const
|
||||
{
|
||||
auto ea = GetEndAngle();
|
||||
auto sa = GetStartAngle();
|
||||
|
||||
if( ea < sa )
|
||||
ea += 360.0;
|
||||
|
||||
while( sa < 0.0 )
|
||||
{
|
||||
sa += 360.0;
|
||||
ea += 360.0;
|
||||
}
|
||||
|
||||
return ea - sa;
|
||||
}
|
||||
|
||||
const SHAPE_LINE_CHAIN SHAPE_ARC::ConvertToPolyline( double aAccuracy ) const
|
||||
{
|
||||
SHAPE_LINE_CHAIN rv;
|
||||
double ca = GetCentralAngle();
|
||||
double r = GetRadius();
|
||||
double step;
|
||||
auto c = GetCenter();
|
||||
int n;
|
||||
|
||||
if( r == 0.0 )
|
||||
{
|
||||
ca = 0;
|
||||
n = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
step = 180 / M_PI * acos( r * ( 1 - aAccuracy ) / r );
|
||||
n = (int) ceil(ca / step);
|
||||
}
|
||||
|
||||
for( int i = 0; i <= n ; i++ )
|
||||
{
|
||||
double a = GetStartAngle() + ca * (double) i / (double) n;
|
||||
double x = c.x + r * cos( a * M_PI / 180.0 );
|
||||
double y = c.y + r * sin( a * M_PI / 180.0 );
|
||||
|
||||
rv.Append( (int) x, (int) y );
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
|
@ -25,6 +25,9 @@
|
|||
#include <geometry/seg.h>
|
||||
#include <geometry/shape_line_chain.h>
|
||||
|
||||
// believe or not, X11 headers have a F****ING macro called Opposite...
|
||||
#undef Opposite
|
||||
|
||||
/**
|
||||
* Class DIRECTION_45.
|
||||
* Represents route directions & corner angles in a 45-degree metric.
|
||||
|
|
|
@ -45,8 +45,9 @@ enum SHAPE_TYPE
|
|||
SH_LINE_CHAIN, ///> line chain (polyline)
|
||||
SH_CIRCLE, ///> circle
|
||||
SH_CONVEX, ///> convex polygon
|
||||
SH_POLY_SET, ///> any polygon (with holes, etc.)
|
||||
SH_COMPOUND ///> compound shape, consisting of multiple simple shapes
|
||||
SH_POLY_SET, ///> set of polygons (with holes, etc.)
|
||||
SH_COMPOUND, ///> compound shape, consisting of multiple simple shapes
|
||||
SH_ARC ///> circular arc
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 CERN
|
||||
* @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 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
|
||||
*/
|
||||
|
||||
#ifndef __SHAPE_ARC_H
|
||||
#define __SHAPE_ARC_H
|
||||
|
||||
#include <geometry/shape.h>
|
||||
#include <geometry/seg.h>
|
||||
|
||||
class SHAPE_LINE_CHAIN;
|
||||
|
||||
class SHAPE_ARC : public SHAPE
|
||||
{
|
||||
public:
|
||||
SHAPE_ARC() :
|
||||
SHAPE( SH_ARC ), m_width( 0 ) {};
|
||||
|
||||
SHAPE_ARC( const VECTOR2I& pa, const VECTOR2I& pb, const VECTOR2I& pCenter, int aWidth = 0 ) :
|
||||
SHAPE( SH_ARC ), m_p0( pa ), m_p1( pb ), m_pc( pCenter ), m_width( aWidth ) {};
|
||||
|
||||
SHAPE_ARC( const SHAPE_ARC& aOther )
|
||||
: SHAPE( SH_ARC )
|
||||
{
|
||||
m_p0 = aOther.m_p0;
|
||||
m_p1 = aOther.m_p1;
|
||||
m_pc = aOther.m_pc;
|
||||
}
|
||||
|
||||
~SHAPE_ARC() {};
|
||||
|
||||
SHAPE* Clone() const override
|
||||
{
|
||||
return new SHAPE_ARC( *this );
|
||||
}
|
||||
|
||||
const VECTOR2I& GetP0() const { return m_p0; }
|
||||
const VECTOR2I& GetP1() const { return m_p1; }
|
||||
const VECTOR2I& GetCenter() const { return m_pc; }
|
||||
|
||||
const BOX2I BBox( int aClearance = 0 ) const override
|
||||
{
|
||||
assert( false );
|
||||
return BOX2I(); // fixme
|
||||
}
|
||||
|
||||
bool Collide( const SEG& aSeg, int aClearance = 0 ) const override;
|
||||
bool Collide( const VECTOR2I& aP, int aClearance = 0 ) const override;
|
||||
|
||||
void SetWidth( int aWidth )
|
||||
{
|
||||
m_width = aWidth;
|
||||
}
|
||||
|
||||
int GetWidth() const
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
bool IsSolid() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Move( const VECTOR2I& aVector ) override
|
||||
{
|
||||
m_p0 += aVector;
|
||||
m_p1 += aVector;
|
||||
m_pc += aVector;
|
||||
}
|
||||
|
||||
int GetRadius() const
|
||||
{
|
||||
return (m_pc - m_p0).EuclideanNorm();
|
||||
}
|
||||
|
||||
SEG GetChord() const
|
||||
{
|
||||
return SEG( m_p0, m_p1 );
|
||||
}
|
||||
|
||||
double GetCentralAngle() const;
|
||||
double GetStartAngle() const;
|
||||
double GetEndAngle() const;
|
||||
|
||||
|
||||
bool ConstructFromCorners( VECTOR2I aP0, VECTOR2I aP1, double aCenterAngle );
|
||||
|
||||
|
||||
bool ConstructFromCornerAndAngles( VECTOR2I aP0,
|
||||
double aStartAngle,
|
||||
double aCenterAngle,
|
||||
double aRadius );
|
||||
|
||||
const SHAPE_LINE_CHAIN ConvertToPolyline( double aAccuracy = 0.02f ) const;
|
||||
|
||||
private:
|
||||
|
||||
bool ccw( const VECTOR2I& aA, const VECTOR2I& aB, const VECTOR2I& aC ) const
|
||||
{
|
||||
return (ecoord) ( aC.y - aA.y ) * ( aB.x - aA.x ) >
|
||||
(ecoord) ( aB.y - aA.y ) * ( aC.x - aA.x );
|
||||
}
|
||||
|
||||
VECTOR2I m_p0, m_p1, m_pc;
|
||||
int m_width;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -46,6 +46,7 @@
|
|||
#include <geometry/shape_rect.h>
|
||||
#include <geometry/shape_circle.h>
|
||||
#include <geometry/shape_convex.h>
|
||||
#include <geometry/shape_arc.h>
|
||||
#include <geometry/convex_hull.h>
|
||||
|
||||
#include "tools/pcb_tool.h"
|
||||
|
@ -802,12 +803,12 @@ bool PNS_KICAD_IFACE::syncZone( PNS::NODE* aWorld, ZONE_CONTAINER* aZone )
|
|||
|
||||
LSET layers = aZone->GetLayerSet();
|
||||
|
||||
for ( int layer = F_Cu; layer <= B_Cu; layer++ )
|
||||
for( int layer = F_Cu; layer <= B_Cu; layer++ )
|
||||
{
|
||||
if ( ! layers[layer] )
|
||||
continue;
|
||||
|
||||
for ( int outline = 0; outline < poly.OutlineCount(); outline++ )
|
||||
for( int outline = 0; outline < poly.OutlineCount(); outline++ )
|
||||
{
|
||||
auto tri = poly.TriangulatedPolygon( outline );
|
||||
|
||||
|
@ -837,9 +838,59 @@ bool PNS_KICAD_IFACE::syncZone( PNS::NODE* aWorld, ZONE_CONTAINER* aZone )
|
|||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<PNS::SOLID> PNS_KICAD_IFACE::syncGraphicalItem( DRAWSEGMENT* aItem )
|
||||
bool PNS_KICAD_IFACE::syncGraphicalItem( PNS::NODE* aWorld, DRAWSEGMENT* aItem )
|
||||
{
|
||||
return nullptr;
|
||||
std::vector<SHAPE_SEGMENT*> segs;
|
||||
|
||||
|
||||
if( aItem->GetLayer() != Edge_Cuts )
|
||||
return false;
|
||||
|
||||
switch( aItem->GetShape() )
|
||||
{
|
||||
case S_ARC:
|
||||
{
|
||||
SHAPE_ARC arc( aItem->GetArcStart(), aItem->GetArcEnd(), aItem->GetCenter() );
|
||||
auto l = arc.ConvertToPolyline();
|
||||
|
||||
for( int i = 0; i < l.SegmentCount(); i++ )
|
||||
{
|
||||
SHAPE_SEGMENT *seg = new SHAPE_SEGMENT( l.CSegment(i), aItem->GetWidth() );
|
||||
segs.push_back( seg );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case S_SEGMENT:
|
||||
{
|
||||
SHAPE_SEGMENT *seg = new SHAPE_SEGMENT( aItem->GetStart(), aItem->GetEnd(), aItem->GetWidth() );
|
||||
segs.push_back( seg );
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for( auto seg : segs )
|
||||
{
|
||||
for( int layer = F_Cu; layer <= B_Cu; layer++ )
|
||||
{
|
||||
std::unique_ptr< PNS::SOLID > solid( new PNS::SOLID );
|
||||
|
||||
solid->SetLayer( layer );
|
||||
solid->SetNet( -1 );
|
||||
solid->SetParent( nullptr );
|
||||
solid->SetShape( seg->Clone() );
|
||||
solid->SetRoutable( false );
|
||||
|
||||
aWorld->Add( std::move( solid ) );
|
||||
}
|
||||
|
||||
delete seg;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PNS_KICAD_IFACE::SetBoard( BOARD* aBoard )
|
||||
|
@ -861,10 +912,7 @@ void PNS_KICAD_IFACE::SyncWorld( PNS::NODE *aWorld )
|
|||
|
||||
for( auto gitem : m_board->Drawings() )
|
||||
{
|
||||
auto solid = syncGraphicalItem( static_cast<DRAWSEGMENT*>( gitem ) );
|
||||
|
||||
if ( solid )
|
||||
aWorld->Add( std::move( solid ) );
|
||||
syncGraphicalItem( aWorld, static_cast<DRAWSEGMENT*>( gitem ) );
|
||||
}
|
||||
|
||||
for( auto zone : m_board->Zones() )
|
||||
|
|
|
@ -70,7 +70,7 @@ private:
|
|||
std::unique_ptr<PNS::SOLID> syncPad( D_PAD* aPad );
|
||||
std::unique_ptr<PNS::SEGMENT> syncTrack( TRACK* aTrack );
|
||||
std::unique_ptr<PNS::VIA> syncVia( VIA* aVia );
|
||||
std::unique_ptr<PNS::SOLID> syncGraphicalItem( DRAWSEGMENT* aItem );
|
||||
bool syncGraphicalItem( PNS::NODE* aWorld, DRAWSEGMENT* aItem );
|
||||
bool syncZone( PNS::NODE* aWorld, ZONE_CONTAINER* aZone );
|
||||
|
||||
KIGFX::VIEW* m_view;
|
||||
|
|
|
@ -172,7 +172,7 @@ bool ROUTER::StartRouting( const VECTOR2I& aP, ITEM* aStartItem, int aLayer )
|
|||
|
||||
if( ! isStartingPointRoutable( aP, aLayer ) )
|
||||
{
|
||||
SetFailureReason( _("Cannot start routing inside a keepout area." ) );
|
||||
SetFailureReason( _("Cannot start routing inside a keepout area or board outline." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue