diff --git a/common/copy_to_clipboard.cpp b/common/copy_to_clipboard.cpp index fe9e353451..58342d53cb 100644 --- a/common/copy_to_clipboard.cpp +++ b/common/copy_to_clipboard.cpp @@ -15,9 +15,6 @@ #include "confirm.h" #include "wxstruct.h" -static const bool s_PlotBlackAndWhite = FALSE; -static const bool Print_Sheet_Ref = TRUE; - static bool DrawPage( EDA_DRAW_FRAME* aFrame ); @@ -77,11 +74,12 @@ bool DrawPage( EDA_DRAW_FRAME* aFrame ) screen->SetZoom( 1 ); - wxMetafileDC dc /*(wxT(""), DrawArea.GetWidth(), DrawArea.GetHeight())*/; + wxMetafileDC dc; EDA_Rect tmp = aFrame->DrawPanel->m_ClipBox; GRResetPenAndBrush( &dc ); - GRForceBlackPen( s_PlotBlackAndWhite ); + const bool plotBlackAndWhite = FALSE; + GRForceBlackPen( plotBlackAndWhite ); screen->m_IsPrinting = true; dc.SetUserScale( scale, scale ); ClipboardSizeX = dc.MaxX() + 10; @@ -96,7 +94,8 @@ bool DrawPage( EDA_DRAW_FRAME* aFrame ) dc.SetClippingRegion( DrawArea ); } - aFrame->PrintPage( &dc, Print_Sheet_Ref, -1, false ); + const int maskLayer = 0xFFFFFFFF; + aFrame->PrintPage( &dc, maskLayer, false ); screen->m_IsPrinting = false; aFrame->DrawPanel->m_ClipBox = tmp; wxMetafile* mf = dc.Close(); diff --git a/eeschema/class_libentry.cpp b/eeschema/class_libentry.cpp index 913fda6959..010da97ca7 100644 --- a/eeschema/class_libentry.cpp +++ b/eeschema/class_libentry.cpp @@ -959,15 +959,13 @@ bool LIB_COMPONENT::LoadFootprints( FILE* aFile, char* aLine, return true; } - -/**********************************************************************/ /* Return the component boundary box ( in user coordinates ) - * The unit aUnit, and the shape aConvert are considered. + * aUnit = unit selection = 0, or 1..n + * aConvert = 0, 1 or 2 * If aUnit == 0, unit is not used * if aConvert == 0 Convert is non used - * Invisible fields are not take in account + * Invisible fields are not taken in account **/ -/**********************************************************************/ EDA_Rect LIB_COMPONENT::GetBoundingBox( int aUnit, int aConvert ) const { EDA_Rect bBox( wxPoint( 0, 0 ), wxSize( 0, 0 ) ); @@ -991,6 +989,36 @@ EDA_Rect LIB_COMPONENT::GetBoundingBox( int aUnit, int aConvert ) const } +/* Return the component boundary box ( in user coordinates ) + * aUnit = unit selection = 0, or 1..n + * aConvert = 0, 1 or 2 + * If aUnit == 0, unit is not used + * if aConvert == 0 Convert is non used + * Fields are not take in account + **/ +EDA_Rect LIB_COMPONENT::GetBodyBoundingBox( int aUnit, int aConvert ) const +{ + EDA_Rect bBox( wxPoint( 0, 0 ), wxSize( 0, 0 ) ); + + BOOST_FOREACH( const LIB_DRAW_ITEM& item, drawings ) + { + if( ( item.m_Unit > 0 ) && ( ( m_unitCount > 1 ) && ( aUnit > 0 ) + && ( aUnit != item.m_Unit ) ) ) + continue; + + if( item.m_Convert > 0 && ( ( aConvert > 0 ) && ( aConvert != item.m_Convert ) ) ) + continue; + + if ( item.Type() == LIB_FIELD_T ) + continue; + + bBox.Merge( item.GetBoundingBox() ); + } + + return bBox; +} + + void LIB_COMPONENT::deleteAllFields() { LIB_DRAW_ITEM_LIST::iterator it; diff --git a/eeschema/class_libentry.h b/eeschema/class_libentry.h index 34ab1d8815..96a65661fc 100644 --- a/eeschema/class_libentry.h +++ b/eeschema/class_libentry.h @@ -233,8 +233,28 @@ public: wxArrayString& GetFootPrints() { return m_FootprintList; } + /** + * Function GetBoundingBox + * @return the component boundary box ( in user coordinates ) + * @param aUnit = unit selection = 0, or 1..n + * @param aConvert = 0, 1 or 2 + * If aUnit == 0, unit is not used + * if aConvert == 0 Convert is non used + * Invisible fields are not taken in account + **/ EDA_Rect GetBoundingBox( int aUnit, int aConvert ) const; + /** + * Function GetBodyBoundingBox + * @return the component boundary box ( in user coordinates ) without fields + * @param aUnit = unit selection = 0, or 1..n + * @param aConvert = 0, 1 or 2 + * If aUnit == 0, unit is not used + * if aConvert == 0 Convert is non used + * Fields are not taken in account + **/ + EDA_Rect GetBodyBoundingBox( int aUnit, int aConvert ) const; + bool SaveDateAndTime( FILE* aFile ); bool LoadDateAndTime( char* aLine ); diff --git a/eeschema/sch_component.cpp b/eeschema/sch_component.cpp index e824de0c5b..f60226c047 100644 --- a/eeschema/sch_component.cpp +++ b/eeschema/sch_component.cpp @@ -1360,10 +1360,14 @@ EDA_Rect SCH_COMPONENT::GetBodyBoundingBox() const int x0, xm, y0, ym; if( Entry == NULL ) - return EDA_Rect( wxPoint( 0, 0 ), wxSize( 0, 0 ) ); + { + if( DummyCmp == NULL ) + CreateDummyCmp(); + Entry = DummyCmp; + } /* Get the basic Boundary box */ - bBox = Entry->GetBoundingBox( m_unit, m_convert ); + bBox = Entry->GetBodyBoundingBox( m_unit, m_convert ); x0 = bBox.GetX(); xm = bBox.GetRight(); diff --git a/pcbnew/block_module_editor.cpp b/pcbnew/block_module_editor.cpp index bc8fe8778d..fdc8585d7c 100644 --- a/pcbnew/block_module_editor.cpp +++ b/pcbnew/block_module_editor.cpp @@ -667,14 +667,7 @@ int MarkItemsInBloc( MODULE* module, EDA_Rect& Rect ) switch( item->Type() ) { case TYPE_EDGE_MODULE: - pos = ( (EDGE_MODULE*) item )->m_Start; - if( Rect.Contains( pos ) ) - { - item->m_Selected = IS_SELECTED; - ItemsCount++; - } - pos = ( (EDGE_MODULE*) item )->m_End; - if( Rect.Contains( pos ) ) + if( ((EDGE_MODULE*)item )->HitTest( Rect ) ) { item->m_Selected = IS_SELECTED; ItemsCount++; diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp index bb0a2c6b84..61a573a8af 100644 --- a/pcbnew/class_drawsegment.cpp +++ b/pcbnew/class_drawsegment.cpp @@ -204,19 +204,17 @@ wxPoint DRAWSEGMENT::GetStart() const wxPoint DRAWSEGMENT::GetEnd() const { - wxPoint center; // center point of the arc - wxPoint start; // start of arc + wxPoint endPoint; // start of arc switch( m_Shape ) { case S_ARC: // rotate the starting point of the arc, given by m_End, through the // angle m_Angle to get the ending point of the arc. - center = m_Start; // center point of the arc - start = m_End; // start of arc - RotatePoint( &start.x, &start.y, center.x, center.y, -m_Angle ); - - return start; // after rotation, the end of the arc. + // m_Start is the arc centre + endPoint = m_End; // m_End = start point of arc + RotatePoint( &endPoint, m_Start, -m_Angle ); + return endPoint; // after rotation, the end of the arc. break; case S_SEGMENT: @@ -417,33 +415,25 @@ void DRAWSEGMENT::DisplayInfo( EDA_DRAW_FRAME* frame ) */ bool DRAWSEGMENT::HitTest( const wxPoint& aRefPos ) { - int ux0 = m_Start.x; - int uy0 = m_Start.y; + /* Calculate coordinates to test relative to segment origin. */ + wxPoint relPos = aRefPos - m_Start; - /* Calculate coordinates with ux0, uy0 = origin. */ - int dx = m_End.x - ux0; - int dy = m_End.y - uy0; - - int spot_cX = aRefPos.x - ux0; - int spot_cY = aRefPos.y - uy0; - - switch(m_Shape){ + switch(m_Shape) + { case S_CIRCLE: case S_ARC: - - int rayon, dist, stAngle, endAngle, mouseAngle; - - rayon = (int) hypot( (double) (dx), (double) (dy) ); - dist = (int) hypot( (double) (spot_cX), (double) (spot_cY) ); + { + int rayon = GetRadius(); + int dist = (int) hypot( (double) relPos.x, (double) relPos.y ); if( abs( rayon - dist ) <= ( m_Width / 2 ) ) { if( m_Shape == S_CIRCLE ) return true; - mouseAngle = (int) ArcTangente( spot_cY, spot_cX ); - stAngle = (int) ArcTangente( dy, dx ); - endAngle = stAngle + m_Angle; + int mouseAngle = ArcTangente( relPos.y, relPos.x ); + int stAngle = ArcTangente( m_End.y - m_Start.y, m_End.x - m_Start.x ); + int endAngle = stAngle + m_Angle; if( endAngle > 3600 ) { @@ -454,6 +444,7 @@ bool DRAWSEGMENT::HitTest( const wxPoint& aRefPos ) if( mouseAngle >= stAngle && mouseAngle <= endAngle ) return true; } + } break; case S_CURVE: @@ -464,8 +455,9 @@ bool DRAWSEGMENT::HitTest( const wxPoint& aRefPos ) return true; } break; + default: - if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) ) + if( TestSegmentHit( aRefPos, m_Start, m_End, m_Width / 2 ) ) return true; } return false; @@ -475,16 +467,33 @@ bool DRAWSEGMENT::HitTest( const wxPoint& aRefPos ) /** * Function HitTest (overlayed) * tests if the given EDA_Rect intersect this object. - * For now, an ending point must be inside this rect. + * For now, for arcs and segments, an ending point must be inside this rect. * @param refArea : the given EDA_Rect * @return bool - true if a hit, else false */ bool DRAWSEGMENT::HitTest( EDA_Rect& refArea ) { - if( refArea.Contains( m_Start ) ) - return true; - if( refArea.Contains( m_End ) ) - return true; + switch(m_Shape) + { + case S_CIRCLE: + { + int radius = GetRadius(); + // Text if area intersects the circle: + EDA_Rect area = refArea; + area.Inflate(radius); + if( area.Contains(m_Start) ) + return true; + } + break; + + case S_ARC: + case S_SEGMENT: + if( refArea.Contains( GetStart() ) ) + return true; + if( refArea.Contains( GetEnd() ) ) + return true; + break; + } return false; } diff --git a/pcbnew/class_drawsegment.h b/pcbnew/class_drawsegment.h index 6d7f398618..f91bd41a04 100644 --- a/pcbnew/class_drawsegment.h +++ b/pcbnew/class_drawsegment.h @@ -52,6 +52,17 @@ public: */ wxPoint GetEnd() const; + /** + * Function GetRadius + * returns the radius of this item + * Has meaning only for arc and circle + */ + int GetRadius() const + { + double radius = hypot( (double) (m_End.x - m_Start.x), (double) (m_End.y - m_Start.y) ); + return wxRound(radius); + } + /** * Function Save * writes the data structures for this object out to a FILE in "*.brd" format. diff --git a/pcbnew/class_edge_mod.cpp b/pcbnew/class_edge_mod.cpp index 2675444d06..34ef165a4e 100644 --- a/pcbnew/class_edge_mod.cpp +++ b/pcbnew/class_edge_mod.cpp @@ -26,7 +26,6 @@ EDGE_MODULE::EDGE_MODULE( MODULE* parent ) : BOARD_ITEM( parent, TYPE_EDGE_MODULE ) { - m_Width = 0; m_Shape = S_SEGMENT; m_Angle = 0; m_Width = 120; @@ -77,16 +76,12 @@ EDA_Rect EDGE_MODULE::GetBoundingBox() const break; case S_CIRCLE: - { - int rayon = (int) hypot( (double) (m_End.x - m_Start.x), (double) (m_End.y - m_Start.y) ); - bbox.Inflate( rayon + 1 ); - } - break; + bbox.Inflate( GetRadius() + 1 ); + break; case S_ARC: { - int rayon = (int) hypot( (double) (m_End.x - m_Start.x), (double) (m_End.y - m_Start.y) ); - bbox.Inflate( rayon + 1 ); + bbox.Inflate( GetRadius() + 1 ); } break; @@ -489,6 +484,42 @@ int EDGE_MODULE::ReadDescr( LINE_READER* aReader ) } +wxPoint EDGE_MODULE::GetStart() const +{ + switch( m_Shape ) + { + case S_ARC: + return m_End; // the start of the arc is held in field m_End, center point is in m_Start. + + case S_SEGMENT: + default: + return m_Start; + } +} + + +wxPoint EDGE_MODULE::GetEnd() const +{ + wxPoint endPoint; // start of arc + + switch( m_Shape ) + { + case S_ARC: + // rotate the starting point of the arc, given by m_End, through the + // angle m_Angle to get the ending point of the arc. + // m_Start is the arc centre + endPoint = m_End; // m_End = start point of arc + RotatePoint( &endPoint, m_Start, -m_Angle ); + return endPoint; // after rotation, the end of the arc. + break; + + case S_SEGMENT: + default: + return m_End; + } +} + + /** * Function HitTest * tests if the given wxPoint is within the bounds of this object. @@ -497,47 +528,31 @@ int EDGE_MODULE::ReadDescr( LINE_READER* aReader ) */ bool EDGE_MODULE::HitTest( const wxPoint& refPos ) { - int uxf, uyf; int rayon, dist; - int dx, dy, spot_cX, spot_cY; - int ux0, uy0; - - ux0 = m_Start.x; - uy0 = m_Start.y; - - uxf = m_End.x; - uyf = m_End.y; switch( m_Shape ) { case S_SEGMENT: - spot_cX = refPos.x - ux0; - spot_cY = refPos.y - uy0; - - dx = uxf - ux0; - dy = uyf - uy0; - if( DistanceTest( m_Width / 2, dx, dy, spot_cX, spot_cY ) ) + if( TestSegmentHit( refPos, m_Start, m_End, m_Width / 2 ) ) return true; break; case S_CIRCLE: - rayon = (int) hypot( (double) (uxf - ux0), (double) (uyf - uy0) ); - dist = (int) hypot( (double) (refPos.x - ux0), - (double) (refPos.y - uy0) ); - if( abs( rayon - dist ) <= m_Width ) + rayon = GetRadius(); + dist = (int) hypot( (double) (refPos.x - m_Start.x), (double) (refPos.y - m_Start.y) ); + if( abs( rayon - dist ) <= (m_Width/2) ) return true; break; case S_ARC: - rayon = (int) hypot( (double) (uxf - ux0), (double) (uyf - uy0) ); - dist = (int) hypot( (double) (refPos.x - ux0), - (double) (refPos.y - uy0) ); + rayon = GetRadius(); + dist = (int) hypot( (double) (refPos.x - m_Start.x), (double) (refPos.y - m_Start.y) ); - if( abs( rayon - dist ) > m_Width ) + if( abs( rayon - dist ) > (m_Width/2) ) break; - int mouseAngle = (int) ArcTangente( refPos.y - uy0, refPos.x - ux0 ); - int stAngle = (int) ArcTangente( uyf - uy0, uxf - ux0 ); + int mouseAngle = ArcTangente( refPos.y - m_Start.y, refPos.x - m_Start.x ); + int stAngle = ArcTangente( m_End.y - m_Start.y, m_End.x - m_Start.x ); int endAngle = stAngle + m_Angle; if( endAngle > 3600 ) @@ -556,6 +571,39 @@ bool EDGE_MODULE::HitTest( const wxPoint& refPos ) } +/** + * Function HitTest (overlayed) + * tests if the given EDA_Rect intersect this object. + * For now, for arcs and segments, an ending point must be inside this rect. + * @param refArea : the given EDA_Rect + * @return bool - true if a hit, else false + */ +bool EDGE_MODULE::HitTest( EDA_Rect& refArea ) +{ + switch(m_Shape) + { + case S_CIRCLE: + { + int radius = GetRadius(); + // Test if area intersects the circle: + EDA_Rect area = refArea; + area.Inflate(radius); + if( area.Contains(m_Start) ) + return true; + } + break; + + case S_ARC: + case S_SEGMENT: + if( refArea.Contains( GetStart() ) ) + return true; + if( refArea.Contains( GetEnd() ) ) + return true; + break; + } + return false; +} + #if defined(DEBUG) diff --git a/pcbnew/class_edge_mod.h b/pcbnew/class_edge_mod.h index 1d4226e7a3..3edf869a00 100644 --- a/pcbnew/class_edge_mod.h +++ b/pcbnew/class_edge_mod.h @@ -11,8 +11,8 @@ class EDGE_MODULE : public BOARD_ITEM { public: int m_Width; // 0 = line, > 0 = tracks, bus ... - wxPoint m_Start; // Line start point / circle and arc center - wxPoint m_End; // Line end point / circle and arc starting point + wxPoint m_Start; // Line start point and circle and arc center + wxPoint m_End; // Line end point and circle and arc starting point int m_Shape; // enum Track_Shapes wxPoint m_Start0; // Start point or centre, relative to module origin, orient 0. @@ -44,6 +44,28 @@ public: return m_Start; } + /** + * Function GetStart + * returns the starting point of the graphic + */ + wxPoint GetStart() const; + + /** + * Function GetEnd + * returns the ending point of the graphic + */ + wxPoint GetEnd() const; + + /** + * Function GetRadius + * returns the radius of this item + * Has meaning only for arc and circle + */ + int GetRadius() const + { + double radius = hypot( (double) (m_End.x - m_Start.x), (double) (m_End.y - m_Start.y) ); + return wxRound(radius); + } void Copy( EDGE_MODULE* source ); // copy structure @@ -92,6 +114,15 @@ public: */ bool HitTest( const wxPoint& refPos ); + /** + * Function HitTest (overlayed) + * tests if the given EDA_Rect intersect this object. + * For now, for segments and arcs, an ending point must be inside this rect. + * @param refArea the given EDA_Rect to test + * @return bool - true if a hit, else false + */ + bool HitTest( EDA_Rect& refArea ); + /** * Function GetClass * returns the class name.