From 07877f90440c06990e48b76ecfc841831a0fd48b Mon Sep 17 00:00:00 2001 From: Lorenzo Marcantonio Date: Wed, 21 May 2014 19:02:32 +0200 Subject: [PATCH] Replaced the display line clipper with the way simpler (and faster) Cohen-Sutherland one. A couple of trivial accessors made inline --- common/gr_basic.cpp | 275 +++++++------------------- pcbnew/class_board_connected_item.cpp | 18 -- pcbnew/class_board_connected_item.h | 17 +- 3 files changed, 82 insertions(+), 228 deletions(-) diff --git a/common/gr_basic.cpp b/common/gr_basic.cpp index b0ff4b6ff2..f82d997789 100644 --- a/common/gr_basic.cpp +++ b/common/gr_basic.cpp @@ -79,6 +79,26 @@ static EDA_COLOR_T s_DC_lastbrushcolor = UNSPECIFIED_COLOR; static bool s_DC_lastbrushfill = false; static wxDC* s_DC_lastDC = NULL; +/*** + * Utility for the line clipping code, returns the boundary code of + * a point. Bit allocation is arbitrary + */ +static inline int clipOutCode( const EDA_RECT *aClipBox, int x, int y ) +{ + int code; + if( y < aClipBox->GetY() ) + code = 2; + else if( y > aClipBox->GetBottom() ) + code = 1; + else + code = 0; + if( x < aClipBox->GetX() ) + code |= 4; + else if( x > aClipBox->GetRight() ) + code |= 8; + return code; +} + /** * Test if any part of a line falls within the bounds of a rectangle. @@ -93,225 +113,68 @@ static wxDC* s_DC_lastDC = NULL; * * @return - False if any part of the line lies within the rectangle. */ -static bool clipLine( EDA_RECT* aClipBox, int& x1, int& y1, int& x2, int& y2 ) +static bool clipLine( const EDA_RECT *aClipBox, int &x1, int &y1, int &x2, int &y2 ) { - if( aClipBox->Contains( x1, y1 ) && aClipBox->Contains( x2, y2 ) ) - return false; + // Stock Cohen-Sutherland algorithm; check *any* CG book for details + int outcode1 = clipOutCode( aClipBox, x1, y1 ); + int outcode2 = clipOutCode( aClipBox, x2, y2 ); - wxRect rect = *aClipBox; - int minX = rect.GetLeft(); - int maxX = rect.GetRight(); - int minY = rect.GetTop(); - int maxY = rect.GetBottom(); - int clippedX, clippedY; - -#if DEBUG_DUMP_CLIP_COORDS - int tmpX1, tmpY1, tmpX2, tmpY2; - tmpX1 = x1; - tmpY1 = y1; - tmpX2 = x2; - tmpY2 = y2; -#endif - - if( aClipBox->Contains( x1, y1 ) ) + while( outcode1 || outcode2 ) { - if( x1 == x2 ) /* Vertical line, clip Y. */ - { - if( y2 < minY ) - { - y2 = minY; - return false; - } + // Fast reject + if( outcode1 & outcode2 ) + return true; + + // Choose a side to clip + int thisoutcode, x, y; + if( outcode1 ) + thisoutcode = outcode1; + else + thisoutcode = outcode2; - if( y2 > maxY ) - { - y2 = maxY; - return false; - } + /* One clip round + * Since we use the full range of 32 bit ints, the proportion + * computation has to be done in 64 bits to avoid horrible + * results */ + if( thisoutcode & 1 ) // Clip the bottom + { + y = aClipBox->GetBottom(); + x = x1 + (x2 - x1) * int64_t(y - y1) / (y2 - y1); + } + else if( thisoutcode & 2 ) // Clip the top + { + y = aClipBox->GetY(); + x = x1 + (x2 - x1) * int64_t(y - y1) / (y2 - y1); + } + else if( thisoutcode & 8 ) // Clip the right + { + x = aClipBox->GetRight(); + y = y1 + (y2 - y1) * int64_t(x - x1) / (x2 - x1); } - else if( y1 == y2 ) /* Horizontal line, clip X. */ + else // if( thisoutcode & 4), obviously, clip the left { - if( x2 < minX ) - { - x2 = minX; - return false; - } - - if( x2 > maxX ) - { - x2 = maxX; - return false; - } + x = aClipBox->GetX(); + y = y1 + (y2 - y1) * int64_t(x - x1) / (x2 - x1); } - /* If we're here, it's a diagonal line. */ - - if( TestForIntersectionOfStraightLineSegments( x1, y1, x2, y2, minX, minY, minX, maxY, - &clippedX, &clippedY ) /* Left */ - || TestForIntersectionOfStraightLineSegments( x1, y1, x2, y2, minX, minY, maxX, minY, - &clippedX, &clippedY ) /* Top */ - || TestForIntersectionOfStraightLineSegments( x1, y1, x2, y2, maxX, minY, maxX, maxY, - &clippedX, &clippedY ) /* Right */ - || TestForIntersectionOfStraightLineSegments( x1, y1, x2, y2, minX, maxY, maxX, maxY, - &clippedX, &clippedY ) ) /* Bottom */ + // Put the result back and update the boundary code + // No ambiguity, otherwise it would have been a fast reject + if( thisoutcode == outcode1 ) { - if( x2 != clippedX ) - x2 = clippedX; - if( y2 != clippedY ) - y2 = clippedY; - return false; + x1 = x; + y1 = y; + outcode1 = clipOutCode( aClipBox, x1, y1 ); + } + else + { + x2 = x; + y2 = y; + outcode2 = clipOutCode( aClipBox, x2, y2 ); } - - /* If we're here, something has gone terribly wrong. */ -#if DEBUG_DUMP_CLIP_ERROR_COORDS - wxLogDebug( wxT( "Line (%d,%d):(%d,%d) in rectangle (%d,%d,%d,%d) clipped to (%d,%d,%d,%d)" ), - tmpX1, tmpY1, tmpX2, tmpY2, minX, minY, maxX, maxY, x1, y1, x2, y2 ); -#endif - return false; } - else if( aClipBox->Contains( x2, y2 ) ) - { - if( x1 == x2 ) /* Vertical line, clip Y. */ - { - if( y2 < minY ) - { - y2 = minY; - return false; - } - - if( y2 > maxY ) - { - y2 = maxY; - return false; - } - } - else if( y1 == y2 ) /* Horizontal line, clip X. */ - { - if( x2 < minX ) - { - x2 = minX; - return false; - } - - if( x2 > maxX ) - { - x2 = maxX; - return false; - } - } - - if( TestForIntersectionOfStraightLineSegments( x1, y1, x2, y2, minX, minY, minX, maxY, - &clippedX, &clippedY ) /* Left */ - || TestForIntersectionOfStraightLineSegments( x1, y1, x2, y2, minX, minY, maxX, minY, - &clippedX, &clippedY ) /* Top */ - || TestForIntersectionOfStraightLineSegments( x1, y1, x2, y2, maxX, minY, maxX, maxY, - &clippedX, &clippedY ) /* Right */ - || TestForIntersectionOfStraightLineSegments( x1, y1, x2, y2, minX, maxY, maxX, maxY, - &clippedX, &clippedY ) ) /* Bottom */ - { - if( x1 != clippedX ) - x1 = clippedX; - if( y1 != clippedY ) - y1 = clippedY; - return false; - } - - /* If we're here, something has gone terribly wrong. */ -#if DEBUG_DUMP_CLIP_ERROR_COORDS - wxLogDebug( wxT( "Line (%d,%d):(%d,%d) in rectangle (%d,%d,%d,%d) clipped to (%d,%d,%d,%d)" ), - tmpX1, tmpY1, tmpX2, tmpY2, minX, minY, maxX, maxY, x1, y1, x2, y2 ); -#endif - return false; - } - else - { - int* intersectX; - int* intersectY; - int intersectX1, intersectY1, intersectX2, intersectY2; - bool haveFirstPoint = false; - - intersectX = &intersectX1; - intersectY = &intersectY1; - - /* Left clip rectangle line. */ - if( TestForIntersectionOfStraightLineSegments( x1, y1, x2, y2, minX, minY, minX, maxY, - intersectX, intersectY ) ) - { - intersectX = &intersectX2; - intersectY = &intersectY2; - haveFirstPoint = true; - } - - /* Top clip rectangle line. */ - if( TestForIntersectionOfStraightLineSegments( x1, y1, x2, y2, minX, minY, maxX, minY, - intersectX, intersectY ) ) - { - intersectX = &intersectX2; - intersectY = &intersectY2; - if( haveFirstPoint ) - { - x1 = intersectX1; - y1 = intersectY1; - x2 = intersectX2; - y2 = intersectY2; - return false; - } - haveFirstPoint = true; - } - - /* Right clip rectangle line. */ - if( TestForIntersectionOfStraightLineSegments( x1, y1, x2, y2, maxX, minY, maxX, maxY, - intersectX, intersectY ) ) - { - intersectX = &intersectX2; - intersectY = &intersectY2; - if( haveFirstPoint ) - { - x1 = intersectX1; - y1 = intersectY1; - x2 = intersectX2; - y2 = intersectY2; - return false; - } - haveFirstPoint = true; - } - - /* Bottom clip rectangle line. */ - if( TestForIntersectionOfStraightLineSegments( x1, y1, x2, y2, minX, maxY, maxX, maxY, - intersectX, intersectY ) ) - { - intersectX = &intersectX2; - intersectY = &intersectY2; - if( haveFirstPoint ) - { - x1 = intersectX1; - y1 = intersectY1; - x2 = intersectX2; - y2 = intersectY2; - return false; - } - } - - /* If we're here and only one line of the clip box has been intersected, - * something has gone terribly wrong. */ -#if DEBUG_DUMP_CLIP_ERROR_COORDS - if( haveFirstPoint ) - wxLogDebug( wxT( "Line (%d,%d):(%d,%d) in rectangle (%d,%d,%d,%d) clipped to (%d,%d,%d,%d)" ), - tmpX1, tmpY1, tmpX2, tmpY2, minX, minY, maxX, maxY, x1, y1, x2, y2 ); -#endif - } - - /* Set this to one to verify that diagonal lines get clipped properly. */ -#if DEBUG_DUMP_CLIP_COORDS - if( !( x1 == x2 || y1 == y2 ) ) - wxLogDebug( wxT( "Clipped line (%d,%d):(%d,%d) from rectangle (%d,%d,%d,%d)" ), - tmpX1, tmpY1, tmpX2, tmpY2, minX, minY, maxX, maxY ); -#endif - - return true; + return false; } - static void WinClipAndDrawLine( EDA_RECT* ClipBox, wxDC* DC, int x1, int y1, int x2, int y2, EDA_COLOR_T Color, int width = 1 ) { diff --git a/pcbnew/class_board_connected_item.cpp b/pcbnew/class_board_connected_item.cpp index eaaa3390ca..d7c54e7925 100644 --- a/pcbnew/class_board_connected_item.cpp +++ b/pcbnew/class_board_connected_item.cpp @@ -50,12 +50,6 @@ BOARD_CONNECTED_ITEM::BOARD_CONNECTED_ITEM( const BOARD_CONNECTED_ITEM& aItem ) } -int BOARD_CONNECTED_ITEM::GetNetCode() const -{ - return m_netinfo->GetNet(); -} - - void BOARD_CONNECTED_ITEM::SetNetCode( int aNetCode ) { BOARD* board = GetBoard(); @@ -75,18 +69,6 @@ void BOARD_CONNECTED_ITEM::SetNetCode( int aNetCode ) } -const wxString& BOARD_CONNECTED_ITEM::GetNetname() const -{ - return m_netinfo->GetNetname(); -} - - -const wxString& BOARD_CONNECTED_ITEM::GetShortNetname() const -{ - return m_netinfo->GetShortNetname(); -} - - int BOARD_CONNECTED_ITEM::GetClearance( BOARD_CONNECTED_ITEM* aItem ) const { NETCLASSPTR myclass = GetNetClass(); diff --git a/pcbnew/class_board_connected_item.h b/pcbnew/class_board_connected_item.h index a3972185d0..a0a4a46dfc 100644 --- a/pcbnew/class_board_connected_item.h +++ b/pcbnew/class_board_connected_item.h @@ -32,8 +32,8 @@ #define BOARD_CONNECTED_ITEM_H #include +#include -class NETINFO_ITEM; class NETCLASS; class TRACK; class D_PAD; @@ -77,7 +77,10 @@ public: * Function GetNetCode * @return int - the net code. */ - int GetNetCode() const; + int GetNetCode() const + { + return m_netinfo->GetNet(); + } /** * Function SetNetCode @@ -119,13 +122,19 @@ public: * Function GetNetname * @return wxString - the full netname */ - const wxString& GetNetname() const; + const wxString& GetNetname() const + { + return m_netinfo->GetNetname(); + } /** * Function GetShortNetname * @return wxString - the short netname */ - const wxString& GetShortNetname() const; + const wxString& GetShortNetname() const + { + return m_netinfo->GetShortNetname(); + } /** * Function GetClearance