diff --git a/pcbnew/drc/drc_engine.cpp b/pcbnew/drc/drc_engine.cpp index 127d6d7e8e..3fbe9853e0 100644 --- a/pcbnew/drc/drc_engine.cpp +++ b/pcbnew/drc/drc_engine.cpp @@ -1103,20 +1103,6 @@ DRC_CONSTRAINT DRC_ENGINE::GetWorstGlobalConstraint( DRC_CONSTRAINT_T ruleID ) #endif -std::vector DRC_ENGINE::QueryConstraintsById( DRC_CONSTRAINT_T constraintID ) -{ - std::vector rv; - - if( m_constraintMap.count( constraintID ) ) - { - for ( DRC_ENGINE_CONSTRAINT* c : *m_constraintMap[constraintID] ) - rv.push_back( c->constraint ); - } - - return rv; -} - - bool DRC_ENGINE::HasRulesForConstraintType( DRC_CONSTRAINT_T constraintID ) { //drc_dbg(10,"hascorrect id %d size %d\n", ruleID, m_ruleMap[ruleID]->sortedRules.size( ) ); @@ -1131,16 +1117,16 @@ bool DRC_ENGINE::QueryWorstConstraint( DRC_CONSTRAINT_T aConstraintId, DRC_CONST { int worst = 0; - for( const DRC_CONSTRAINT& constraint : QueryConstraintsById( aConstraintId ) ) + if( m_constraintMap.count( aConstraintId ) ) { - if( constraint.GetValue().HasMin() ) + for( DRC_ENGINE_CONSTRAINT* c : *m_constraintMap[aConstraintId] ) { - int current = constraint.GetValue().Min(); + int current = c->constraint.GetValue().Min(); if( current > worst ) { worst = current; - aConstraint = constraint; + aConstraint = c->constraint; } } } diff --git a/pcbnew/drc/drc_engine.h b/pcbnew/drc/drc_engine.h index fe0621ecc4..8d828fad19 100644 --- a/pcbnew/drc/drc_engine.h +++ b/pcbnew/drc/drc_engine.h @@ -145,8 +145,6 @@ public: PCB_LAYER_ID aLayer = UNDEFINED_LAYER, REPORTER* aReporter = nullptr ); - std::vector QueryConstraintsById( DRC_CONSTRAINT_T ruleID ); - bool HasRulesForConstraintType( DRC_CONSTRAINT_T constraintID ); EDA_UNITS UserUnits() const { return m_userUnits; } diff --git a/pcbnew/pad.cpp b/pcbnew/pad.cpp index 7244abbb4d..6bafdce8fc 100644 --- a/pcbnew/pad.cpp +++ b/pcbnew/pad.cpp @@ -86,7 +86,7 @@ PAD::PAD( FOOTPRINT* parent ) : SetSubRatsnest( 0 ); // used in ratsnest calculations - m_shapesDirty = true; + SetDirty(); m_effectiveBoundingRadius = 0; m_removeUnconnectedLayer = false; m_keepTopBottomLayer = true; @@ -262,7 +262,7 @@ void PAD::SetRoundRectRadiusRatio( double aRadiusScale ) { m_roundedCornerScale = std::max( 0.0, std::min( aRadiusScale, 0.5 ) ); - m_shapesDirty = true; + SetDirty(); } @@ -270,14 +270,14 @@ void PAD::SetChamferRectRatio( double aChamferScale ) { m_chamferScale = std::max( 0.0, std::min( aChamferScale, 0.5 ) ); - m_shapesDirty = true; + SetDirty(); } -const std::shared_ptr& PAD::GetEffectivePolygon( PCB_LAYER_ID aLayer ) const +const std::shared_ptr& PAD::GetEffectivePolygon() const { - if( m_shapesDirty ) - BuildEffectiveShapes( aLayer ); + if( m_polyDirty ) + BuildEffectivePolygon(); return m_effectivePolygon; } @@ -303,8 +303,8 @@ const SHAPE_SEGMENT* PAD::GetEffectiveHoleShape() const int PAD::GetBoundingRadius() const { - if( m_shapesDirty ) - BuildEffectiveShapes( UNDEFINED_LAYER ); + if( m_polyDirty ) + BuildEffectivePolygon(); return m_effectiveBoundingRadius; } @@ -453,31 +453,6 @@ void PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const } } - // Polygon - // - m_effectivePolygon = std::make_shared(); - TransformShapeWithClearanceToPolygon( *m_effectivePolygon, aLayer, 0, maxError, ERROR_INSIDE ); - - // Bounding box and radius - // - // PADSTACKS TODO: these will both need to cycle through all layers to get the largest - // values.... - // - m_effectiveBoundingRadius = 0; - - for( int cnt = 0; cnt < m_effectivePolygon->OutlineCount(); ++cnt ) - { - const SHAPE_LINE_CHAIN& poly = m_effectivePolygon->COutline( cnt ); - - for( int ii = 0; ii < poly.PointCount(); ++ii ) - { - int dist = KiROUND( ( poly.CPoint( ii ) - m_pos ).EuclideanNorm() ); - m_effectiveBoundingRadius = std::max( m_effectiveBoundingRadius, dist ); - } - } - - m_effectiveBoundingRadius += 1; - BOX2I bbox = m_effectiveShape->BBox(); m_effectiveBoundingBox = EDA_RECT( (wxPoint) bbox.GetPosition(), wxSize( bbox.GetWidth(), bbox.GetHeight() ) ); @@ -499,6 +474,48 @@ void PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const } +void PAD::BuildEffectivePolygon() const +{ + std::lock_guard RAII_lock( m_polyBuildingLock ); + + // If we had to wait for the lock then we were probably waiting for someone else to + // finish rebuilding the shapes. So check to see if they're clean now. + if( !m_polyDirty ) + return; + + BOARD* board = GetBoard(); + int maxError = board ? board->GetDesignSettings().m_MaxError : ARC_HIGH_DEF; + + // Polygon + // + m_effectivePolygon = std::make_shared(); + TransformShapeWithClearanceToPolygon( *m_effectivePolygon, UNDEFINED_LAYER, 0, maxError, + ERROR_INSIDE ); + + // Bounding radius + // + // PADSTACKS TODO: these will both need to cycle through all layers to get the largest + // values.... + // + m_effectiveBoundingRadius = 0; + + for( int cnt = 0; cnt < m_effectivePolygon->OutlineCount(); ++cnt ) + { + const SHAPE_LINE_CHAIN& poly = m_effectivePolygon->COutline( cnt ); + + for( int ii = 0; ii < poly.PointCount(); ++ii ) + { + int dist = KiROUND( ( poly.CPoint( ii ) - m_pos ).EuclideanNorm() ); + m_effectiveBoundingRadius = std::max( m_effectiveBoundingRadius, dist ); + } + } + + // All done + // + m_polyDirty = false; +} + + const EDA_RECT PAD::GetBoundingBox() const { if( m_shapesDirty ) @@ -522,7 +539,7 @@ void PAD::SetDrawCoord() RotatePoint( &m_pos.x, &m_pos.y, angle ); m_pos += parentFootprint->GetPosition(); - m_shapesDirty = true; + SetDirty(); } @@ -548,7 +565,7 @@ void PAD::SetAttribute( PAD_ATTR_T aAttribute ) if( aAttribute == PAD_ATTRIB_SMD ) m_drill = wxSize( 0, 0 ); - m_shapesDirty = true; + SetDirty(); } @@ -556,7 +573,7 @@ void PAD::SetProperty( PAD_PROP_T aProperty ) { m_property = aProperty; - m_shapesDirty = true; + SetDirty(); } @@ -565,7 +582,7 @@ void PAD::SetOrientation( double aAngle ) NORMALIZE_ANGLE_POS( aAngle ); m_orient = aAngle; - m_shapesDirty = true; + SetDirty(); } @@ -623,7 +640,7 @@ void PAD::Flip( const wxPoint& aCentre, bool aFlipLeftRight ) // Flip the basic shapes, in custom pads FlipPrimitives( aFlipLeftRight ); - m_shapesDirty = true; + SetDirty(); } @@ -633,7 +650,7 @@ void PAD::FlipPrimitives( bool aFlipLeftRight ) for( std::shared_ptr& primitive : m_editPrimitives ) primitive->Flip( wxPoint( 0, 0 ), aFlipLeftRight ); - m_shapesDirty = true; + SetDirty(); } @@ -1040,7 +1057,7 @@ void PAD::Rotate( const wxPoint& aRotCentre, double aAngle ) SetLocalCoord(); - m_shapesDirty = true; + SetDirty(); } @@ -1357,7 +1374,7 @@ void PAD::ImportSettingsFrom( const PAD& aMasterPad ) ReplacePrimitives( aMasterPad.GetPrimitives() ); SetAnchorPadShape( aMasterPad.GetAnchorPadShape() ); - m_shapesDirty = true; + SetDirty(); } diff --git a/pcbnew/pad.h b/pcbnew/pad.h index 567f87014d..d123d1ab38 100644 --- a/pcbnew/pad.h +++ b/pcbnew/pad.h @@ -153,7 +153,7 @@ public: void SetShape( PAD_SHAPE_T aShape ) { m_padShape = aShape; - m_shapesDirty = true; + SetDirty(); } /** @@ -164,7 +164,7 @@ public: void SetPosition( const wxPoint& aPos ) override { m_pos = aPos; - m_shapesDirty = true; + SetDirty(); } wxPoint GetPosition() const override { return m_pos; } @@ -203,7 +203,7 @@ public: void SetAnchorPadShape( PAD_SHAPE_T aShape ) { m_anchorPadShape = ( aShape == PAD_SHAPE_RECT ) ? PAD_SHAPE_RECT : PAD_SHAPE_CIRCLE; - m_shapesDirty = true; + SetDirty(); } /** @@ -216,8 +216,8 @@ public: return ( GetLayerSet() & LSET::AllCuMask() ) != 0; } - void SetY( int y ) { m_pos.y = y; m_shapesDirty = true; } - void SetX( int x ) { m_pos.x = x; m_shapesDirty = true; } + void SetY( int y ) { m_pos.y = y; SetDirty(); } + void SetX( int x ) { m_pos.x = x; SetDirty(); } void SetPos0( const wxPoint& aPos ) { m_pos0 = aPos; } const wxPoint& GetPos0() const { return m_pos0; } @@ -225,24 +225,24 @@ public: void SetY0( int y ) { m_pos0.y = y; } void SetX0( int x ) { m_pos0.x = x; } - void SetSize( const wxSize& aSize ) { m_size = aSize; m_shapesDirty = true; } + void SetSize( const wxSize& aSize ) { m_size = aSize; SetDirty(); } const wxSize& GetSize() const { return m_size; } - void SetSizeX( const int aX ) { m_size.x = aX; m_shapesDirty = true; } + void SetSizeX( const int aX ) { m_size.x = aX; SetDirty(); } const int GetSizeX() const { return m_size.x; } - void SetSizeY( const int aY ) { m_size.y = aY; m_shapesDirty = true; } + void SetSizeY( const int aY ) { m_size.y = aY; SetDirty(); } const int GetSizeY() const { return m_size.y; } - void SetDelta( const wxSize& aSize ) { m_deltaSize = aSize; m_shapesDirty = true; } + void SetDelta( const wxSize& aSize ) { m_deltaSize = aSize; SetDirty(); } const wxSize& GetDelta() const { return m_deltaSize; } - void SetDrillSize( const wxSize& aSize ) { m_drill = aSize; m_shapesDirty = true; } + void SetDrillSize( const wxSize& aSize ) { m_drill = aSize; SetDirty(); } const wxSize& GetDrillSize() const { return m_drill; } - void SetDrillSizeX( const int aX ) { m_drill.x = aX; m_shapesDirty = true; } + void SetDrillSizeX( const int aX ) { m_drill.x = aX; SetDirty(); } const int GetDrillSizeX() const { return m_drill.x; } - void SetDrillSizeY( const int aY ) { m_drill.y = aY; m_shapesDirty = true; } + void SetDrillSizeY( const int aY ) { m_drill.y = aY; SetDirty(); } const int GetDrillSizeY() const { return m_drill.y; } - void SetOffset( const wxPoint& aOffset ) { m_offset = aOffset; m_shapesDirty = true; } + void SetOffset( const wxPoint& aOffset ) { m_offset = aOffset; SetDirty(); } const wxPoint& GetOffset() const { return m_offset; } wxPoint GetCenter() const override { return GetPosition(); } @@ -341,8 +341,16 @@ public: void SetDrillShape( PAD_DRILL_SHAPE_T aShape ) { m_drillShape = aShape; m_shapesDirty = true; } PAD_DRILL_SHAPE_T GetDrillShape() const { return m_drillShape; } - bool IsDirty() const { return m_shapesDirty; } - void SetDirty() { m_shapesDirty = true; } + bool IsDirty() const + { + return m_shapesDirty || m_polyDirty; + } + + void SetDirty() + { + m_shapesDirty = true; + m_polyDirty = true; + } void SetLayerSet( LSET aLayers ) override { m_layerMask = aLayers; } LSET GetLayerSet() const override { return m_layerMask; } @@ -402,7 +410,7 @@ public: // @copydoc BOARD_ITEM::GetEffectiveShape virtual std::shared_ptr GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override; - const std::shared_ptr& GetEffectivePolygon( PCB_LAYER_ID = UNDEFINED_LAYER ) const; + const std::shared_ptr& GetEffectivePolygon() const; /** * Function GetEffectiveHoleShape @@ -597,7 +605,7 @@ public: { m_pos += aMoveVector; SetLocalCoord(); - m_shapesDirty = true; + SetDirty(); } void Rotate( const wxPoint& aRotCentre, double aAngle ) override; @@ -634,6 +642,7 @@ public: * the dirty bit. */ void BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const; + void BuildEffectivePolygon() const; virtual void ViewGetLayers( int aLayers[], int& aCount ) const override; @@ -670,11 +679,14 @@ private: // Must be set to true to force rebuild shapes to draw (after geometry change for instance) mutable bool m_shapesDirty; mutable std::mutex m_shapesBuildingLock; - mutable int m_effectiveBoundingRadius; mutable EDA_RECT m_effectiveBoundingBox; mutable std::shared_ptr m_effectiveShape; mutable std::shared_ptr m_effectiveHoleShape; + + mutable bool m_polyDirty; + mutable std::mutex m_polyBuildingLock; mutable std::shared_ptr m_effectivePolygon; + mutable int m_effectiveBoundingRadius; /* * How to build the custom shape in zone, to create the clearance area: diff --git a/pcbnew/pad_custom_shape_functions.cpp b/pcbnew/pad_custom_shape_functions.cpp index 8f54e819d9..a159e20f36 100644 --- a/pcbnew/pad_custom_shape_functions.cpp +++ b/pcbnew/pad_custom_shape_functions.cpp @@ -60,7 +60,7 @@ void PAD::AddPrimitivePoly( const std::vector& aPoly, int aThickness, b item->SetPolyPoints( aPoly ); item->SetWidth( aThickness ); m_editPrimitives.emplace_back( item ); - m_shapesDirty = true; + SetDirty(); } @@ -73,7 +73,7 @@ void PAD::AddPrimitiveSegment( const wxPoint& aStart, const wxPoint& aEnd, int a item->SetEnd( aEnd ); item->SetWidth( aThickness ); m_editPrimitives.emplace_back( item ); - m_shapesDirty = true; + SetDirty(); } @@ -88,7 +88,7 @@ void PAD::AddPrimitiveArc( const wxPoint& aCenter, const wxPoint& aStart, int aA item->SetAngle( aArcAngle ); item->SetWidth( aThickness ); m_editPrimitives.emplace_back( item ); - m_shapesDirty = true; + SetDirty(); } @@ -104,7 +104,7 @@ void PAD::AddPrimitiveCurve( const wxPoint& aStart, const wxPoint& aEnd, const w item->SetBezControl2( aCtrl2 ); item->SetWidth( aThickness ); m_editPrimitives.emplace_back( item ); - m_shapesDirty = true; + SetDirty(); } @@ -117,7 +117,7 @@ void PAD::AddPrimitiveCircle( const wxPoint& aCenter, int aRadius, int aThicknes item->SetEnd( wxPoint( aCenter.x + aRadius, aCenter.y ) ); item->SetWidth( aThickness ); m_editPrimitives.emplace_back( item ); - m_shapesDirty = true; + SetDirty(); } @@ -131,7 +131,7 @@ void PAD::AddPrimitiveRect( const wxPoint& aStart, const wxPoint& aEnd, int aThi item->SetEnd( aEnd ); item->SetWidth( aThickness ); m_editPrimitives.emplace_back( item ); - m_shapesDirty = true; + SetDirty(); } @@ -144,7 +144,7 @@ void PAD::ReplacePrimitives( const std::vector>& aPri if( aPrimitivesList.size() ) AppendPrimitives( aPrimitivesList ); - m_shapesDirty = true; + SetDirty(); } @@ -154,7 +154,7 @@ void PAD::AppendPrimitives( const std::vector>& aPrim for( const std::shared_ptr& prim : aPrimitivesList ) AddPrimitive( new PCB_SHAPE( *prim ) ); - m_shapesDirty = true; + SetDirty(); } @@ -162,7 +162,7 @@ void PAD::AddPrimitive( PCB_SHAPE* aPrimitive ) { m_editPrimitives.emplace_back( aPrimitive ); - m_shapesDirty = true; + SetDirty(); } @@ -171,7 +171,7 @@ void PAD::DeletePrimitivesList() { m_editPrimitives.clear(); - m_shapesDirty = true; + SetDirty(); } diff --git a/pcbnew/ratsnest/ratsnest_data.cpp b/pcbnew/ratsnest/ratsnest_data.cpp index 743f7ec021..7b8766d3d4 100644 --- a/pcbnew/ratsnest/ratsnest_data.cpp +++ b/pcbnew/ratsnest/ratsnest_data.cpp @@ -428,7 +428,7 @@ bool RN_NET::NearestBicoloredPair( const RN_NET& aOtherNet, CN_ANCHOR_PTR& aNode for( ; fwd_it != m_nodes.end(); ++fwd_it ) { - auto nodeB = *fwd_it; + const std::shared_ptr& nodeB = *fwd_it; if( nodeB->GetNoLine() ) continue; @@ -446,7 +446,7 @@ bool RN_NET::NearestBicoloredPair( const RN_NET& aOtherNet, CN_ANCHOR_PTR& aNode /// Step 3: using the same starting point, check points backwards for closer points for( ; rev_it != m_nodes.rend(); ++rev_it ) { - auto nodeB = *rev_it; + const std::shared_ptr& nodeB = *rev_it; if( nodeB->GetNoLine() ) continue; diff --git a/pcbnew/tools/pcb_selection_tool.cpp b/pcbnew/tools/pcb_selection_tool.cpp index a0ae6a0f87..0213c26a44 100644 --- a/pcbnew/tools/pcb_selection_tool.cpp +++ b/pcbnew/tools/pcb_selection_tool.cpp @@ -421,7 +421,9 @@ int PCB_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent ) //move cursor prediction if( !modifier_enabled && !dragAlwaysSelects && !m_selection.Empty() && evt->HasPosition() && selectionContains( evt->Position() ) ) + { m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING ); + } else { if( m_additive ) @@ -2204,13 +2206,18 @@ bool PCB_SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const const unsigned GRIP_MARGIN = 20; VECTOR2I margin = getView()->ToWorld( VECTOR2I( GRIP_MARGIN, GRIP_MARGIN ), false ); - // Check if the point is located within any of the currently selected items bounding boxes - for( EDA_ITEM* item : m_selection ) - { - BOX2I itemBox = item->ViewBBox(); - itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item + GENERAL_COLLECTORS_GUIDE guide = getCollectorsGuide(); + GENERAL_COLLECTOR collector; - if( itemBox.Contains( aPoint ) ) + collector.Collect( board(), m_isFootprintEditor ? GENERAL_COLLECTOR::FootprintItems + : GENERAL_COLLECTOR::AllBoardItems, + (wxPoint) aPoint, guide ); + + for( int i = collector.GetCount() - 1; i >= 0; --i ) + { + BOARD_ITEM* item = collector[i]; + + if( item->IsSelected() && item->HitTest( (wxPoint) aPoint, margin.x ) ) return true; } diff --git a/pcbnew/track.cpp b/pcbnew/track.cpp index 46ab3b07a1..3df4224f08 100644 --- a/pcbnew/track.cpp +++ b/pcbnew/track.cpp @@ -547,7 +547,12 @@ double TRACK::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const const BOX2I TRACK::ViewBBox() const { BOX2I bbox = GetBoundingBox(); - bbox.Inflate( 2 * GetOwnClearance( GetLayer() ) ); + + BOARD* board = GetBoard(); + + if( board ) + bbox.Inflate( 2 * board->GetDesignSettings().GetBiggestClearanceValue() ); + return bbox; } diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp index 436990f4e4..9c56e93873 100644 --- a/pcbnew/zone_filler.cpp +++ b/pcbnew/zone_filler.cpp @@ -126,7 +126,10 @@ bool ZONE_FILLER::Fill( std::vector& aZones, bool aCheck, wxWindow* aPare for( PAD* pad : footprint->Pads() ) { if( pad->IsDirty() ) + { pad->BuildEffectiveShapes( UNDEFINED_LAYER ); + pad->BuildEffectivePolygon(); + } } for( ZONE* zone : footprint->Zones() )