From f135ec47fa46938a6a65cf21cb89d012501d7baf Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Thu, 13 Jun 2019 13:23:39 +0200 Subject: [PATCH] Page layout: rework and fix a few issues. * rename WS_DRAW_ITEM_POLYGON to WS_DRAW_ITEM_POLYPOLYGONS (better name) * use SHAPE_POLY_SET instead of std::vector( to manage the set of polygons. It also remove duplicate code related to HitTest and bounding box. * fix HitTest and WS_DRAW_ITEM_POLYGON highlight. --- common/page_layout/ws_data_item.cpp | 31 +++++---- common/page_layout/ws_draw_item.cpp | 78 ++++++++++++----------- common/page_layout/ws_painter.cpp | 30 +++------ common/plotters/common_plot_functions.cpp | 17 ++++- include/ws_data_item.h | 6 +- include/ws_draw_item.h | 20 +++--- include/ws_painter.h | 2 +- 7 files changed, 96 insertions(+), 88 deletions(-) diff --git a/common/page_layout/ws_data_item.cpp b/common/page_layout/ws_data_item.cpp index 1f064b61fe..fe3f32d291 100644 --- a/common/page_layout/ws_data_item.cpp +++ b/common/page_layout/ws_data_item.cpp @@ -422,27 +422,30 @@ void WS_DATA_ITEM_POLYGONS::SyncDrawItems( WS_DRAW_ITEM_LIST* aCollector, KIGFX: if( j && !IsInsidePage( j ) ) continue; + int pensize = GetPenSizeUi(); + auto poly_shape = new WS_DRAW_ITEM_POLYPOLYGONS( this, j, GetStartPosUi( j ), pensize ); + poly_shape->SetFlags( itemFlags[ j ] ); + m_drawItems.push_back( poly_shape ); + + // Transfer all outlines (basic polygons) + SHAPE_POLY_SET& polygons = poly_shape->GetPolygons(); for( int kk = 0; kk < GetPolyCount(); kk++ ) { - const bool fill = true; - int pensize = GetPenSizeUi(); - auto poly = new WS_DRAW_ITEM_POLYGON( this, j, GetStartPosUi( j ), fill, pensize ); - poly->SetFlags( itemFlags[ j ] ); - m_drawItems.push_back( poly ); - - if( aCollector ) - aCollector->Append( poly ); - - if( aView ) - aView->Add( poly ); - - // Create polygon outline + // Create new outline unsigned ist = GetPolyIndexStart( kk ); unsigned iend = GetPolyIndexEnd( kk ); + polygons.NewOutline(); + while( ist <= iend ) - poly->m_Corners.push_back( GetCornerPositionUi( ist++, j ) ); + polygons.Append( GetCornerPositionUi( ist++, j ) ); } + + if( aCollector ) + aCollector->Append( poly_shape ); + + if( aView ) + aView->Add( poly_shape ); } } diff --git a/common/page_layout/ws_draw_item.cpp b/common/page_layout/ws_draw_item.cpp index d6b12c3fd1..71c5925d5a 100644 --- a/common/page_layout/ws_draw_item.cpp +++ b/common/page_layout/ws_draw_item.cpp @@ -188,54 +188,48 @@ wxString WS_DRAW_ITEM_TEXT::GetSelectMenuText( EDA_UNITS_T aUnits ) const } -// ============================ POLYGON ============================== +// ============================ POLYGON -void WS_DRAW_ITEM_POLYGON::PrintWsItem( wxDC* aDC, const wxPoint& aOffset, COLOR4D aColor ) +void WS_DRAW_ITEM_POLYPOLYGONS::PrintWsItem( wxDC* aDC, const wxPoint& aOffset, COLOR4D aColor ) { std::vector points_moved; - wxPoint *points; - if( aOffset.x || aOffset.y ) + for( int idx = 0; idx < m_Polygons.OutlineCount(); ++idx ) { - for( auto point: m_Corners ) - points_moved.push_back( point + aOffset ); + points_moved.clear(); + SHAPE_LINE_CHAIN& outline = m_Polygons.Outline( idx ); - points = &points_moved[0]; - } - else - { - points = &m_Corners[0]; - } + for( int ii = 0; ii < outline.PointCount(); ii++ ) + points_moved.push_back( wxPoint( outline.Point( ii ).x + aOffset.x, + outline.Point( ii ).y + aOffset.y ) ); - GRPoly( nullptr, aDC, m_Corners.size(), points, IsFilled() ? FILLED_SHAPE : NO_FILL, - GetPenWidth(), aColor, aColor ); + GRPoly( nullptr, aDC, points_moved.size(), &points_moved[0], FILLED_SHAPE, + GetPenWidth(), aColor, aColor ); + } } -const EDA_RECT WS_DRAW_ITEM_POLYGON::GetBoundingBox() const +const EDA_RECT WS_DRAW_ITEM_POLYPOLYGONS::GetBoundingBox() const { - EDA_RECT rect( GetPosition(), wxSize( 0, 0 ) ); - - for( wxPoint corner : m_Corners ) - rect.Merge( corner ); + EDA_RECT rect; + BOX2I box = m_Polygons.BBox(); + rect.SetX( box.GetX() ); + rect.SetY( box.GetY() ); + rect.SetWidth( box.GetWidth() ); + rect.SetHeight( box.GetHeight() ); +printf("bbox %f %f %f %f\n",box.GetX()/1e3,box.GetY()/1e3,box.GetWidth()/1e3,box.GetHeight()/1e3);fflush(0); return rect; } -bool WS_DRAW_ITEM_POLYGON::HitTest( const wxPoint& aPosition, int aAccuracy ) const +bool WS_DRAW_ITEM_POLYPOLYGONS::HitTest( const wxPoint& aPosition, int aAccuracy ) const { - for( unsigned ii = 1; ii < m_Corners.size(); ii++ ) - { - if( TestSegmentHit( aPosition, m_Corners[ii - 1], m_Corners[ii], aAccuracy ) ) - return true; - } - - return false; + return m_Polygons.Contains( aPosition ); } -bool WS_DRAW_ITEM_POLYGON::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const +bool WS_DRAW_ITEM_POLYPOLYGONS::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const { EDA_RECT sel = aRect; @@ -249,24 +243,32 @@ bool WS_DRAW_ITEM_POLYGON::HitTest( const EDA_RECT& aRect, bool aContained, int if( !sel.Intersects( GetBoundingBox() ) ) return false; - int count = m_Corners.size(); - - for( int ii = 0; ii < count; ii++ ) + for( int idx = 0; idx < m_Polygons.OutlineCount(); ++idx ) { - // Test if the point is within aRect - if( sel.Contains( m_Corners[ ii ] ) ) - return true; + const SHAPE_LINE_CHAIN& outline = m_Polygons.COutline( idx ); - // Test if this edge intersects aRect - if( sel.Intersects( m_Corners[ ii ], m_Corners[ (ii+1) % count ] ) ) - return true; + for( int ii = 0; ii < outline.PointCount(); ii++ ) + { + wxPoint corner( outline.CPoint( ii ).x, outline.CPoint( ii ).y ); + + // Test if the point is within aRect + if( sel.Contains( corner ) ) + return true; + + // Test if this edge intersects aRect + int ii_next = (ii+1) % outline.PointCount(); + wxPoint next_corner( outline.CPoint( ii_next ).x, outline.CPoint( ii_next ).y ); + + if( sel.Intersects( corner, next_corner ) ) + return true; + } } return false; } -wxString WS_DRAW_ITEM_POLYGON::GetSelectMenuText( EDA_UNITS_T aUnits ) const +wxString WS_DRAW_ITEM_POLYPOLYGONS::GetSelectMenuText( EDA_UNITS_T aUnits ) const { return wxString::Format( _( "Imported shape at (%s, %s)" ), MessageTextFromValue( aUnits, GetPosition().x ), diff --git a/common/page_layout/ws_painter.cpp b/common/page_layout/ws_painter.cpp index da7158589b..c16e7f6db5 100644 --- a/common/page_layout/ws_painter.cpp +++ b/common/page_layout/ws_painter.cpp @@ -243,7 +243,7 @@ bool KIGFX::WS_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer ) switch( item->Type() ) { case WSG_LINE_T: draw( (WS_DRAW_ITEM_LINE*) item, aLayer ); break; - case WSG_POLY_T: draw( (WS_DRAW_ITEM_POLYGON*) item, aLayer ); break; + case WSG_POLY_T: draw( (WS_DRAW_ITEM_POLYPOLYGONS*) item, aLayer ); break; case WSG_RECT_T: draw( (WS_DRAW_ITEM_RECT*) item, aLayer ); break; case WSG_TEXT_T: draw( (WS_DRAW_ITEM_TEXT*) item, aLayer ); break; case WSG_BITMAP_T: draw( (WS_DRAW_ITEM_BITMAP*) item, aLayer ); break; @@ -275,28 +275,18 @@ void KIGFX::WS_PAINTER::draw( const WS_DRAW_ITEM_RECT* aItem, int aLayer ) const } -void KIGFX::WS_PAINTER::draw( const WS_DRAW_ITEM_POLYGON* aItem, int aLayer ) const +void KIGFX::WS_PAINTER::draw( const WS_DRAW_ITEM_POLYPOLYGONS* aItem, int aLayer ) const { - std::deque corners; - for( wxPoint point : aItem->m_Corners ) - { - corners.push_back( VECTOR2D( point ) ); - } + m_gal->SetFillColor( m_renderSettings.GetColor( aItem, aLayer ) ); + m_gal->SetIsFill( true ); + m_gal->SetIsStroke( false ); - if( aItem->IsFilled() ) + WS_DRAW_ITEM_POLYPOLYGONS* item = (WS_DRAW_ITEM_POLYPOLYGONS*)aItem; + + for( int idx = 0; idx < item->GetPolygons().OutlineCount(); ++idx ) { - m_gal->SetFillColor( m_renderSettings.GetColor( aItem, aLayer ) ); - m_gal->SetIsFill( true ); - m_gal->SetIsStroke( false ); - m_gal->DrawPolygon( corners ); - } - else - { - m_gal->SetStrokeColor( m_renderSettings.GetColor( aItem, aLayer ) ); - m_gal->SetIsFill( false ); - m_gal->SetIsStroke( true ); - m_gal->SetLineWidth( aItem->GetPenWidth() ); - m_gal->DrawPolyline( corners ); + SHAPE_LINE_CHAIN& outline = item->GetPolygons().Outline( idx ); + m_gal->DrawPolygon( outline ); } } diff --git a/common/plotters/common_plot_functions.cpp b/common/plotters/common_plot_functions.cpp index 6b480e40a8..14b984f28b 100644 --- a/common/plotters/common_plot_functions.cpp +++ b/common/plotters/common_plot_functions.cpp @@ -117,9 +117,20 @@ void PlotWorkSheet( PLOTTER* plotter, const TITLE_BLOCK& aTitleBlock, case WSG_POLY_T: { - WS_DRAW_ITEM_POLYGON* poly = (WS_DRAW_ITEM_POLYGON*) item; - plotter->PlotPoly( poly->m_Corners, poly->IsFilled() ? FILLED_SHAPE : NO_FILL, - poly->GetPenWidth() ); + WS_DRAW_ITEM_POLYPOLYGONS* poly = (WS_DRAW_ITEM_POLYPOLYGONS*) item; + std::vector points; + + for( int idx = 0; idx < poly->GetPolygons().OutlineCount(); ++idx ) + { + points.clear(); + SHAPE_LINE_CHAIN& outline = poly->GetPolygons().Outline( idx ); + + for( int ii = 0; ii < outline.PointCount(); ii++ ) + points.push_back( wxPoint( outline.Point( ii ).x , + outline.Point( ii ).y ) ); + + plotter->PlotPoly( points, FILLED_SHAPE, poly->GetPenWidth() ); + } } break; diff --git a/include/ws_data_item.h b/include/ws_data_item.h index 763da6e7d4..0f00218e0d 100644 --- a/include/ws_data_item.h +++ b/include/ws_data_item.h @@ -1,8 +1,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2013-2014 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 1992-2014 KiCad Developers, see CHANGELOG.TXT for contributors. + * Copyright (C) 2013-2019 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -215,7 +215,7 @@ public: class WS_DATA_ITEM_POLYGONS : public WS_DATA_ITEM { public: - double m_Orient; // Orientation in degrees + double m_Orient; // Orientation in degrees std::vector m_Corners; // corner list private: diff --git a/include/ws_draw_item.h b/include/ws_draw_item.h index b6c082295c..4795a98c4b 100644 --- a/include/ws_draw_item.h +++ b/include/ws_draw_item.h @@ -30,6 +30,7 @@ #include #include #include "msgpanel.h" +#include class WS_DATA_ITEM; class TITLE_BLOCK; @@ -139,32 +140,32 @@ public: }; // This class draws a polygon -class WS_DRAW_ITEM_POLYGON : public WS_DRAW_ITEM_BASE +class WS_DRAW_ITEM_POLYPOLYGONS : public WS_DRAW_ITEM_BASE { wxPoint m_pos; // position of reference point, from the // WS_DATA_ITEM_POLYGONS parent // (used only in page layout editor to draw anchors) int m_penWidth; - bool m_fill; public: - std::vector m_Corners; + /** The list of polygons. Because these polygons are only for drawing purposes, + * each polygon is expected having no holes, jusst a main outline + */ + SHAPE_POLY_SET m_Polygons; public: - WS_DRAW_ITEM_POLYGON( WS_DATA_ITEM* aPeer, int aIndex, wxPoint aPos, bool aFill, - int aPenWidth ) : + WS_DRAW_ITEM_POLYPOLYGONS( WS_DATA_ITEM* aPeer, int aIndex, wxPoint aPos, int aPenWidth ) : WS_DRAW_ITEM_BASE( aPeer, aIndex, WSG_POLY_T ) { m_penWidth = aPenWidth; - m_fill = aFill; m_pos = aPos; } - virtual wxString GetClass() const override { return wxT( "WS_DRAW_ITEM_POLYGON" ); } + virtual wxString GetClass() const override { return wxT( "WS_DRAW_ITEM_POLYPOLYGONS" ); } // Accessors: + SHAPE_POLY_SET& GetPolygons() { return m_Polygons; } int GetPenWidth() const { return m_penWidth; } - bool IsFilled() const { return m_fill; } const wxPoint GetPosition() const override { return m_pos; } void SetPosition( wxPoint aPos ) override { m_pos = aPos; } @@ -224,7 +225,8 @@ public: // This class draws a rectangle with thick segment showing the page limits -// and a marker showing the coord origin +// and a marker showing the coord origin. This only a draw item only. +// Therefore m_peer ( the parent WS_DATA_ITEM item in the WS_DATA_MODEL) is always a nullptr. class WS_DRAW_ITEM_PAGE : public WS_DRAW_ITEM_BASE { wxPoint m_markerPos; // position of the marker diff --git a/include/ws_painter.h b/include/ws_painter.h index 369c599a00..cec964f1e7 100644 --- a/include/ws_painter.h +++ b/include/ws_painter.h @@ -116,7 +116,7 @@ public: private: void draw( const WS_DRAW_ITEM_LINE* aItem, int aLayer ) const; void draw( const WS_DRAW_ITEM_RECT* aItem, int aLayer ) const; - void draw( const WS_DRAW_ITEM_POLYGON* aItem, int aLayer ) const; + void draw( const WS_DRAW_ITEM_POLYPOLYGONS* aItem, int aLayer ) const; void draw( const WS_DRAW_ITEM_TEXT* aItem, int aLayer ) const; void draw( const WS_DRAW_ITEM_BITMAP* aItem, int aLayer ) const; void draw( const WS_DRAW_ITEM_PAGE* aItem, int aLayer ) const;