mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-18 21:29:17 +00:00
pcbnew: Adding arcs to PNS
This is allows ARCs in tracks to be synchronized with the PNS router. Note this does not yet include the UI components to route curved traces
This commit is contained in:
parent
3af868e3d1
commit
8c19b4b6ae
include
libs/kimath
pcbnew
board_commit.cppboard_connected_item.hboard_design_settings.cppclass_board.cppclass_board.hclass_module.cppclass_track.cppclass_track.hcollectors.cpp
connectivity
dialogs
dialog_global_edit_tracks_and_vias.cppdialog_select_net_from_list.cppdialog_track_via_properties.cpp
exporters
kicad_plugin.cppkicad_plugin.hpcb_painter.cpppcb_painter.hpcb_parser.cpprouter
CMakeLists.txtpns_arc.cpppns_arc.hpns_diff_pair.cpppns_diff_pair.hpns_diff_pair_placer.cpppns_dragger.cpppns_dragger.hpns_index.cpppns_item.cpppns_item.hpns_joint.hpns_kicad_iface.cpppns_kicad_iface.hpns_line.cpppns_line.hpns_line_placer.cpppns_linked_item.hpns_node.cpppns_node.hpns_optimizer.cpppns_router.cpppns_router.hpns_routing_settings.cpppns_routing_settings.hpns_segment.hpns_shove.cpppns_shove.hpns_tool_base.cpppns_topology.cpppns_utils.cpppns_utils.hrouter_preview_item.cpprouter_tool.cpp
swig
tools
undo_redo.cppzone_filler.cppqa/common
@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2009-2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2020 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
|
||||
@ -26,7 +26,6 @@
|
||||
#define BOARD_DESIGN_SETTINGS_H_
|
||||
|
||||
#include <class_pad.h>
|
||||
#include <class_track.h>
|
||||
#include <netclass.h>
|
||||
#include <config_params.h>
|
||||
#include <board_stackup_manager/class_board_stackup.h>
|
||||
@ -167,6 +166,8 @@ enum
|
||||
LAYER_CLASS_COUNT
|
||||
};
|
||||
|
||||
// forward declaration from class_track.h
|
||||
enum class VIATYPE : int;
|
||||
|
||||
/**
|
||||
* BOARD_DESIGN_SETTINGS
|
||||
|
@ -5,6 +5,7 @@ set( KIMATH_SRCS
|
||||
src/trigo.cpp
|
||||
|
||||
src/geometry/convex_hull.cpp
|
||||
src/geometry/direction_45.cpp
|
||||
src/geometry/geometry_utils.cpp
|
||||
src/geometry/polygon_test_point_inside.cpp
|
||||
src/geometry/seg.cpp
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2013-2015 CERN
|
||||
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
* Copyright (C) 2017 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2017-2019 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
|
||||
@ -43,7 +43,7 @@ public:
|
||||
* Represents available directions - there are 8 of them, as on a rectilinear map (north = up) +
|
||||
* an extra undefined direction, reserved for traces that don't respect 45-degree routing regime.
|
||||
*/
|
||||
enum Directions
|
||||
enum Directions : int
|
||||
{
|
||||
N = 0,
|
||||
NE = 1,
|
||||
@ -53,6 +53,7 @@ public:
|
||||
SW = 5,
|
||||
W = 6,
|
||||
NW = 7,
|
||||
LAST = 8,
|
||||
UNDEFINED = -1
|
||||
};
|
||||
|
||||
@ -70,13 +71,14 @@ public:
|
||||
ANG_UNDEFINED = 0x20
|
||||
};
|
||||
|
||||
DIRECTION_45( Directions aDir = UNDEFINED ) : m_dir( aDir ) {}
|
||||
DIRECTION_45( Directions aDir = UNDEFINED ) : m_dir( aDir ), m_90deg( false ) {}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param aVec vector, whose direction will be translated into a DIRECTION_45.
|
||||
*/
|
||||
DIRECTION_45( const VECTOR2I& aVec )
|
||||
DIRECTION_45( const VECTOR2I &aVec, bool a90 = false ) :
|
||||
m_90deg( a90 )
|
||||
{
|
||||
construct_( aVec );
|
||||
}
|
||||
@ -85,7 +87,8 @@ public:
|
||||
* Constructor
|
||||
* @param aSeg segment, whose direction will be translated into a DIRECTION_45.
|
||||
*/
|
||||
DIRECTION_45( const SEG& aSeg )
|
||||
DIRECTION_45( const SEG& aSeg, bool a90 = false ) :
|
||||
m_90deg( a90 )
|
||||
{
|
||||
construct_( aSeg.B - aSeg.A );
|
||||
}
|
||||
@ -198,51 +201,13 @@ public:
|
||||
* @param aP0 starting point
|
||||
* @param aP1 ending point
|
||||
* @param aStartDiagonal whether the first segment has to be diagonal
|
||||
* @param aRadius is the radius of curvature for rounding. If =0, do not insert arcs
|
||||
* @return the trace
|
||||
*/
|
||||
const SHAPE_LINE_CHAIN BuildInitialTrace( const VECTOR2I& aP0,
|
||||
const VECTOR2I& aP1,
|
||||
bool aStartDiagonal = false ) const
|
||||
{
|
||||
int w = abs( aP1.x - aP0.x );
|
||||
int h = abs( aP1.y - aP0.y );
|
||||
int sw = sign( aP1.x - aP0.x );
|
||||
int sh = sign( aP1.y - aP0.y );
|
||||
|
||||
VECTOR2I mp0, mp1;
|
||||
|
||||
// we are more horizontal than vertical?
|
||||
if( w > h )
|
||||
{
|
||||
mp0 = VECTOR2I( ( w - h ) * sw, 0 ); // direction: E
|
||||
mp1 = VECTOR2I( h * sw, h * sh ); // direction: NE
|
||||
}
|
||||
else
|
||||
{
|
||||
mp0 = VECTOR2I( 0, sh * ( h - w ) ); // direction: N
|
||||
mp1 = VECTOR2I( sw * w, sh * w ); // direction: NE
|
||||
}
|
||||
|
||||
bool start_diagonal;
|
||||
|
||||
if( m_dir == UNDEFINED )
|
||||
start_diagonal = aStartDiagonal;
|
||||
else
|
||||
start_diagonal = IsDiagonal();
|
||||
|
||||
SHAPE_LINE_CHAIN pl;
|
||||
|
||||
pl.Append( aP0 );
|
||||
|
||||
if( start_diagonal )
|
||||
pl.Append( aP0 + mp1 );
|
||||
else
|
||||
pl.Append( aP0 + mp0 );
|
||||
|
||||
pl.Append( aP1 );
|
||||
pl.Simplify();
|
||||
return pl;
|
||||
}
|
||||
bool aStartDiagonal = false,
|
||||
int aMaxRadius = 0 ) const;
|
||||
|
||||
bool operator==( const DIRECTION_45& aOther ) const
|
||||
{
|
||||
@ -258,14 +223,19 @@ public:
|
||||
* Function Right()
|
||||
*
|
||||
* Returns the direction on the right side of this (i.e. turns right
|
||||
* by 45 deg)
|
||||
* by 45 or 90 deg)
|
||||
*/
|
||||
const DIRECTION_45 Right() const
|
||||
{
|
||||
DIRECTION_45 r;
|
||||
|
||||
if ( m_dir != UNDEFINED )
|
||||
r.m_dir = static_cast<Directions>( ( m_dir + 1 ) % 8 );
|
||||
{
|
||||
if( m_90deg )
|
||||
r.m_dir = static_cast<Directions>( ( m_dir + 2 ) % LAST );
|
||||
else
|
||||
r.m_dir = static_cast<Directions>( ( m_dir + 1 ) % LAST );
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -274,19 +244,19 @@ public:
|
||||
* Function Left()
|
||||
*
|
||||
* Returns the direction on the left side of this (i.e. turns left
|
||||
* by 45 deg)
|
||||
* by 45 or 90 deg)
|
||||
*/
|
||||
const DIRECTION_45 Left() const
|
||||
{
|
||||
DIRECTION_45 l;
|
||||
|
||||
if ( m_dir == UNDEFINED )
|
||||
return l;
|
||||
|
||||
if( m_dir == N )
|
||||
l.m_dir = NW;
|
||||
else
|
||||
l.m_dir = static_cast<Directions>( m_dir - 1 );
|
||||
if ( m_dir != UNDEFINED )
|
||||
{
|
||||
if( m_90deg )
|
||||
l.m_dir = static_cast<Directions>( ( m_dir + LAST - 2 ) % LAST );
|
||||
else
|
||||
l.m_dir = static_cast<Directions>( ( m_dir + LAST - 1 ) % LAST );
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
@ -344,11 +314,11 @@ private:
|
||||
|
||||
int dir = ( mag + 22.5 ) / 45.0;
|
||||
|
||||
if( dir >= 8 )
|
||||
dir = dir - 8;
|
||||
if( dir >= LAST )
|
||||
dir -= LAST;
|
||||
|
||||
if( dir < 0 )
|
||||
dir = dir + 8;
|
||||
dir += LAST;
|
||||
|
||||
m_dir = (Directions) dir;
|
||||
|
||||
@ -357,6 +327,9 @@ private:
|
||||
|
||||
///> our actual direction
|
||||
Directions m_dir;
|
||||
|
||||
///> Are we routing on 45 or 90 degree increments
|
||||
bool m_90deg;
|
||||
};
|
||||
|
||||
#endif // DIRECTION45_H
|
||||
|
@ -2,6 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2018 CERN
|
||||
* Copyright (C) 2019-2020 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
|
||||
@ -50,6 +51,7 @@ public:
|
||||
SHAPE( SH_ARC ), m_p0( aArcStartPoint ), m_pc( aArcCenter ), m_centralAngle( aCenterAngle ),
|
||||
m_width( aWidth )
|
||||
{
|
||||
update_bbox();
|
||||
}
|
||||
|
||||
SHAPE_ARC( const SHAPE_ARC& aOther )
|
||||
@ -59,6 +61,7 @@ public:
|
||||
m_pc = aOther.m_pc;
|
||||
m_centralAngle = aOther.m_centralAngle;
|
||||
m_width = aOther.m_width;
|
||||
m_bbox = aOther.m_bbox;
|
||||
}
|
||||
|
||||
~SHAPE_ARC() {}
|
||||
@ -70,6 +73,7 @@ public:
|
||||
|
||||
const VECTOR2I& GetP0() const { return m_p0; }
|
||||
const VECTOR2I GetP1() const;
|
||||
const VECTOR2I GetArcMid() const;
|
||||
const VECTOR2I& GetCenter() const { return m_pc; }
|
||||
|
||||
const BOX2I BBox( int aClearance = 0 ) const override;
|
||||
@ -96,6 +100,7 @@ public:
|
||||
{
|
||||
m_p0 += aVector;
|
||||
m_pc += aVector;
|
||||
update_bbox();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -114,6 +119,7 @@ public:
|
||||
|
||||
m_pc += aCenter;
|
||||
m_p0 += aCenter;
|
||||
update_bbox();
|
||||
}
|
||||
|
||||
void Mirror( bool aX = true, bool aY = false, const VECTOR2I& aVector = { 0, 0 } )
|
||||
@ -131,6 +137,8 @@ public:
|
||||
m_pc.y = -m_pc.y + 2 * aVector.y;
|
||||
m_centralAngle = - m_centralAngle;
|
||||
}
|
||||
|
||||
update_bbox();
|
||||
}
|
||||
|
||||
int GetRadius() const;
|
||||
@ -176,11 +184,14 @@ private:
|
||||
(ecoord) ( aB.y - aA.y ) * ( aC.x - aA.x );
|
||||
}
|
||||
|
||||
void update_bbox();
|
||||
|
||||
|
||||
VECTOR2I m_p0, m_pc;
|
||||
double m_centralAngle;
|
||||
|
||||
int m_width;
|
||||
BOX2I m_bbox;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2013 CERN
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
* Copyright (C) 2013-2019
|
||||
* Copyright (C) 2013-2020 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
|
||||
@ -93,8 +93,8 @@ public:
|
||||
m_shapes( aShape.m_shapes ),
|
||||
m_arcs( aShape.m_arcs ),
|
||||
m_closed( aShape.m_closed ),
|
||||
m_bbox( aShape.m_bbox ),
|
||||
m_width( aShape.m_width )
|
||||
m_width( aShape.m_width ),
|
||||
m_bbox( aShape.m_bbox )
|
||||
{}
|
||||
|
||||
SHAPE_LINE_CHAIN( const std::vector<wxPoint>& aV, bool aClosed = false )
|
||||
@ -115,8 +115,20 @@ public:
|
||||
m_shapes = std::vector<ssize_t>( aV.size(), ssize_t( SHAPE_IS_PT ) );
|
||||
}
|
||||
|
||||
SHAPE_LINE_CHAIN( const ClipperLib::Path& aPath )
|
||||
: SHAPE( SH_LINE_CHAIN ), m_closed( true ), m_width( 0 )
|
||||
SHAPE_LINE_CHAIN( const SHAPE_ARC& aArc, bool aClosed = false )
|
||||
: SHAPE( SH_LINE_CHAIN ),
|
||||
m_closed( aClosed ),
|
||||
m_width( 0 )
|
||||
{
|
||||
m_points = aArc.ConvertToPolyline().CPoints();
|
||||
m_arcs.emplace_back( aArc );
|
||||
m_shapes = std::vector<ssize_t>( m_points.size(), 0 );
|
||||
}
|
||||
|
||||
SHAPE_LINE_CHAIN( const ClipperLib::Path& aPath ) :
|
||||
SHAPE( SH_LINE_CHAIN ),
|
||||
m_closed( true ),
|
||||
m_width( 0 )
|
||||
{
|
||||
m_points.reserve( aPath.size() );
|
||||
m_shapes = std::vector<ssize_t>( aPath.size(), ssize_t( SHAPE_IS_PT ) );
|
||||
@ -298,6 +310,22 @@ public:
|
||||
return m_points[PointCount() - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the vector of stored arcs
|
||||
*/
|
||||
const std::vector<SHAPE_ARC>& CArcs() const
|
||||
{
|
||||
return m_arcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the vector of values indicating shape type and location
|
||||
*/
|
||||
const std::vector<ssize_t>& CShapes() const
|
||||
{
|
||||
return m_shapes;
|
||||
}
|
||||
|
||||
/// @copydoc SHAPE::BBox()
|
||||
const BOX2I BBox( int aClearance = 0 ) const override
|
||||
{
|
||||
@ -695,7 +723,33 @@ public:
|
||||
|
||||
double Area() const;
|
||||
|
||||
size_t ArcCount() const
|
||||
{
|
||||
return m_arcs.size();
|
||||
}
|
||||
|
||||
ssize_t ArcIndex( size_t aSegment ) const
|
||||
{
|
||||
if( aSegment >= m_shapes.size() )
|
||||
return SHAPE_IS_PT;
|
||||
|
||||
return m_shapes[aSegment];
|
||||
}
|
||||
|
||||
const SHAPE_ARC& Arc( size_t aArc ) const
|
||||
{
|
||||
return m_arcs[aArc];
|
||||
}
|
||||
|
||||
bool isArc( size_t aSegment ) const
|
||||
{
|
||||
return aSegment < m_shapes.size() && m_shapes[aSegment] != SHAPE_IS_PT;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
constexpr static ssize_t SHAPE_IS_PT = -1;
|
||||
|
||||
/// array of vertices
|
||||
std::vector<VECTOR2I> m_points;
|
||||
|
||||
@ -705,7 +759,6 @@ private:
|
||||
* If the value is -1, the point is just a point
|
||||
*/
|
||||
std::vector<ssize_t> m_shapes;
|
||||
constexpr static ssize_t SHAPE_IS_PT = -1;
|
||||
|
||||
std::vector<SHAPE_ARC> m_arcs;
|
||||
|
||||
|
102
libs/kimath/src/geometry/direction_45.cpp
Normal file
102
libs/kimath/src/geometry/direction_45.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019 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 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.or/licenses/>.
|
||||
*/
|
||||
|
||||
#include <geometry/direction45.h>
|
||||
|
||||
const SHAPE_LINE_CHAIN DIRECTION_45::BuildInitialTrace( const VECTOR2I& aP0, const VECTOR2I& aP1,
|
||||
bool aStartDiagonal, int aMaxRadius ) const
|
||||
{
|
||||
bool start_diagonal;
|
||||
|
||||
if( m_dir == UNDEFINED )
|
||||
start_diagonal = aStartDiagonal;
|
||||
else
|
||||
start_diagonal = IsDiagonal();
|
||||
|
||||
int w = abs( aP1.x - aP0.x );
|
||||
int h = abs( aP1.y - aP0.y );
|
||||
int sw = sign( aP1.x - aP0.x );
|
||||
int sh = sign( aP1.y - aP0.y );
|
||||
|
||||
int radius = std::min( aMaxRadius, std::min( w, h ) );
|
||||
bool use_rounded = aMaxRadius > 0;
|
||||
int dist90 = use_rounded ? KiROUND( ( M_SQRT2 - 1.0 ) * radius ) : 0;
|
||||
int dist45 = use_rounded ? KiROUND( radius * ( 1.0 - M_SQRT1_2 ) ) : 0;
|
||||
|
||||
VECTOR2I mp0, mp1, arc_offset_90, arc_offset_45;
|
||||
|
||||
// we are more horizontal than vertical?
|
||||
// if( m_90deg )
|
||||
// {
|
||||
// if( m_dir == N || m_dir == S )
|
||||
//
|
||||
// }
|
||||
|
||||
if( w > h )
|
||||
{
|
||||
mp0 = VECTOR2I( ( w - h - dist90 ) * sw, 0 ); // direction: E
|
||||
mp1 = VECTOR2I( ( h - dist45 ) * sw, ( h - dist45 ) * sh ); // direction: NE
|
||||
arc_offset_90 = VECTOR2I( 0, radius * sh );
|
||||
arc_offset_45 = VECTOR2I( sw * radius * M_SQRT1_2, -sh * radius * M_SQRT1_2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
mp0 = VECTOR2I( 0, sh * ( h - w - dist90 ) ); // direction: N
|
||||
mp1 = VECTOR2I( sw * ( w - dist45 ), sh * ( w - dist45 ) ); // direction: NE
|
||||
arc_offset_90 = VECTOR2I( radius * sw, 0 );
|
||||
arc_offset_45 = VECTOR2I( -sw * radius * M_SQRT1_2, sh * radius * M_SQRT1_2 );
|
||||
}
|
||||
|
||||
SHAPE_LINE_CHAIN pl;
|
||||
VECTOR2I arc_center;
|
||||
|
||||
pl.Append( aP0 );
|
||||
VECTOR2I next_point;
|
||||
|
||||
if( start_diagonal )
|
||||
{
|
||||
next_point = aP0 + mp1;
|
||||
arc_center = aP0 + mp1 + arc_offset_45;
|
||||
}
|
||||
else
|
||||
{
|
||||
next_point = aP0 + mp0;
|
||||
arc_center = aP0 + mp0 + arc_offset_90;
|
||||
}
|
||||
|
||||
if( use_rounded )
|
||||
{
|
||||
int sa = start_diagonal ? -sw * sh : sw * sh;
|
||||
|
||||
if( h > w )
|
||||
sa = -sa;
|
||||
|
||||
SHAPE_ARC new_arc( arc_center, next_point, sa * 45.0 );
|
||||
pl.Append( new_arc );
|
||||
}
|
||||
else
|
||||
{
|
||||
pl.Append( next_point );
|
||||
}
|
||||
|
||||
pl.Append( aP1 );
|
||||
|
||||
pl.Simplify();
|
||||
return pl;
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 CERN
|
||||
* Copyright (C) 2019-2020 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
|
||||
@ -22,17 +23,18 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <assert.h> // for assert
|
||||
#include <math.h> // for cos, sin, M_PI, atan2, ceil
|
||||
#include <type_traits> // for swap
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
|
||||
#include <geometry/geometry_utils.h>
|
||||
#include <geometry/seg.h> // for SEG
|
||||
#include <geometry/shape_arc.h>
|
||||
#include <geometry/shape_line_chain.h>
|
||||
#include <math.h> // for cos, sin, M_PI, atan2, ceil
|
||||
#include <math/box2.h> // for BOX2I
|
||||
#include <math/vector2d.h> // for VECTOR2I, VECTOR2D, VECTOR2
|
||||
#include <type_traits> // for swap
|
||||
|
||||
|
||||
bool SHAPE_ARC::Collide( const SEG& aSeg, int aClearance ) const
|
||||
@ -150,16 +152,28 @@ const VECTOR2I SHAPE_ARC::GetP1() const
|
||||
auto ca = m_centralAngle * M_PI / 180.0;
|
||||
VECTOR2I p1;
|
||||
|
||||
p1.x = (int) ( m_pc.x + rvec.x * cos( ca ) - rvec.y * sin( ca ) );
|
||||
p1.y = (int) ( m_pc.y + rvec.x * sin( ca ) + rvec.y * cos( ca ) );
|
||||
p1.x = KiROUND( m_pc.x + rvec.x * cos( ca ) - rvec.y * sin( ca ) );
|
||||
p1.y = KiROUND( m_pc.y + rvec.x * sin( ca ) + rvec.y * cos( ca ) );
|
||||
|
||||
return p1;
|
||||
}
|
||||
|
||||
|
||||
const BOX2I SHAPE_ARC::BBox( int aClearance ) const
|
||||
const VECTOR2I SHAPE_ARC::GetArcMid() const
|
||||
{
|
||||
VECTOR2D rvec = m_p0 - m_pc;
|
||||
auto ca = m_centralAngle / 2.0 * M_PI / 180.0;
|
||||
VECTOR2I p1;
|
||||
|
||||
p1.x = KiROUND( m_pc.x + rvec.x * cos( ca ) - rvec.y * sin( ca ) );
|
||||
p1.y = KiROUND( m_pc.y + rvec.x * sin( ca ) + rvec.y * cos( ca ) );
|
||||
|
||||
return p1;
|
||||
}
|
||||
|
||||
|
||||
void SHAPE_ARC::update_bbox()
|
||||
{
|
||||
BOX2I bbox;
|
||||
std::vector<VECTOR2I> points;
|
||||
// Put start and end points in the point list
|
||||
points.push_back( m_p0 );
|
||||
@ -197,7 +211,13 @@ const BOX2I SHAPE_ARC::BBox( int aClearance ) const
|
||||
points.push_back( quad_pt );
|
||||
}
|
||||
|
||||
bbox.Compute( points );
|
||||
m_bbox.Compute( points );
|
||||
}
|
||||
|
||||
|
||||
const BOX2I SHAPE_ARC::BBox( int aClearance ) const
|
||||
{
|
||||
BOX2I bbox( m_bbox );
|
||||
|
||||
if( aClearance != 0 )
|
||||
bbox.Inflate( aClearance );
|
||||
@ -208,8 +228,15 @@ const BOX2I SHAPE_ARC::BBox( int aClearance ) const
|
||||
|
||||
bool SHAPE_ARC::Collide( const VECTOR2I& aP, int aClearance ) const
|
||||
{
|
||||
assert( false );
|
||||
return false;
|
||||
int minDist = aClearance + m_width / 2;
|
||||
auto bbox = BBox( minDist );
|
||||
|
||||
if( !bbox.Contains( aP ) )
|
||||
return false;
|
||||
|
||||
auto dist = ( aP - GetCenter() ).SquaredEuclideanNorm();
|
||||
|
||||
return dist <= ( GetRadius() + minDist ) && dist >= ( GetRadius() - minDist );
|
||||
}
|
||||
|
||||
|
||||
|
@ -192,7 +192,11 @@ void SHAPE_LINE_CHAIN::Replace( int aStartIndex, int aEndIndex, const VECTOR2I&
|
||||
{
|
||||
m_points.erase( m_points.begin() + aStartIndex + 1, m_points.begin() + aEndIndex + 1 );
|
||||
m_points[aStartIndex] = aP;
|
||||
|
||||
m_shapes.erase( m_shapes.begin() + aStartIndex + 1, m_shapes.begin() + aEndIndex + 1 );
|
||||
}
|
||||
|
||||
assert( m_shapes.size() == m_points.size() );
|
||||
}
|
||||
|
||||
|
||||
@ -204,47 +208,26 @@ void SHAPE_LINE_CHAIN::Replace( int aStartIndex, int aEndIndex, const SHAPE_LINE
|
||||
if( aStartIndex < 0 )
|
||||
aStartIndex += PointCount();
|
||||
|
||||
aEndIndex = std::min( aEndIndex, PointCount() - 1 );
|
||||
ssize_t arc_index = -1;
|
||||
Remove( aStartIndex, aEndIndex );
|
||||
|
||||
// N.B. This works because convertArc changes m_shapes on the first run
|
||||
for( int ind = aStartIndex; ind <= aEndIndex; ind++ )
|
||||
{
|
||||
if( m_shapes[ind] != SHAPE_IS_PT )
|
||||
{
|
||||
if( arc_index == -1 )
|
||||
arc_index = m_shapes[ind];
|
||||
// The total new arcs index is added to the new arc indices
|
||||
size_t prev_arc_count = m_arcs.size();
|
||||
auto new_shapes = aLine.m_shapes;
|
||||
|
||||
convertArc( ind );
|
||||
}
|
||||
}
|
||||
for( auto& shape : new_shapes )
|
||||
shape += prev_arc_count;
|
||||
|
||||
for( auto remaining_it = m_shapes.erase( m_shapes.begin() + aStartIndex,
|
||||
m_shapes.begin() + aEndIndex + 1 );
|
||||
remaining_it != m_shapes.end(); remaining_it++ )
|
||||
{
|
||||
if( *remaining_it != SHAPE_IS_PT )
|
||||
*remaining_it += aLine.m_arcs.size();
|
||||
}
|
||||
|
||||
m_shapes.insert( m_shapes.begin() + aStartIndex, aLine.m_shapes.begin(), aLine.m_shapes.end() );
|
||||
|
||||
for( auto new_it = m_shapes.begin() + aStartIndex;
|
||||
new_it != m_shapes.begin() + aStartIndex + aLine.m_shapes.size() + 1; new_it++ )
|
||||
{
|
||||
if( *new_it != SHAPE_IS_PT )
|
||||
*new_it += arc_index;
|
||||
}
|
||||
|
||||
m_arcs.insert( m_arcs.begin() + arc_index, aLine.m_arcs.begin(), aLine.m_arcs.end() );
|
||||
|
||||
m_points.erase( m_points.begin() + aStartIndex, m_points.begin() + aEndIndex + 1 );
|
||||
m_shapes.insert( m_shapes.begin() + aStartIndex, new_shapes.begin(), new_shapes.end() );
|
||||
m_points.insert( m_points.begin() + aStartIndex, aLine.m_points.begin(), aLine.m_points.end() );
|
||||
m_arcs.insert( m_arcs.end(), aLine.m_arcs.begin(), aLine.m_arcs.end() );
|
||||
|
||||
assert( m_shapes.size() == m_points.size() );
|
||||
}
|
||||
|
||||
|
||||
void SHAPE_LINE_CHAIN::Remove( int aStartIndex, int aEndIndex )
|
||||
{
|
||||
assert( m_shapes.size() == m_points.size() );
|
||||
if( aEndIndex < 0 )
|
||||
aEndIndex += PointCount();
|
||||
|
||||
@ -255,23 +238,21 @@ void SHAPE_LINE_CHAIN::Remove( int aStartIndex, int aEndIndex )
|
||||
return;
|
||||
|
||||
aEndIndex = std::min( aEndIndex, PointCount() );
|
||||
std::vector<size_t> extra_arcs;
|
||||
ssize_t last_arc = -1;
|
||||
std::set<size_t> extra_arcs;
|
||||
|
||||
for( ssize_t i = aStartIndex; i < aEndIndex; i++)
|
||||
// Remove any overlapping arcs in the point range
|
||||
for( int i = aStartIndex; i < aEndIndex; i++ )
|
||||
{
|
||||
if( m_shapes[i] != SHAPE_IS_PT && m_shapes[i] != last_arc )
|
||||
extra_arcs.emplace_back( m_shapes[i] );
|
||||
if( m_shapes[i] != SHAPE_IS_PT )
|
||||
extra_arcs.insert( m_shapes[i] );
|
||||
}
|
||||
|
||||
// Reverse the sort order to ensure we maintain valid indices
|
||||
std::sort( extra_arcs.begin(), extra_arcs.end(), std::greater<size_t>() );
|
||||
|
||||
for( auto arc : extra_arcs )
|
||||
convertArc( arc );
|
||||
|
||||
m_shapes.erase( m_shapes.begin() + aStartIndex, m_shapes.begin() + aEndIndex + 1 );
|
||||
m_points.erase( m_points.begin() + aStartIndex, m_points.begin() + aEndIndex + 1 );
|
||||
assert( m_shapes.size() == m_points.size() );
|
||||
}
|
||||
|
||||
|
||||
@ -358,7 +339,7 @@ const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int aStartIndex, int aEndIndex )
|
||||
if( aStartIndex < 0 )
|
||||
aStartIndex += PointCount();
|
||||
|
||||
for( int i = aStartIndex; i <= aEndIndex; i++ )
|
||||
for( int i = aStartIndex; i <= aEndIndex && static_cast<size_t>( i ) < m_points.size(); i++ )
|
||||
rv.Append( m_points[i] );
|
||||
|
||||
return rv;
|
||||
@ -367,6 +348,8 @@ const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int aStartIndex, int aEndIndex )
|
||||
|
||||
void SHAPE_LINE_CHAIN::Append( const SHAPE_LINE_CHAIN& aOtherLine )
|
||||
{
|
||||
assert( m_shapes.size() == m_points.size() );
|
||||
|
||||
if( aOtherLine.PointCount() == 0 )
|
||||
return;
|
||||
|
||||
@ -378,26 +361,41 @@ void SHAPE_LINE_CHAIN::Append( const SHAPE_LINE_CHAIN& aOtherLine )
|
||||
m_bbox.Merge( p );
|
||||
}
|
||||
|
||||
size_t num_arcs = m_arcs.size();
|
||||
m_arcs.insert( m_arcs.end(), aOtherLine.m_arcs.begin(), aOtherLine.m_arcs.end() );
|
||||
|
||||
for( int i = 1; i < aOtherLine.PointCount(); i++ )
|
||||
{
|
||||
const VECTOR2I p = aOtherLine.CPoint( i );
|
||||
m_points.push_back( p );
|
||||
m_shapes.push_back( ssize_t( SHAPE_IS_PT ) );
|
||||
|
||||
ssize_t arcIndex = aOtherLine.ArcIndex( i );
|
||||
|
||||
if( arcIndex != ssize_t( SHAPE_IS_PT ) )
|
||||
m_shapes.push_back( num_arcs + arcIndex );
|
||||
else
|
||||
m_shapes.push_back( ssize_t( SHAPE_IS_PT ) );
|
||||
|
||||
m_bbox.Merge( p );
|
||||
}
|
||||
|
||||
assert( m_shapes.size() == m_points.size() );
|
||||
}
|
||||
|
||||
|
||||
void SHAPE_LINE_CHAIN::Append( const SHAPE_ARC& aArc )
|
||||
{
|
||||
auto& chain = aArc.ConvertToPolyline();
|
||||
m_arcs.push_back( aArc );
|
||||
|
||||
for( auto& pt : chain.CPoints() )
|
||||
{
|
||||
m_points.push_back( pt );
|
||||
m_shapes.push_back( m_arcs.size() );
|
||||
}
|
||||
|
||||
m_arcs.push_back( aArc );
|
||||
|
||||
assert( m_shapes.size() == m_points.size() );
|
||||
}
|
||||
|
||||
|
||||
@ -408,6 +406,8 @@ void SHAPE_LINE_CHAIN::Insert( size_t aVertex, const VECTOR2I& aP )
|
||||
|
||||
m_points.insert( m_points.begin() + aVertex, aP );
|
||||
m_shapes.insert( m_shapes.begin() + aVertex, ssize_t( SHAPE_IS_PT ) );
|
||||
|
||||
assert( m_shapes.size() == m_points.size() );
|
||||
}
|
||||
|
||||
|
||||
@ -437,6 +437,7 @@ void SHAPE_LINE_CHAIN::Insert( size_t aVertex, const SHAPE_ARC& aArc )
|
||||
/// Step 3: Add the vector of indices to the shape vector
|
||||
std::vector<size_t> new_points( chain.PointCount(), arc_pos );
|
||||
m_shapes.insert( m_shapes.begin() + aVertex, new_points.begin(), new_points.end() );
|
||||
assert( m_shapes.size() == m_points.size() );
|
||||
}
|
||||
|
||||
|
||||
@ -707,6 +708,7 @@ const OPT<SHAPE_LINE_CHAIN::INTERSECTION> SHAPE_LINE_CHAIN::SelfIntersecting() c
|
||||
SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify()
|
||||
{
|
||||
std::vector<VECTOR2I> pts_unique;
|
||||
std::vector<ssize_t> shapes_unique;
|
||||
|
||||
if( PointCount() < 2 )
|
||||
{
|
||||
@ -728,20 +730,22 @@ SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify()
|
||||
{
|
||||
int j = i + 1;
|
||||
|
||||
while( j < np && CPoint( i ) == CPoint( j ) )
|
||||
while( j < np && m_points[i] == m_points[j] && m_shapes[i] == m_shapes[j] )
|
||||
j++;
|
||||
|
||||
pts_unique.push_back( CPoint( i ) );
|
||||
shapes_unique.push_back( m_shapes[i] );
|
||||
|
||||
i = j;
|
||||
}
|
||||
|
||||
m_points.clear();
|
||||
m_shapes.clear();
|
||||
np = pts_unique.size();
|
||||
|
||||
i = 0;
|
||||
|
||||
// stage 1: eliminate collinear segments
|
||||
// TODO(sh): handle arcs Maybe segment-wise?
|
||||
while( i < np - 2 )
|
||||
{
|
||||
const VECTOR2I p0 = pts_unique[i];
|
||||
@ -754,7 +758,7 @@ SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify()
|
||||
n++;
|
||||
|
||||
m_points.push_back( p0 );
|
||||
m_shapes.push_back( ssize_t( SHAPE_IS_PT ) );
|
||||
m_shapes.push_back( shapes_unique[i] );
|
||||
|
||||
if( n > i )
|
||||
i = n;
|
||||
@ -762,7 +766,7 @@ SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify()
|
||||
if( n == np )
|
||||
{
|
||||
m_points.push_back( pts_unique[n - 1] );
|
||||
m_shapes.push_back( ssize_t( SHAPE_IS_PT ) );
|
||||
m_shapes.push_back( shapes_unique[n - 1] );
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -772,11 +776,13 @@ SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify()
|
||||
if( np > 1 )
|
||||
{
|
||||
m_points.push_back( pts_unique[np - 2] );
|
||||
m_shapes.push_back( ssize_t( SHAPE_IS_PT ) );
|
||||
m_shapes.push_back( shapes_unique[np - 2] );
|
||||
}
|
||||
|
||||
m_points.push_back( pts_unique[np - 1] );
|
||||
m_shapes.push_back( ssize_t( SHAPE_IS_PT ) );
|
||||
m_shapes.push_back( shapes_unique[np - 1] );
|
||||
|
||||
assert( m_points.size() == m_shapes.size() );
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -929,7 +935,7 @@ bool SHAPE_LINE_CHAIN::Parse( std::stringstream& aStream )
|
||||
aStream >> p0.y;
|
||||
aStream >> angle;
|
||||
|
||||
m_arcs.emplace_back( pc, p0, angle );
|
||||
m_arcs.emplace_back( pc, p0, angle );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -212,6 +212,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry, bool a
|
||||
case PCB_LINE_T: // a segment not on copper layers
|
||||
case PCB_TEXT_T: // a text on a layer
|
||||
case PCB_TRACE_T: // a track segment (segment on a copper layer)
|
||||
case PCB_ARC_T: // an arced track segment (segment on a copper layer)
|
||||
case PCB_VIA_T: // a via (like track segment on a copper layer)
|
||||
case PCB_DIMENSION_T: // a dimension (graphic item)
|
||||
case PCB_TARGET_T: // a target (graphic item)
|
||||
|
@ -58,6 +58,7 @@ public:
|
||||
{
|
||||
case PCB_PAD_T:
|
||||
case PCB_TRACE_T:
|
||||
case PCB_ARC_T:
|
||||
case PCB_VIA_T:
|
||||
case PCB_ZONE_AREA_T:
|
||||
return true;
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <fctsys.h>
|
||||
#include <common.h>
|
||||
#include <class_board.h>
|
||||
#include <class_track.h>
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
#include <kiface_i.h>
|
||||
#include <pcbnew.h>
|
||||
|
@ -203,6 +203,7 @@ void BOARD::Move( const wxPoint& aMoveVector ) // overload
|
||||
PCB_TARGET_T,
|
||||
PCB_VIA_T,
|
||||
PCB_TRACE_T,
|
||||
PCB_ARC_T,
|
||||
// PCB_PAD_T, Can't be at board level
|
||||
// PCB_MODULE_TEXT_T, Can't be at board level
|
||||
PCB_MODULE_T,
|
||||
@ -549,6 +550,7 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
|
||||
|
||||
case PCB_TRACE_T:
|
||||
case PCB_VIA_T:
|
||||
case PCB_ARC_T:
|
||||
|
||||
// N.B. This inserts a small memory leak as we lose the
|
||||
if( !IsCopperLayer( aBoardItem->GetLayer() ) )
|
||||
@ -647,6 +649,7 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem )
|
||||
break;
|
||||
|
||||
case PCB_TRACE_T:
|
||||
case PCB_ARC_T:
|
||||
case PCB_VIA_T:
|
||||
m_tracks.erase( std::remove_if( m_tracks.begin(), m_tracks.end(),
|
||||
[aBoardItem]( BOARD_ITEM* aItem ) { return aItem == aBoardItem; } ) );
|
||||
@ -954,6 +957,7 @@ SEARCH_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, const KICAD_T s
|
||||
// consuming) search is made, but this case is statistically rare.
|
||||
case PCB_VIA_T:
|
||||
case PCB_TRACE_T:
|
||||
case PCB_ARC_T:
|
||||
result = IterateForward( m_Track, inspector, testData, p );
|
||||
|
||||
// skip over any types handled in the above call.
|
||||
@ -963,6 +967,7 @@ SEARCH_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, const KICAD_T s
|
||||
{
|
||||
case PCB_VIA_T:
|
||||
case PCB_TRACE_T:
|
||||
case PCB_ARC_T:
|
||||
continue;
|
||||
|
||||
default:
|
||||
@ -981,6 +986,7 @@ SEARCH_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, const KICAD_T s
|
||||
break;
|
||||
|
||||
case PCB_TRACE_T:
|
||||
case PCB_ARC_T:
|
||||
result = IterateForward<TRACK*>( m_tracks, inspector, testData, p );
|
||||
++p;
|
||||
break;
|
||||
@ -1415,7 +1421,7 @@ std::tuple<int, double, double> BOARD::GetTrackLength( const TRACK& aTrack ) con
|
||||
double length = 0.0;
|
||||
double package_length = 0.0;
|
||||
|
||||
constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_VIA_T, PCB_PAD_T, EOT };
|
||||
constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, EOT };
|
||||
auto connectivity = GetBoard()->GetConnectivity();
|
||||
|
||||
for( auto item : connectivity->GetConnectedItems(
|
||||
|
@ -58,6 +58,9 @@ class SHAPE_POLY_SET;
|
||||
class CONNECTIVITY_DATA;
|
||||
class COMPONENT;
|
||||
|
||||
// Forward declare endpoint from class_track.h
|
||||
enum ENDPOINT_T : int;
|
||||
|
||||
/**
|
||||
* Enum LAYER_T
|
||||
* gives the allowed types of layers, same as Specctra DSN spec.
|
||||
|
@ -1449,6 +1449,7 @@ double MODULE::CoverageRatio( const GENERAL_COLLECTOR& aCollector ) const
|
||||
case PCB_TEXT_T:
|
||||
case PCB_MODULE_TEXT_T:
|
||||
case PCB_TRACE_T:
|
||||
case PCB_ARC_T:
|
||||
case PCB_VIA_T:
|
||||
addRect( holes, item->GetBoundingBox() );
|
||||
break;
|
||||
|
@ -977,16 +977,28 @@ bool TRACK::HitTest( const wxPoint& aPosition, int aAccuracy ) const
|
||||
bool ARC::HitTest( const wxPoint& aPosition, int aAccuracy ) const
|
||||
{
|
||||
int max_dist = aAccuracy + ( m_Width / 2 );
|
||||
wxPoint center = GetPosition();
|
||||
wxPoint relpos = aPosition - center;
|
||||
double dist = EuclideanNorm( relpos );
|
||||
double radius = GetRadius();
|
||||
|
||||
auto rel_start = EuclideanNorm( aPosition - m_Start );
|
||||
auto rel_mid = EuclideanNorm( aPosition - m_Mid );
|
||||
auto rel_end = EuclideanNorm( aPosition - m_End );
|
||||
if( std::abs( dist - radius ) > max_dist )
|
||||
return false;
|
||||
|
||||
if( rel_start <= max_dist || rel_mid <= max_dist || rel_end <= max_dist )
|
||||
return true;
|
||||
double arc_angle_start = GetArcAngleStart(); // Always 0.0 ... 360 deg, in 0.1 deg
|
||||
double arc_hittest = ArcTangente( relpos.y, relpos.x );
|
||||
|
||||
//TODO: Calculate along arc
|
||||
return false;
|
||||
// Calculate relative angle between the starting point of the arc, and the test point
|
||||
arc_hittest -= arc_angle_start;
|
||||
|
||||
// Normalise arc_hittest between 0 ... 360 deg
|
||||
NORMALIZE_ANGLE_POS( arc_hittest );
|
||||
double arc_angle = GetAngle();
|
||||
|
||||
if( arc_angle < 0 )
|
||||
return arc_hittest >= 3600 + arc_angle;
|
||||
|
||||
return arc_hittest <= GetAngle();
|
||||
}
|
||||
|
||||
|
||||
@ -1090,6 +1102,50 @@ void VIA::SwapData( BOARD_ITEM* aImage )
|
||||
std::swap( *((VIA*) this), *((VIA*) aImage) );
|
||||
}
|
||||
|
||||
|
||||
const wxPoint ARC::GetPosition() const
|
||||
{
|
||||
auto center = GetArcCenter( VECTOR2I( m_Start ), VECTOR2I( m_Mid ), VECTOR2I( m_End ) );
|
||||
return wxPoint( center.x, center.y );
|
||||
}
|
||||
|
||||
double ARC::GetRadius() const
|
||||
{
|
||||
auto center = GetArcCenter( VECTOR2I( m_Start ), VECTOR2I( m_Mid ), VECTOR2I( m_End ) );
|
||||
return GetLineLength( wxPoint( center ), m_Start );
|
||||
}
|
||||
|
||||
double ARC::GetAngle() const
|
||||
{
|
||||
wxPoint center = GetPosition();
|
||||
wxPoint p0 = m_Start - center;
|
||||
wxPoint p1 = m_Mid - center;
|
||||
wxPoint p2 = m_End - center;
|
||||
double angle1 = ArcTangente( p1.y, p1.x ) - ArcTangente( p0.y, p0.x );
|
||||
double angle2 = ArcTangente( p2.y, p2.x ) - ArcTangente( p1.y, p1.x );
|
||||
|
||||
return NormalizeAngle180( angle1 ) + NormalizeAngle180( angle2 );
|
||||
}
|
||||
|
||||
double ARC::GetArcAngleStart() const
|
||||
{
|
||||
wxPoint center = GetPosition();
|
||||
|
||||
double angleStart = ArcTangente( m_Start.y - center.y,
|
||||
m_Start.x - center.x );
|
||||
return NormalizeAnglePos( angleStart );
|
||||
}
|
||||
|
||||
double ARC::GetArcAngleEnd() const
|
||||
{
|
||||
wxPoint center = GetPosition();
|
||||
|
||||
double angleEnd = ArcTangente( m_End.y - center.y,
|
||||
m_End.x - center.x );
|
||||
return NormalizeAnglePos( angleEnd );
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEBUG)
|
||||
|
||||
wxString TRACK::ShowState( int stateBits )
|
||||
|
@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
|
||||
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2020 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
|
||||
@ -38,6 +38,7 @@
|
||||
#include <pcbnew.h>
|
||||
|
||||
#include <geometry/seg.h>
|
||||
#include <geometry/shape_arc.h>
|
||||
|
||||
#include <trigo.h>
|
||||
|
||||
@ -50,14 +51,15 @@ class SHAPE_POLY_SET;
|
||||
|
||||
|
||||
// Flag used in locate routines (from which endpoint work)
|
||||
enum ENDPOINT_T {
|
||||
enum ENDPOINT_T : int
|
||||
{
|
||||
ENDPOINT_START = 0,
|
||||
ENDPOINT_END = 1
|
||||
};
|
||||
|
||||
// Via types
|
||||
// Note that this enum must be synchronized to GAL_LAYER_ID
|
||||
enum class VIATYPE
|
||||
enum class VIATYPE : int
|
||||
{
|
||||
THROUGH = 3, /* Always a through hole via */
|
||||
BLIND_BURIED = 2, /* this via can be on internal layers */
|
||||
@ -262,6 +264,14 @@ class ARC : public TRACK
|
||||
public:
|
||||
ARC( BOARD_ITEM* aParent ) : TRACK( aParent, PCB_ARC_T ){};
|
||||
|
||||
ARC( BOARD_ITEM* aParent, const SHAPE_ARC* aArc ) :
|
||||
TRACK( aParent, PCB_ARC_T )
|
||||
{
|
||||
m_Start = wxPoint( aArc->GetP0() );
|
||||
m_End = wxPoint( aArc->GetP1() );
|
||||
m_Mid = wxPoint( aArc->GetArcMid() );
|
||||
}
|
||||
|
||||
static inline bool ClassOf( const EDA_ITEM *aItem )
|
||||
{
|
||||
return aItem && PCB_ARC_T == aItem->Type();
|
||||
@ -281,6 +291,19 @@ public:
|
||||
void SetMid( const wxPoint& aMid ) { m_Mid = aMid; }
|
||||
const wxPoint& GetMid() const { return m_Mid; }
|
||||
|
||||
void SetPosition( const wxPoint& aPos ) override
|
||||
{
|
||||
printf("Setting the arc position\n");
|
||||
m_Start = aPos;
|
||||
}
|
||||
|
||||
virtual const wxPoint GetPosition() const override;
|
||||
|
||||
double GetRadius() const;
|
||||
double GetAngle() const;
|
||||
double GetArcAngleStart() const;
|
||||
double GetArcAngleEnd() const;
|
||||
|
||||
virtual bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
|
||||
|
||||
virtual bool HitTest( const EDA_RECT& aRect, bool aContained = true, int aAccuracy = 0 ) const override;
|
||||
@ -294,7 +317,7 @@ public:
|
||||
|
||||
/**
|
||||
* Function GetLength
|
||||
* returns the length of the track using the hypotenuse calculation.
|
||||
* returns the length of the arc track using a series of segment approximations.
|
||||
* @return double - the length of the track
|
||||
*/
|
||||
virtual double GetLength() const override
|
||||
|
@ -51,6 +51,7 @@ const KICAD_T GENERAL_COLLECTOR::AllBoardItems[] = {
|
||||
PCB_TARGET_T, // in m_Drawings
|
||||
PCB_VIA_T, // in m_Tracks
|
||||
PCB_TRACE_T, // in m_Tracks
|
||||
PCB_ARC_T, // in m_Tracks
|
||||
PCB_PAD_T, // in modules
|
||||
PCB_MODULE_TEXT_T, // in modules
|
||||
PCB_MODULE_T, // in m_Modules
|
||||
@ -66,6 +67,7 @@ const KICAD_T GENERAL_COLLECTOR::BoardLevelItems[] = {
|
||||
PCB_DIMENSION_T,
|
||||
PCB_TARGET_T,
|
||||
PCB_VIA_T,
|
||||
PCB_ARC_T,
|
||||
PCB_TRACE_T,
|
||||
PCB_MODULE_T,
|
||||
PCB_ZONE_AREA_T,
|
||||
@ -81,6 +83,7 @@ const KICAD_T GENERAL_COLLECTOR::AllButZones[] = {
|
||||
PCB_TARGET_T,
|
||||
PCB_VIA_T,
|
||||
PCB_TRACE_T,
|
||||
PCB_ARC_T,
|
||||
PCB_PAD_T,
|
||||
PCB_MODULE_TEXT_T,
|
||||
PCB_MODULE_T,
|
||||
@ -106,6 +109,7 @@ const KICAD_T GENERAL_COLLECTOR::PadsOrTracks[] = {
|
||||
PCB_PAD_T,
|
||||
PCB_VIA_T,
|
||||
PCB_TRACE_T,
|
||||
PCB_ARC_T,
|
||||
EOT
|
||||
};
|
||||
|
||||
@ -131,6 +135,7 @@ const KICAD_T GENERAL_COLLECTOR::ModuleItems[] = {
|
||||
|
||||
const KICAD_T GENERAL_COLLECTOR::Tracks[] = {
|
||||
PCB_TRACE_T,
|
||||
PCB_ARC_T,
|
||||
PCB_VIA_T,
|
||||
EOT
|
||||
};
|
||||
@ -139,6 +144,7 @@ const KICAD_T GENERAL_COLLECTOR::Tracks[] = {
|
||||
const KICAD_T GENERAL_COLLECTOR::LockableItems[] = {
|
||||
PCB_MODULE_T,
|
||||
PCB_TRACE_T,
|
||||
PCB_ARC_T,
|
||||
PCB_VIA_T,
|
||||
EOT
|
||||
};
|
||||
@ -184,6 +190,7 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData )
|
||||
break;
|
||||
|
||||
case PCB_TRACE_T:
|
||||
case PCB_ARC_T:
|
||||
breakhere++;
|
||||
break;
|
||||
|
||||
@ -263,6 +270,7 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData )
|
||||
break;
|
||||
|
||||
case PCB_TRACE_T:
|
||||
case PCB_ARC_T:
|
||||
if( m_Guide->IgnoreTracks() )
|
||||
goto exit;
|
||||
break;
|
||||
|
@ -60,6 +60,7 @@ bool CN_CONNECTIVITY_ALGO::Remove( BOARD_ITEM* aItem )
|
||||
break;
|
||||
|
||||
case PCB_TRACE_T:
|
||||
case PCB_ARC_T:
|
||||
m_itemMap[ static_cast<BOARD_CONNECTED_ITEM*>( aItem ) ].MarkItemsAsInvalid();
|
||||
m_itemMap.erase( static_cast<BOARD_CONNECTED_ITEM*>( aItem ) );
|
||||
m_itemList.SetDirty( true );
|
||||
@ -153,6 +154,16 @@ bool CN_CONNECTIVITY_ALGO::Add( BOARD_ITEM* aItem )
|
||||
break;
|
||||
}
|
||||
|
||||
case PCB_ARC_T:
|
||||
{
|
||||
if( m_itemMap.find( static_cast<ARC*>( aItem ) ) != m_itemMap.end() )
|
||||
return false;
|
||||
|
||||
add( m_itemList, static_cast<ARC*>( aItem ) );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PCB_VIA_T:
|
||||
if( m_itemMap.find( static_cast<VIA*>( aItem ) ) != m_itemMap.end() )
|
||||
return false;
|
||||
@ -280,8 +291,10 @@ void CN_CONNECTIVITY_ALGO::searchConnections()
|
||||
|
||||
const CN_CONNECTIVITY_ALGO::CLUSTERS CN_CONNECTIVITY_ALGO::SearchClusters( CLUSTER_SEARCH_MODE aMode )
|
||||
{
|
||||
constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_PAD_T, PCB_VIA_T, PCB_ZONE_AREA_T, PCB_MODULE_T, EOT };
|
||||
constexpr KICAD_T no_zones[] = { PCB_TRACE_T, PCB_PAD_T, PCB_VIA_T, PCB_MODULE_T, EOT };
|
||||
constexpr KICAD_T types[] =
|
||||
{ PCB_TRACE_T, PCB_ARC_T, PCB_PAD_T, PCB_VIA_T, PCB_ZONE_AREA_T, PCB_MODULE_T, EOT };
|
||||
constexpr KICAD_T no_zones[] =
|
||||
{ PCB_TRACE_T, PCB_ARC_T, PCB_PAD_T, PCB_VIA_T, PCB_MODULE_T, EOT };
|
||||
|
||||
if( aMode == CSM_PROPAGATE )
|
||||
return SearchClusters( aMode, no_zones, -1 );
|
||||
@ -423,6 +436,7 @@ void CN_CONNECTIVITY_ALGO::Build( const std::vector<BOARD_ITEM*>& aItems )
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_TRACE_T:
|
||||
case PCB_ARC_T:
|
||||
case PCB_VIA_T:
|
||||
case PCB_PAD_T:
|
||||
Add( item );
|
||||
|
@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 CERN
|
||||
* Copyright (C) 2018-2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018-2020 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
|
||||
@ -248,8 +248,8 @@ void CONNECTIVITY_DATA::ComputeDynamicRatsnest( const std::vector<BOARD_ITEM*>&
|
||||
|
||||
if( std::none_of( aItems.begin(), aItems.end(), []( const BOARD_ITEM* aItem )
|
||||
{ return( aItem->Type() == PCB_TRACE_T || aItem->Type() == PCB_PAD_T ||
|
||||
aItem->Type() == PCB_ZONE_AREA_T || aItem->Type() == PCB_MODULE_T ||
|
||||
aItem->Type() == PCB_VIA_T ); } ) )
|
||||
aItem->Type() == PCB_ARC_T || aItem->Type() == PCB_ZONE_AREA_T ||
|
||||
aItem->Type() == PCB_MODULE_T || aItem->Type() == PCB_VIA_T ); } ) )
|
||||
{
|
||||
return ;
|
||||
}
|
||||
@ -448,7 +448,10 @@ const
|
||||
{
|
||||
for( auto connected : citem->ConnectedItems() )
|
||||
{
|
||||
if( connected->Valid() && ( connected->Parent()->Type() == PCB_TRACE_T || connected->Parent()->Type() == PCB_VIA_T ) )
|
||||
if( connected->Valid() &&
|
||||
( connected->Parent()->Type() == PCB_TRACE_T ||
|
||||
connected->Parent()->Type() == PCB_VIA_T ||
|
||||
connected->Parent()->Type() == PCB_ARC_T ) )
|
||||
tracks.insert( static_cast<TRACK*> ( connected->Parent() ) );
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,8 @@ int CN_ITEM::AnchorCount() const
|
||||
case PCB_PAD_T:
|
||||
return 5; // center, north, south, east and west
|
||||
case PCB_TRACE_T:
|
||||
return 2; // stard and end
|
||||
case PCB_ARC_T:
|
||||
return 2; // start and end
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
@ -125,6 +126,7 @@ const VECTOR2I CN_ITEM::GetAnchor( int n ) const
|
||||
break;
|
||||
}
|
||||
case PCB_TRACE_T:
|
||||
case PCB_ARC_T:
|
||||
if( n == 0 )
|
||||
return static_cast<const TRACK*>( m_parent )->GetStart();
|
||||
else
|
||||
@ -236,17 +238,29 @@ CN_ITEM* CN_LIST::Add( D_PAD* pad )
|
||||
return item;
|
||||
}
|
||||
|
||||
CN_ITEM* CN_LIST::Add( TRACK* track )
|
||||
{
|
||||
auto item = new CN_ITEM( track, true );
|
||||
m_items.push_back( item );
|
||||
item->AddAnchor( track->GetStart() );
|
||||
item->AddAnchor( track->GetEnd() );
|
||||
item->SetLayer( track->GetLayer() );
|
||||
addItemtoTree( item );
|
||||
SetDirty();
|
||||
return item;
|
||||
}
|
||||
CN_ITEM* CN_LIST::Add( TRACK* track )
|
||||
{
|
||||
auto item = new CN_ITEM( track, true );
|
||||
m_items.push_back( item );
|
||||
item->AddAnchor( track->GetStart() );
|
||||
item->AddAnchor( track->GetEnd() );
|
||||
item->SetLayer( track->GetLayer() );
|
||||
addItemtoTree( item );
|
||||
SetDirty();
|
||||
return item;
|
||||
}
|
||||
|
||||
CN_ITEM* CN_LIST::Add( ARC* aArc )
|
||||
{
|
||||
auto item = new CN_ITEM( aArc, true );
|
||||
m_items.push_back( item );
|
||||
item->AddAnchor( aArc->GetStart() );
|
||||
item->AddAnchor( aArc->GetEnd() );
|
||||
item->SetLayer( aArc->GetLayer() );
|
||||
addItemtoTree( item );
|
||||
SetDirty();
|
||||
return item;
|
||||
}
|
||||
|
||||
CN_ITEM* CN_LIST::Add( VIA* via )
|
||||
{
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <class_board.h>
|
||||
#include <class_pad.h>
|
||||
#include <class_module.h>
|
||||
#include <class_track.h>
|
||||
#include <class_zone.h>
|
||||
|
||||
#include <geometry/shape_poly_set.h>
|
||||
@ -476,6 +477,8 @@ public:
|
||||
|
||||
CN_ITEM* Add( TRACK* track );
|
||||
|
||||
CN_ITEM* Add( ARC* track );
|
||||
|
||||
CN_ITEM* Add( VIA* via );
|
||||
|
||||
const std::vector<CN_ITEM*> Add( ZONE_CONTAINER* zone );
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <confirm.h>
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <class_board.h>
|
||||
#include <class_track.h>
|
||||
#include <connectivity/connectivity_data.h>
|
||||
#include <view/view.h>
|
||||
#include <pcb_layer_box_selector.h>
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <pcbnew.h>
|
||||
#include <tools/pcb_inspection_tool.h>
|
||||
#include <class_board.h>
|
||||
#include <class_track.h>
|
||||
#include <dialog_select_net_from_list_base.h>
|
||||
#include <eda_pattern_match.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
|
@ -93,6 +93,7 @@ DIALOG_TRACK_VIA_PROPERTIES::DIALOG_TRACK_VIA_PROPERTIES( PCB_BASE_FRAME* aParen
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_TRACE_T:
|
||||
case PCB_ARC_T:
|
||||
{
|
||||
const TRACK* t = static_cast<const TRACK*>( item );
|
||||
|
||||
@ -410,6 +411,7 @@ bool DIALOG_TRACK_VIA_PROPERTIES::TransferDataFromWindow()
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_TRACE_T:
|
||||
case PCB_ARC_T:
|
||||
{
|
||||
wxASSERT( m_tracks );
|
||||
TRACK* t = static_cast<TRACK*>( item );
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include <class_track.h>
|
||||
#include <collectors.h>
|
||||
#include <reporter.h>
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user