const EDA_RECT GERBER_DRAW_ITEM::GetBoundingBox() const { // return a rectangle which is (pos,dim) in nature. therefore the +1 EDA_RECT bbox( m_Start, wxSize( 1, 1 ) ); bbox.Inflate( m_Size.x / 2, m_Size.y / 2 ); bbox.SetOrigin( GetABPosition( bbox.GetOrigin() ) ); bbox.SetEnd( GetABPosition( bbox.GetEnd() ) ); return bbox; }
bool GERBER_DRAW_ITEM::HitTest( const EDA_RECT& aRefArea ) const { wxPoint pos = GetABPosition( m_Start ); if( aRefArea.Contains( pos ) ) return true; pos = GetABPosition( m_End ); if( aRefArea.Contains( pos ) ) return true; return false; }
const EDA_RECT GERBER_DRAW_ITEM::GetBoundingBox() const { // return a rectangle which is (pos,dim) in nature. therefore the +1 EDA_RECT bbox( m_Start, wxSize( 1, 1 ) ); bbox.Inflate( m_Size.x / 2, m_Size.y / 2 ); // calculate the corners coordinates in current gerber axis orientations wxPoint org = GetABPosition( bbox.GetOrigin() ); wxPoint end = GetABPosition( bbox.GetEnd() ); // Set the corners position: bbox.SetOrigin( org ); bbox.SetEnd( end ); bbox.Normalize(); return bbox; }
bool GERBER_DRAW_ITEM::GetTextD_CodePrms( int& aSize, wxPoint& aPos, double& aOrientation ) { // calculate the best size and orientation of the D_Code text if( m_DCode <= 0 ) return false; // No D_Code for this item if( m_Flashed || m_Shape == GBR_ARC ) { aPos = m_Start; } else // it is a line: { aPos = ( m_Start + m_End) / 2; } aPos = GetABPosition( aPos ); int size; // the best size for the text if( GetDcodeDescr() ) size = GetDcodeDescr()->GetShapeDim( this ); else size = std::min( m_Size.x, m_Size.y ); aOrientation = TEXT_ANGLE_HORIZ; if( m_Flashed ) { // A reasonable size for text is min_dim/3 because most of time this text has 3 chars. aSize = size / 3; } else // this item is a line { wxPoint delta = m_Start - m_End; aOrientation = RAD2DECIDEG( atan2( (double)delta.y, (double)delta.x ) ); NORMALIZE_ANGLE_90( aOrientation ); // A reasonable size for text is size/2 because text needs margin below and above it. // a margin = size/4 seems good, expecting the line len is large enough to show 3 chars, // that is the case most of time. aSize = size / 2; } return true; }
void GERBER_DRAW_ITEM::DrawGbrPoly( EDA_RECT* aClipBox, wxDC* aDC, EDA_COLOR_T aColor, const wxPoint& aOffset, bool aFilledShape ) { std::vector<wxPoint> points; points = m_PolyCorners; for( unsigned ii = 0; ii < points.size(); ii++ ) { points[ii] += aOffset; points[ii] = GetABPosition( points[ii] ); } GRClosedPoly( aClipBox, aDC, points.size(), &points[0], aFilledShape, aColor, aColor ); }
void GERBER_DRAW_ITEM::DrawGbrPoly( EDA_RECT* aClipBox, wxDC* aDC, COLOR4D aColor, const wxPoint& aOffset, bool aFilledShape ) { std::vector<wxPoint> points; SHAPE_LINE_CHAIN& poly = m_Polygon.Outline( 0 ); int pointCount = poly.PointCount() - 1; points.reserve( pointCount ); for( int ii = 0; ii < pointCount; ii++ ) { wxPoint p( poly.Point( ii ).x, poly.Point( ii ).y ); points[ii] = p + aOffset; points[ii] = GetABPosition( points[ii] ); } GRClosedPoly( aClipBox, aDC, pointCount, &points[0], aFilledShape, aColor, aColor ); }
void GERBER_DRAW_ITEM::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode, const wxPoint& aOffset, GBR_DISPLAY_OPTIONS* aDrawOptions ) { // used when a D_CODE is not found. default D_CODE to draw a flashed item static D_CODE dummyD_CODE( 0 ); bool isFilled; int radius; int halfPenWidth; static bool show_err; D_CODE* d_codeDescr = GetDcodeDescr(); if( d_codeDescr == NULL ) d_codeDescr = &dummyD_CODE; COLOR4D color = m_GerberImageFile->GetPositiveDrawColor(); if( ( aDrawMode & GR_HIGHLIGHT ) && !( aDrawMode & GR_AND ) ) color.SetToLegacyHighlightColor(); /* isDark is true if flash is positive and should use a drawing * color other than the background color, else use the background color * when drawing so that an erasure happens. */ bool isDark = !(m_LayerNegative ^ m_GerberImageFile->m_ImageNegative); if( !isDark ) { // draw in background color ("negative" color) color = aDrawOptions->m_NegativeDrawColor; } GRSetDrawMode( aDC, aDrawMode ); isFilled = aDrawOptions->m_DisplayLinesFill; switch( m_Shape ) { case GBR_POLYGON: isFilled = aDrawOptions->m_DisplayPolygonsFill; if( !isDark ) isFilled = true; DrawGbrPoly( aPanel->GetClipBox(), aDC, color, aOffset, isFilled ); break; case GBR_CIRCLE: radius = KiROUND( GetLineLength( m_Start, m_End ) ); halfPenWidth = m_Size.x >> 1; if( !isFilled ) { // draw the border of the pen's path using two circles, each as narrow as possible GRCircle( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ), radius - halfPenWidth, 0, color ); GRCircle( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ), radius + halfPenWidth, 0, color ); } else // Filled mode { GRCircle( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ), radius, m_Size.x, color ); } break; case GBR_ARC: // Currently, arcs plotted with a rectangular aperture are not supported. // a round pen only is expected. #if 0 // for arc debug only GRLine( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ), GetABPosition( m_ArcCentre ), 0, color ); GRLine( aPanel->GetClipBox(), aDC, GetABPosition( m_End ), GetABPosition( m_ArcCentre ), 0, color ); #endif if( !isFilled ) { GRArc1( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ), GetABPosition( m_End ), GetABPosition( m_ArcCentre ), 0, color ); } else { GRArc1( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ), GetABPosition( m_End ), GetABPosition( m_ArcCentre ), m_Size.x, color ); } break; case GBR_SPOT_CIRCLE: case GBR_SPOT_RECT: case GBR_SPOT_OVAL: case GBR_SPOT_POLY: case GBR_SPOT_MACRO: isFilled = aDrawOptions->m_DisplayFlashedItemsFill; d_codeDescr->DrawFlashedShape( this, aPanel->GetClipBox(), aDC, color, m_Start, isFilled ); break; case GBR_SEGMENT: /* Plot a line from m_Start to m_End. * Usually, a round pen is used, but some gerber files use a rectangular pen * In fact, any aperture can be used to plot a line. * currently: only a square pen is handled (I believe using a polygon gives a strange plot). */ if( d_codeDescr->m_Shape == APT_RECT ) { if( m_Polygon.OutlineCount() == 0 ) ConvertSegmentToPolygon(); DrawGbrPoly( aPanel->GetClipBox(), aDC, color, aOffset, isFilled ); } else { if( !isFilled ) { GRCSegm( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ), GetABPosition( m_End ), m_Size.x, color ); } else { GRFilledSegment( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ), GetABPosition( m_End ), m_Size.x, color ); } } break; default: if( !show_err ) { wxMessageBox( wxT( "Trace_Segment() type error" ) ); show_err = true; } break; } }
const EDA_RECT GERBER_DRAW_ITEM::GetBoundingBox() const { // return a rectangle which is (pos,dim) in nature. therefore the +1 EDA_RECT bbox( m_Start, wxSize( 1, 1 ) ); D_CODE* code = GetDcodeDescr(); // TODO(JE) GERBER_DRAW_ITEM maybe should actually be a number of subclasses. // Until/unless that is changed, we need to do different things depending on // what is actually being represented by this GERBER_DRAW_ITEM. switch( m_Shape ) { case GBR_POLYGON: { auto bb = m_Polygon.BBox(); bbox.Inflate( bb.GetWidth() / 2, bb.GetHeight() / 2 ); bbox.SetOrigin( bb.GetOrigin().x, bb.GetOrigin().y ); break; } case GBR_CIRCLE: { double radius = GetLineLength( m_Start, m_End ); bbox.Inflate( radius, radius ); break; } case GBR_ARC: { // Note: using a larger-than-necessary BB to simplify computation double radius = GetLineLength( m_Start, m_ArcCentre ); bbox.Move( m_ArcCentre - m_Start ); bbox.Inflate( radius + m_Size.x, radius + m_Size.x ); break; } case GBR_SPOT_CIRCLE: { if( code ) { int radius = code->m_Size.x >> 1; bbox.Inflate( radius, radius ); } break; } case GBR_SPOT_RECT: { if( code ) bbox.Inflate( code->m_Size.x / 2, code->m_Size.y / 2 ); break; } case GBR_SPOT_OVAL: { if( code ) bbox.Inflate( code->m_Size.x, code->m_Size.y ); break; } case GBR_SPOT_POLY: { if( code ) { if( code->m_Polygon.OutlineCount() == 0 ) code->ConvertShapeToPolygon(); bbox.Inflate( code->m_Polygon.BBox().GetWidth() / 2, code->m_Polygon.BBox().GetHeight() / 2 ); } break; } case GBR_SPOT_MACRO: { if( code ) { // Update the shape drawings and the bounding box coordiantes: code->GetMacro()->GetApertureMacroShape( this, m_Start ); // now the bounding box is valid: bbox = code->GetMacro()->GetBoundingBox(); } break; } case GBR_SEGMENT: { if( code && code->m_Shape == APT_RECT ) { if( m_Polygon.OutlineCount() > 0 ) { auto bb = m_Polygon.BBox(); bbox.Inflate( bb.GetWidth() / 2, bb.GetHeight() / 2 ); bbox.SetOrigin( bb.GetOrigin().x, bb.GetOrigin().y ); } } else { int radius = ( m_Size.x + 1 ) / 2; int ymax = std::max( m_Start.y, m_End.y ) + radius; int xmax = std::max( m_Start.x, m_End.x ) + radius; int ymin = std::min( m_Start.y, m_End.y ) - radius; int xmin = std::min( m_Start.x, m_End.x ) - radius; bbox = EDA_RECT( wxPoint( xmin, ymin ), wxSize( xmax - xmin + 1, ymax - ymin + 1 ) ); } break; } default: wxASSERT_MSG( false, wxT( "GERBER_DRAW_ITEM shape is unknown!" ) ); break; } // calculate the corners coordinates in current gerber axis orientations wxPoint org = GetABPosition( bbox.GetOrigin() ); wxPoint end = GetABPosition( bbox.GetEnd() ); // Set the corners position: bbox.SetOrigin( org ); bbox.SetEnd( end ); bbox.Normalize(); return bbox; }