Replaced the display line clipper with the way simpler (and faster) Cohen-Sutherland one.

A couple of trivial accessors made inline
This commit is contained in:
Lorenzo Marcantonio 2014-05-21 19:02:32 +02:00
parent f7c1372d58
commit 07877f9044
3 changed files with 82 additions and 228 deletions

View File

@ -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 )
{

View File

@ -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();

View File

@ -32,8 +32,8 @@
#define BOARD_CONNECTED_ITEM_H
#include <class_board_item.h>
#include <class_netinfo.h>
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