From 342fd6e19eaf9a941b15df0696f7ecbe35206de1 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 18 Mar 2014 13:57:10 +0100 Subject: [PATCH] EC_CONVERGING handles colinear lines properly. --- include/geometry/seg.h | 14 +++++++------- pcbnew/tools/edit_points.cpp | 28 +++++++++++++++++++++++----- pcbnew/tools/edit_points.h | 4 ++++ 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/include/geometry/seg.h b/include/geometry/seg.h index 7e789f9d21..cf5b8d50c9 100644 --- a/include/geometry/seg.h +++ b/include/geometry/seg.h @@ -244,14 +244,14 @@ public: */ bool Collinear( const SEG& aSeg ) const { - ecoord qa1 = A.y - B.y; - ecoord qb1 = B.x - A.x; - ecoord qc1 = -qa1 * A.x - qb1 * A.y; - ecoord qa2 = aSeg.A.y - aSeg.B.y; - ecoord qb2 = aSeg.B.x - aSeg.A.x; - ecoord qc2 = -qa2 * aSeg.A.x - qb2 * aSeg.A.y; + ecoord qa = A.y - B.y; + ecoord qb = B.x - A.x; + ecoord qc = -qa * A.x - qb * A.y; - return ( qa1 == qa2 ) && ( qb1 == qb2 ) && ( qc1 == qc2 ); + ecoord d1 = std::abs( aSeg.A.x * qa + aSeg.A.y * qb + qc ); + ecoord d2 = std::abs( aSeg.B.x * qa + aSeg.B.y * qb + qc ); + + return ( d1 <= 1 && d2 <= 1 ); } /** diff --git a/pcbnew/tools/edit_points.cpp b/pcbnew/tools/edit_points.cpp index 23c8f1dbf4..291caae818 100644 --- a/pcbnew/tools/edit_points.cpp +++ b/pcbnew/tools/edit_points.cpp @@ -194,7 +194,8 @@ void EC_CIRCLE::Apply( EDIT_POINT& aHandle ) EC_CONVERGING::EC_CONVERGING( EDIT_LINE& aLine, EDIT_POINTS& aPoints ) : - EDIT_CONSTRAINT( aLine.GetOrigin() ), m_line( aLine ), m_editPoints( aPoints ) + EDIT_CONSTRAINT( aLine.GetOrigin() ), + m_colinearConstraint( NULL ), m_line( aLine ), m_editPoints( aPoints ) { // Dragged segment endings EDIT_POINT& origin = aLine.GetOrigin(); @@ -209,7 +210,17 @@ EC_CONVERGING::EC_CONVERGING( EDIT_LINE& aLine, EDIT_POINTS& aPoints ) : m_endSideConstraint = new EC_LINE( end, nextEnd ); // Store the current vector of the line - m_draggedVector = end.GetPosition() - origin.GetPosition() ; + m_draggedVector = end.GetPosition() - origin.GetPosition(); + + // Check for colinearity + SEG originSide( origin.GetPosition(), prevOrigin.GetPosition() ); + SEG endSide( end.GetPosition(), nextEnd.GetPosition() ); + SEG dragged( origin.GetPosition(), end.GetPosition() ); + + if( dragged.Collinear( originSide ) ) + m_colinearConstraint = m_originSideConstraint; + else if( dragged.Collinear( endSide ) ) + m_colinearConstraint = m_endSideConstraint; } @@ -217,18 +228,25 @@ EC_CONVERGING::~EC_CONVERGING() { delete m_originSideConstraint; delete m_endSideConstraint; + // m_colinearConstraint should not be freed, it is a pointer to one of the above } void EC_CONVERGING::Apply( EDIT_POINT& aHandle ) { - // The dragged segment - SEG dragged( m_line.GetPosition(), m_line.GetPosition() + m_draggedVector ); - // The dragged segment endpoints EDIT_POINT& origin = m_line.GetOrigin(); EDIT_POINT& end = m_line.GetEnd(); + if( m_colinearConstraint ) + { + m_colinearConstraint->Apply( origin ); + m_colinearConstraint->Apply( end ); + } + + // The dragged segment + SEG dragged( origin.GetPosition(), origin.GetPosition() + m_draggedVector ); + // Do not allow points on the adjacent segments move freely m_originSideConstraint->Apply(); m_endSideConstraint->Apply(); diff --git a/pcbnew/tools/edit_points.h b/pcbnew/tools/edit_points.h index 0c1dd343c2..b2e99988e6 100644 --- a/pcbnew/tools/edit_points.h +++ b/pcbnew/tools/edit_points.h @@ -622,6 +622,10 @@ private: ///> Constraint for end side segment. EDIT_CONSTRAINT* m_endSideConstraint; + ///> Additional constriant, applied when at least two points are collinear. It is a pointer to + ///> m_[origin/end]SideConstraint, so it should not be freed. + EDIT_CONSTRAINT* m_colinearConstraint; + ///> Dragged segment. EDIT_LINE& m_line;