mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 18:23:15 +02:00
Improve H/V/45 deg mode when drawing zones and polygons.
This commit is contained in:
parent
945361ca65
commit
3d2b1aaf90
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2017-2020 Kicad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2017-2022 Kicad Developers, see AUTHORS.txt for contributors.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@ -46,9 +46,10 @@ bool POLYGON_GEOM_MANAGER::AddPoint( const VECTOR2I& aPt )
|
|||||||
if( m_leaderPts.PointCount() > 1 )
|
if( m_leaderPts.PointCount() > 1 )
|
||||||
{
|
{
|
||||||
// there are enough leader points - the next
|
// there are enough leader points - the next
|
||||||
// locked-in point is the end of the first leader
|
// locked-in point is the end of the last leader
|
||||||
// segment
|
// segment
|
||||||
m_lockedPoints.Append( m_leaderPts.CPoint( 1 ) );
|
m_lockedPoints.Append( m_leaderPts.CPoint( -2 ) );
|
||||||
|
m_lockedPoints.Append( m_leaderPts.CPoint( -1 ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -63,6 +64,9 @@ bool POLYGON_GEOM_MANAGER::AddPoint( const VECTOR2I& aPt )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( m_lockedPoints.PointCount() > 0 )
|
||||||
|
updateTemporaryLines( aPt );
|
||||||
|
|
||||||
m_client.OnGeometryChange( *this );
|
m_client.OnGeometryChange( *this );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -103,7 +107,7 @@ bool POLYGON_GEOM_MANAGER::IsSelfIntersecting( bool aIncludeLeaderPts ) const
|
|||||||
|
|
||||||
void POLYGON_GEOM_MANAGER::SetCursorPosition( const VECTOR2I& aPos )
|
void POLYGON_GEOM_MANAGER::SetCursorPosition( const VECTOR2I& aPos )
|
||||||
{
|
{
|
||||||
updateLeaderPoints( aPos );
|
updateTemporaryLines( aPos );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -127,7 +131,7 @@ void POLYGON_GEOM_MANAGER::DeleteLastCorner()
|
|||||||
// update the new last segment (was previously
|
// update the new last segment (was previously
|
||||||
// locked in), reusing last constraints
|
// locked in), reusing last constraints
|
||||||
if( m_lockedPoints.PointCount() > 0 )
|
if( m_lockedPoints.PointCount() > 0 )
|
||||||
updateLeaderPoints( m_leaderPts.CLastPoint() );
|
updateTemporaryLines( m_leaderPts.CLastPoint() );
|
||||||
|
|
||||||
m_client.OnGeometryChange( *this );
|
m_client.OnGeometryChange( *this );
|
||||||
}
|
}
|
||||||
@ -142,67 +146,93 @@ void POLYGON_GEOM_MANAGER::Reset()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void POLYGON_GEOM_MANAGER::updateLeaderPoints( const VECTOR2I& aEndPoint, LEADER_MODE aModifier )
|
SHAPE_LINE_CHAIN build45DegLeader( const VECTOR2I& aEndPoint, SHAPE_LINE_CHAIN aLastPoints )
|
||||||
|
{
|
||||||
|
if( aLastPoints.PointCount() < 1 )
|
||||||
|
return SHAPE_LINE_CHAIN();
|
||||||
|
|
||||||
|
const VECTOR2I lastPt = aLastPoints.CPoint( -1 );
|
||||||
|
const VECTOR2D endpointD = aEndPoint;
|
||||||
|
const VECTOR2D lineVec = endpointD - lastPt;
|
||||||
|
|
||||||
|
if( aLastPoints.SegmentCount() < 1 )
|
||||||
|
return SHAPE_LINE_CHAIN(
|
||||||
|
std::vector<VECTOR2I>{ lastPt, lastPt + GetVectorSnapped45( lineVec ) } );
|
||||||
|
|
||||||
|
EDA_ANGLE lineA( lineVec );
|
||||||
|
EDA_ANGLE prevA( GetVectorSnapped45( lastPt - aLastPoints.CPoint( -2 ) ) );
|
||||||
|
|
||||||
|
bool vertical = std::abs( lineVec.y ) > std::abs( lineVec.x );
|
||||||
|
bool horizontal = std::abs( lineVec.y ) < std::abs( lineVec.x );
|
||||||
|
|
||||||
|
double angDiff = std::abs( ( lineA - prevA ).Normalize180().AsDegrees() );
|
||||||
|
|
||||||
|
bool bendEnd = ( angDiff < 45 ) || ( angDiff > 90 && angDiff < 135 );
|
||||||
|
|
||||||
|
if( prevA.Normalize90() == ANGLE_45 || prevA.Normalize90() == -ANGLE_45 )
|
||||||
|
bendEnd = !bendEnd;
|
||||||
|
|
||||||
|
VECTOR2D mid = endpointD;
|
||||||
|
|
||||||
|
if( bendEnd )
|
||||||
|
{
|
||||||
|
if( vertical )
|
||||||
|
{
|
||||||
|
if( lineVec.y > 0 )
|
||||||
|
mid = VECTOR2D( lastPt.x, endpointD.y - std::abs( lineVec.x ) );
|
||||||
|
else
|
||||||
|
mid = VECTOR2D( lastPt.x, endpointD.y + std::abs( lineVec.x ) );
|
||||||
|
}
|
||||||
|
else if( horizontal )
|
||||||
|
{
|
||||||
|
if( lineVec.x > 0 )
|
||||||
|
mid = VECTOR2D( endpointD.x - std::abs( lineVec.y ), lastPt.y );
|
||||||
|
else
|
||||||
|
mid = VECTOR2D( endpointD.x + std::abs( lineVec.y ), lastPt.y );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( vertical )
|
||||||
|
{
|
||||||
|
if( lineVec.y > 0 )
|
||||||
|
mid = VECTOR2D( endpointD.x, lastPt.y + std::abs( lineVec.x ) );
|
||||||
|
else
|
||||||
|
mid = VECTOR2D( endpointD.x, lastPt.y - std::abs( lineVec.x ) );
|
||||||
|
}
|
||||||
|
else if( horizontal )
|
||||||
|
{
|
||||||
|
if( lineVec.x > 0 )
|
||||||
|
mid = VECTOR2D( lastPt.x + std::abs( lineVec.y ), endpointD.y );
|
||||||
|
else
|
||||||
|
mid = VECTOR2D( lastPt.x - std::abs( lineVec.y ), endpointD.y );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const VECTOR2I midInt = { KiROUND( mid.x ), KiROUND( mid.y ) };
|
||||||
|
|
||||||
|
return SHAPE_LINE_CHAIN( std::vector<VECTOR2I>{ lastPt, midInt, aEndPoint } );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void POLYGON_GEOM_MANAGER::updateTemporaryLines( const VECTOR2I& aEndPoint, LEADER_MODE aModifier )
|
||||||
{
|
{
|
||||||
wxCHECK( m_lockedPoints.PointCount() > 0, /*void*/ );
|
wxCHECK( m_lockedPoints.PointCount() > 0, /*void*/ );
|
||||||
const VECTOR2I& last_pt = m_lockedPoints.CLastPoint();
|
const VECTOR2I& last_pt = m_lockedPoints.CLastPoint();
|
||||||
|
|
||||||
if( m_leaderMode == LEADER_MODE::DEG45 || aModifier == LEADER_MODE::DEG45 )
|
if( m_leaderMode == LEADER_MODE::DEG45 || aModifier == LEADER_MODE::DEG45 )
|
||||||
{
|
{
|
||||||
const VECTOR2I line_vec( aEndPoint - last_pt );
|
if( m_lockedPoints.PointCount() > 0 )
|
||||||
// get a restricted 45/H/V line from the last fixed point to the cursor
|
|
||||||
auto new_end = last_pt + GetVectorSnapped45( line_vec );
|
|
||||||
OPT_VECTOR2I pt;
|
|
||||||
|
|
||||||
if( m_lockedPoints.SegmentCount() > 1 )
|
|
||||||
{
|
{
|
||||||
const VECTOR2I& start_pt = m_lockedPoints.CPoint( 0 );
|
m_leaderPts = build45DegLeader( aEndPoint, m_lockedPoints );
|
||||||
VECTOR2I completed_vec( start_pt - new_end );
|
m_loopPts = build45DegLeader( aEndPoint, m_lockedPoints.Reverse() ).Reverse();
|
||||||
|
|
||||||
if( completed_vec != GetVectorSnapped45( completed_vec ) )
|
|
||||||
{
|
|
||||||
SEG v_first( new_end, VECTOR2I( new_end.x, start_pt.y ) );
|
|
||||||
SEG h_first( new_end, VECTOR2I( start_pt.x, new_end.y ) );
|
|
||||||
|
|
||||||
SHAPE_LINE_CHAIN::INTERSECTIONS intersections;
|
|
||||||
auto v_hits = m_lockedPoints.Intersect( v_first, intersections );
|
|
||||||
v_hits += m_lockedPoints.Intersect( SEG( v_first.B, start_pt ), intersections );
|
|
||||||
pt = v_first.B;
|
|
||||||
|
|
||||||
if( v_hits > 0 )
|
|
||||||
{
|
|
||||||
intersections.clear();
|
|
||||||
auto h_hits = m_lockedPoints.Intersect( h_first, intersections );
|
|
||||||
h_hits += m_lockedPoints.Intersect( SEG( h_first.B, start_pt ), intersections );
|
|
||||||
|
|
||||||
if( h_hits < v_hits )
|
|
||||||
pt = h_first.B;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_leaderPts = SHAPE_LINE_CHAIN( { last_pt, new_end } );
|
|
||||||
|
|
||||||
if( pt )
|
|
||||||
{
|
|
||||||
SEG drawn( last_pt, new_end );
|
|
||||||
SEG completed( new_end, *pt );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check for backtracking from the point to intersection. If the snapped path to
|
|
||||||
* completion is shorter than what the user actually drew, we want to discard the
|
|
||||||
* drawn point and just use the snapped completion point.
|
|
||||||
*/
|
|
||||||
if( drawn.Collinear( completed ) && drawn.SquaredLength() > completed.SquaredLength() )
|
|
||||||
m_leaderPts = SHAPE_LINE_CHAIN( { last_pt, *pt } );
|
|
||||||
else
|
|
||||||
m_leaderPts.Append( *pt );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// direct segment
|
// direct segment
|
||||||
m_leaderPts = SHAPE_LINE_CHAIN( { last_pt, aEndPoint } );
|
m_leaderPts = SHAPE_LINE_CHAIN( { last_pt, aEndPoint } );
|
||||||
|
m_loopPts.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_client.OnGeometryChange( *this );
|
m_client.OnGeometryChange( *this );
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2017 Kicad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2017-2022 Kicad Developers, see AUTHORS.txt for contributors.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@ -36,10 +36,11 @@ POLYGON_ITEM::POLYGON_ITEM() :
|
|||||||
|
|
||||||
|
|
||||||
void POLYGON_ITEM::SetPoints( const SHAPE_LINE_CHAIN& aLockedInPts,
|
void POLYGON_ITEM::SetPoints( const SHAPE_LINE_CHAIN& aLockedInPts,
|
||||||
const SHAPE_LINE_CHAIN& aLeaderPts )
|
const SHAPE_LINE_CHAIN& aLeaderPts, const SHAPE_LINE_CHAIN& aLoopPts )
|
||||||
{
|
{
|
||||||
m_lockedChain = aLockedInPts;
|
m_lockedChain = aLockedInPts;
|
||||||
m_leaderChain = aLeaderPts;
|
m_leaderChain = aLeaderPts;
|
||||||
|
m_loopChain = aLoopPts;
|
||||||
|
|
||||||
m_polyfill.RemoveAllContours();
|
m_polyfill.RemoveAllContours();
|
||||||
m_polyfill.NewOutline();
|
m_polyfill.NewOutline();
|
||||||
@ -49,6 +50,9 @@ void POLYGON_ITEM::SetPoints( const SHAPE_LINE_CHAIN& aLockedInPts,
|
|||||||
|
|
||||||
for( int i = 0; i < aLeaderPts.PointCount(); ++i )
|
for( int i = 0; i < aLeaderPts.PointCount(); ++i )
|
||||||
m_polyfill.Append( aLeaderPts.CPoint( i ) );
|
m_polyfill.Append( aLeaderPts.CPoint( i ) );
|
||||||
|
|
||||||
|
for( int i = 0; i < aLoopPts.PointCount(); ++i )
|
||||||
|
m_polyfill.Append( aLoopPts.CPoint( i ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -70,6 +74,8 @@ void POLYGON_ITEM::drawPreviewShape( KIGFX::VIEW* aView ) const
|
|||||||
gal.DrawPolyline( m_leaderChain );
|
gal.DrawPolyline( m_leaderChain );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gal.SetIsStroke( false );
|
||||||
|
|
||||||
for( int j = 0; j < m_polyfill.OutlineCount(); ++j )
|
for( int j = 0; j < m_polyfill.OutlineCount(); ++j )
|
||||||
{
|
{
|
||||||
const SHAPE_LINE_CHAIN& outline = m_polyfill.COutline( j );
|
const SHAPE_LINE_CHAIN& outline = m_polyfill.COutline( j );
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2017-2021 Kicad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2017-2022 Kicad Developers, see AUTHORS.txt for contributors.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@ -174,13 +174,22 @@ public:
|
|||||||
return m_leaderPts;
|
return m_leaderPts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the points from the current cursor position
|
||||||
|
* to the polygon start point
|
||||||
|
*/
|
||||||
|
const SHAPE_LINE_CHAIN& GetLoopLinePoints() const
|
||||||
|
{
|
||||||
|
return m_loopPts;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the leader line points based on a new endpoint (probably
|
* Update the leader and loop lines points based on a new endpoint (probably
|
||||||
* a cursor position)
|
* a cursor position)
|
||||||
*/
|
*/
|
||||||
void updateLeaderPoints( const VECTOR2I& aEndPoint,
|
void updateTemporaryLines( const VECTOR2I& aEndPoint,
|
||||||
LEADER_MODE aModifier = LEADER_MODE::DIRECT );
|
LEADER_MODE aModifier = LEADER_MODE::DIRECT );
|
||||||
|
|
||||||
///< The "user" of the polygon data that is informed when the geometry changes
|
///< The "user" of the polygon data that is informed when the geometry changes
|
||||||
@ -197,6 +206,9 @@ private:
|
|||||||
|
|
||||||
///< Points in the temporary "leader" line(s)
|
///< Points in the temporary "leader" line(s)
|
||||||
SHAPE_LINE_CHAIN m_leaderPts;
|
SHAPE_LINE_CHAIN m_leaderPts;
|
||||||
|
|
||||||
|
///< Points between the cursor and start point
|
||||||
|
SHAPE_LINE_CHAIN m_loopPts;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PREVIEW_POLYGON_GEOM_MANAGER__H_
|
#endif // PREVIEW_POLYGON_GEOM_MANAGER__H_
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* This program source code file is part of KICAD, a free EDA CAD application.
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2017-2021 Kicad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2017-2022 Kicad Developers, see AUTHORS.txt for contributors.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@ -56,16 +56,17 @@ public:
|
|||||||
* @param aLockedInPts - the "fixed points" of the outline
|
* @param aLockedInPts - the "fixed points" of the outline
|
||||||
* @param aLeaderPts - the lines from the last fixed point to
|
* @param aLeaderPts - the lines from the last fixed point to
|
||||||
* another point, eg the cursor.
|
* another point, eg the cursor.
|
||||||
|
* @param aLoopPts - the lines from the cursor to the start point.
|
||||||
*/
|
*/
|
||||||
void SetPoints( const SHAPE_LINE_CHAIN& aLockedInPts,
|
void SetPoints( const SHAPE_LINE_CHAIN& aLockedInPts, const SHAPE_LINE_CHAIN& aLeaderPts,
|
||||||
const SHAPE_LINE_CHAIN& aLeaderPts );
|
const SHAPE_LINE_CHAIN& aLoopPts );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
///< Draw rectangle and center line onto GAL
|
///< Draw rectangle and center line onto GAL
|
||||||
void drawPreviewShape( KIGFX::VIEW* aView ) const override;
|
void drawPreviewShape( KIGFX::VIEW* aView ) const override;
|
||||||
|
|
||||||
///< complete polyline of locked in and leader points
|
///< complete polyline of locked in, leader and looping points
|
||||||
SHAPE_LINE_CHAIN m_lockedChain, m_leaderChain;
|
SHAPE_LINE_CHAIN m_lockedChain, m_leaderChain, m_loopChain;
|
||||||
|
|
||||||
///< polygon fill
|
///< polygon fill
|
||||||
SHAPE_POLY_SET m_polyfill;
|
SHAPE_POLY_SET m_polyfill;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2017-2019 KiCad Developers, see AUTHORS.txt for contributors.
|
* Copyright (C) 2017-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@ -320,7 +320,8 @@ bool ZONE_CREATE_HELPER::OnFirstPoint( POLYGON_GEOM_MANAGER& aMgr )
|
|||||||
void ZONE_CREATE_HELPER::OnGeometryChange( const POLYGON_GEOM_MANAGER& aMgr )
|
void ZONE_CREATE_HELPER::OnGeometryChange( const POLYGON_GEOM_MANAGER& aMgr )
|
||||||
{
|
{
|
||||||
// send the points to the preview item
|
// send the points to the preview item
|
||||||
m_previewItem.SetPoints( aMgr.GetLockedInPoints(), aMgr.GetLeaderLinePoints() );
|
m_previewItem.SetPoints( aMgr.GetLockedInPoints(), aMgr.GetLeaderLinePoints(),
|
||||||
|
aMgr.GetLoopLinePoints() );
|
||||||
m_parentView.Update( &m_previewItem, KIGFX::GEOMETRY );
|
m_parentView.Update( &m_previewItem, KIGFX::GEOMETRY );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,9 +350,13 @@ void ZONE_CREATE_HELPER::OnComplete( const POLYGON_GEOM_MANAGER& aMgr )
|
|||||||
// 45 constraint
|
// 45 constraint
|
||||||
if( aMgr.GetLeaderMode() == POLYGON_GEOM_MANAGER::LEADER_MODE::DEG45 )
|
if( aMgr.GetLeaderMode() == POLYGON_GEOM_MANAGER::LEADER_MODE::DEG45 )
|
||||||
{
|
{
|
||||||
const auto& pts = aMgr.GetLeaderLinePoints();
|
const SHAPE_LINE_CHAIN leaderPts = aMgr.GetLeaderLinePoints();
|
||||||
for( int i = 1; i < pts.PointCount(); i++ )
|
for( int i = 1; i < leaderPts.PointCount(); i++ )
|
||||||
outline->Append( pts.CPoint( i ) );
|
outline->Append( leaderPts.CPoint( i ) );
|
||||||
|
|
||||||
|
const SHAPE_LINE_CHAIN loopPts = aMgr.GetLoopLinePoints();
|
||||||
|
for( int i = 1; i < loopPts.PointCount(); i++ )
|
||||||
|
outline->Append( loopPts.CPoint( i ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
outline->Outline( 0 ).SetClosed( true );
|
outline->Outline( 0 ).SetClosed( true );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user