| 
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -73,16 +73,11 @@ std::optional<INTERSECTABLE_GEOM> GetBoardIntersectable( const BOARD_ITEM& aItem | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        switch( shape.GetShape() ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        case SHAPE_T::SEGMENT: return SEG{ shape.GetStart(), shape.GetEnd() }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        case SHAPE_T::CIRCLE: return CIRCLE{ shape.GetCenter(), shape.GetRadius() }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        case SHAPE_T::ARC: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            return SHAPE_ARC{ shape.GetStart(), shape.GetArcMid(), shape.GetEnd(), 0 }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        case SHAPE_T::SEGMENT:   return SEG{ shape.GetStart(), shape.GetEnd() }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        case SHAPE_T::CIRCLE:    return CIRCLE{ shape.GetCenter(), shape.GetRadius() }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        case SHAPE_T::ARC:       return SHAPE_ARC{ shape.GetStart(), shape.GetArcMid(), shape.GetEnd(), 0 }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        case SHAPE_T::RECTANGLE: return BOX2I::ByCorners( shape.GetStart(), shape.GetEnd() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        default: break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        default:                 break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        break; | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -91,14 +86,12 @@ std::optional<INTERSECTABLE_GEOM> GetBoardIntersectable( const BOARD_ITEM& aItem | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    case PCB_TRACE_T: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const PCB_TRACK& track = static_cast<const PCB_TRACK&>( aItem ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return SEG{ track.GetStart(), track.GetEnd() }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    case PCB_ARC_T: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const PCB_ARC& arc = static_cast<const PCB_ARC&>( aItem ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return SHAPE_ARC{ arc.GetStart(), arc.GetMid(), arc.GetEnd(), 0 }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -150,7 +143,8 @@ std::optional<int64_t> FindSquareDistanceToItem( const BOARD_ITEM& item, const V | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} // namespace
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					PCB_GRID_HELPER::PCB_GRID_HELPER( TOOL_MANAGER* aToolMgr, MAGNETIC_SETTINGS* aMagneticSettings ) : | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        GRID_HELPER( aToolMgr, LAYER_ANCHOR ), m_magneticSettings( aMagneticSettings ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        GRID_HELPER( aToolMgr, LAYER_ANCHOR ), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        m_magneticSettings( aMagneticSettings ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    KIGFX::VIEW*            view = m_toolMgr->GetView(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    KIGFX::RENDER_SETTINGS* settings = view->GetPainter()->GetSettings(); | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -185,9 +179,7 @@ void PCB_GRID_HELPER::AddConstructionItems( std::vector<BOARD_ITEM*> aItems, boo | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                            bool aIsPersistent ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if( !ADVANCED_CFG::GetCfg().m_EnableExtensionSnaps ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // For all the elements that get drawn construction geometry,
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // add something suitable to the construction helper.
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -218,10 +210,8 @@ void PCB_GRID_HELPER::AddConstructionItems( std::vector<BOARD_ITEM*> aItems, boo | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    // Two rays, extending from the segment ends
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    const VECTOR2I segVec = shape.GetEnd() - shape.GetStart(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    constructionDrawables.emplace_back( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            HALF_LINE{ shape.GetStart(), shape.GetStart() - segVec } ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    constructionDrawables.emplace_back( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            HALF_LINE{ shape.GetEnd(), shape.GetEnd() + segVec } ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    constructionDrawables.emplace_back( HALF_LINE{ shape.GetStart(), shape.GetStart() - segVec } ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    constructionDrawables.emplace_back( HALF_LINE{ shape.GetEnd(), shape.GetEnd() + segVec } ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if( aIsPersistent ) | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -241,17 +231,15 @@ void PCB_GRID_HELPER::AddConstructionItems( std::vector<BOARD_ITEM*> aItems, boo | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if( !aExtensionOnly ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    constructionDrawables.push_back( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            CIRCLE{ shape.GetCenter(), shape.GetRadius() } ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    constructionDrawables.push_back( CIRCLE{ shape.GetCenter(), shape.GetRadius() } ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                else | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    // The rest of the circle is the arc through the opposite point to the midpoint
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    const VECTOR2I oppositeMid = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            shape.GetCenter() + ( shape.GetCenter() - shape.GetArcMid() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    constructionDrawables.push_back( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            SHAPE_ARC{ shape.GetStart(), oppositeMid, shape.GetEnd(), 0 } ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    const VECTOR2I oppositeMid = shape.GetCenter() + ( shape.GetCenter() - shape.GetArcMid() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    constructionDrawables.push_back( SHAPE_ARC{ shape.GetStart(), oppositeMid, shape.GetEnd(), 0 } ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                constructionDrawables.push_back( shape.GetCenter() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if( aIsPersistent ) | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -288,15 +276,11 @@ void PCB_GRID_HELPER::AddConstructionItems( std::vector<BOARD_ITEM*> aItems, boo | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            constructionDrawables.push_back( refImg.GetPosition() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if( refImg.GetTransformOriginOffset() != VECTOR2I( 0, 0 ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                constructionDrawables.push_back( refImg.GetPosition() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                                 + refImg.GetTransformOriginOffset() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                constructionDrawables.push_back( refImg.GetPosition() + refImg.GetTransformOriginOffset() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            for( const SEG& seg : KIGEOM::BoxToSegs( refImg.GetBoundingBox() ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                constructionDrawables.push_back( seg ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        default: | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -315,13 +299,11 @@ void PCB_GRID_HELPER::AddConstructionItems( std::vector<BOARD_ITEM*> aItems, boo | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if( referenceOnlyPoints.size() ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        getSnapManager().SetReferenceOnlyPoints( std::move( referenceOnlyPoints ) ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    //  Let the manager handle it
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    getSnapManager().GetConstructionManager().ProposeConstructionItems( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            std::move( constructionItemsBatch ), aIsPersistent ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    getSnapManager().GetConstructionManager().ProposeConstructionItems( std::move( constructionItemsBatch ), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                                                        aIsPersistent ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -554,6 +536,7 @@ VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& a | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if( KIGFX::ANCHOR_DEBUG* ad = enableAndGetAnchorDebug(); ad ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        ad->ClearAnchors(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        for( const ANCHOR& anchor : m_anchors ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            ad->AddAnchor( anchor.pos ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -563,6 +546,7 @@ VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& a | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // The distance to the nearest snap point, if any
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    std::optional<int> snapDist; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if( nearest ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        snapDist = nearest->Distance( aOrigin ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -571,41 +555,40 @@ VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& a | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    SNAP_MANAGER&      snapManager = getSnapManager(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    SNAP_LINE_MANAGER& snapLineManager = snapManager.GetSnapLineManager(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const auto ptIsReferenceOnly = [&]( const VECTOR2I& aPt ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const std::vector<VECTOR2I>& referenceOnlyPoints = snapManager.GetReferenceOnlyPoints(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return std::find( referenceOnlyPoints.begin(), referenceOnlyPoints.end(), aPt ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					               != referenceOnlyPoints.end(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const auto proposeConstructionForItems = [&]( const std::vector<EDA_ITEM*>& aItems ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // Add any involved item as a temporary construction item
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // (de-duplication with existing construction items is handled later)
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        std::vector<BOARD_ITEM*> items; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        for( EDA_ITEM* item : aItems ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const auto ptIsReferenceOnly = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            [&]( const VECTOR2I& aPt ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const std::vector<VECTOR2I>& referenceOnlyPoints = snapManager.GetReferenceOnlyPoints(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return std::find( referenceOnlyPoints.begin(), referenceOnlyPoints.end(), aPt ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                       != referenceOnlyPoints.end(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // Null items are allowed to arrive here as they represent geometry that isn't
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // specifically tied to a board item. For example snap lines from some
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // other anchor.
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // But they don't produce new construction items.
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if( boardItem ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const auto proposeConstructionForItems = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            [&]( const std::vector<EDA_ITEM*>& aItems ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if( m_magneticSettings->allLayers | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    || ( ( aLayers & boardItem->GetLayerSet() ).any() ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // Add any involved item as a temporary construction item
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // (de-duplication with existing construction items is handled later)
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                std::vector<BOARD_ITEM*> items; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for( EDA_ITEM* item : aItems ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    items.push_back( boardItem ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    // Null items are allowed to arrive here as they represent geometry that isn't
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    // specifically tied to a board item. For example snap lines from some
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    // other anchor.
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    // But they don't produce new construction items.
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if( boardItem ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        if( m_magneticSettings->allLayers || ( ( aLayers & boardItem->GetLayerSet() ).any() ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            items.push_back( boardItem ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // Temporary construction items are not persistent and don't
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // overlay the items themselves (as the items will not be moved)
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        AddConstructionItems( items, true, false ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // Temporary construction items are not persistent and don't
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // overlay the items themselves (as the items will not be moved)
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                AddConstructionItems( items, true, false ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    bool snapValid = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -631,9 +614,7 @@ VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& a | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // (we don't snap to reference points, but we can use them to update the snap line,
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // without actually snapping)
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if( !ptIsReferenceOnly( *snapLineSnap ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    return *snapLineSnap; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -658,15 +639,13 @@ VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& a | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // This is to make construction items less intrusive and more
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // a result of user intent.
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if( !anchorIsConstructed ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    proposeConstructionForItems( nearest->items ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const auto shouldAcceptAnchor = [&]( const ANCHOR& aAnchor ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    // If no extension snaps are enabled, don't inhibit
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    static const bool haveExtensions = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            ADVANCED_CFG::GetCfg().m_EnableExtensionSnaps; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    static const bool haveExtensions = ADVANCED_CFG::GetCfg().m_EnableExtensionSnaps; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if( !haveExtensions ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        return true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -677,8 +656,7 @@ VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& a | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    // This is an area most likely to be controversial/need tuning,
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    // as some users will think it's fiddly; without 'activation', others will
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    // think the snaps are intrusive.
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    bool allRealAreInvolved = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            snapManager.GetConstructionManager().InvolvesAllGivenRealItems( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    bool allRealAreInvolved = snapManager.GetConstructionManager().InvolvesAllGivenRealItems( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                    aAnchor.items ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    return allRealAreInvolved; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                }; | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -700,14 +678,15 @@ VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& a | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        else | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            static const bool canActivateByHitTest = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    ADVANCED_CFG::GetCfg().m_ExtensionSnapActivateOnHover; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            static const bool canActivateByHitTest = ADVANCED_CFG::GetCfg().m_ExtensionSnapActivateOnHover; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if( canActivateByHitTest ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // An exact hit on an item, even if not near a snap point
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // If it's tool hard to hit by hover, this can be increased
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // to make it non-exact.
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const int hoverAccuracy = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for( BOARD_ITEM* item : visibleItems ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if( item->HitTest( aOrigin, hoverAccuracy ) ) | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -726,12 +705,10 @@ VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& a | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // but they're useful when there isn't a grid to snap to
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        if( !m_enableGrid ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            OPT_VECTOR2I nearestPointOnAnElement = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    GetNearestPoint( m_pointOnLineCandidates, aOrigin ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            OPT_VECTOR2I nearestPointOnAnElement = GetNearestPoint( m_pointOnLineCandidates, aOrigin ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // Got any nearest point - snap if in range
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if( nearestPointOnAnElement | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                && nearestPointOnAnElement->Distance( aOrigin ) <= snapRange ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if( nearestPointOnAnElement && nearestPointOnAnElement->Distance( aOrigin ) <= snapRange ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                updateSnapPoint( { *nearestPointOnAnElement, POINT_TYPE::PT_ON_ELEMENT } ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -954,49 +931,46 @@ void PCB_GRID_HELPER::computeAnchors( const std::vector<BOARD_ITEM*>& aItems, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const bool excludeGraphics = aSelectionFilter && !aSelectionFilter->graphics; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const bool excludeTracks = aSelectionFilter && !aSelectionFilter->tracks; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const auto itemIsSnappable = [&]( const BOARD_ITEM& aItem ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // If we are filtering by layers, check if the item matches
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        if( aMatchLayers ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            return m_magneticSettings->allLayers | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                   || ( ( *aMatchLayers & aItem.GetLayerSet() ).any() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const auto processItem = [&]( BOARD_ITEM& item ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // Don't even process the item if it doesn't match the layers
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        if( !itemIsSnappable( item ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const auto itemIsSnappable = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            [&]( const BOARD_ITEM& aItem ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // If we are filtering by layers, check if the item matches
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if( aMatchLayers ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    return m_magneticSettings->allLayers || ( ( *aMatchLayers & aItem.GetLayerSet() ).any() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // First, add all the key points of the item itself
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        computeAnchors( &item, aRefPos, aFrom, aSelectionFilter ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // If we are computing intersections, construct the relevant intersectables
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // Points on elements also use the intersectables.
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        if( computeIntersections || computePointsOnElements ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            std::optional<INTERSECTABLE_GEOM> intersectableGeom; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if( !excludeGraphics | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                && ( item.Type() == PCB_SHAPE_T || item.Type() == PCB_REFERENCE_IMAGE_T ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                intersectableGeom = GetBoardIntersectable( item ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            else if( !excludeTracks && ( item.Type() == PCB_TRACE_T || item.Type() == PCB_ARC_T ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const auto processItem = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            [&]( BOARD_ITEM& item ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                intersectableGeom = GetBoardIntersectable( item ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // Don't even process the item if it doesn't match the layers
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if( !itemIsSnappable( item ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if( intersectableGeom ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                intersectables.emplace_back( &item, *intersectableGeom ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // First, add all the key points of the item itself
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                computeAnchors( &item, aRefPos, aFrom, aSelectionFilter ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // If we are computing intersections, construct the relevant intersectables
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // Points on elements also use the intersectables.
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if( computeIntersections || computePointsOnElements ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    std::optional<INTERSECTABLE_GEOM> intersectableGeom; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if( !excludeGraphics | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        && ( item.Type() == PCB_SHAPE_T || item.Type() == PCB_REFERENCE_IMAGE_T ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        intersectableGeom = GetBoardIntersectable( item ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    else if( !excludeTracks && ( item.Type() == PCB_TRACE_T || item.Type() == PCB_ARC_T ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        intersectableGeom = GetBoardIntersectable( item ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if( intersectableGeom ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        intersectables.emplace_back( &item, *intersectableGeom ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    for( BOARD_ITEM* item : aItems ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    { | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -1080,6 +1054,7 @@ void PCB_GRID_HELPER::computeAnchors( const std::vector<BOARD_ITEM*>& aItems, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // The intersectables can also be used for fall-back snapping to "point on line"
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // snaps if no other snap is found
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    m_pointOnLineCandidates.clear(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if( computePointsOnElements ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // For the moment, it's trivial to make a NEARABLE from an INTERSECTABLE,
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -1176,144 +1151,143 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // As defaults, these are probably reasonable to avoid spamming key points
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const KIGEOM::OVAL_KEY_POINT_FLAGS ovalKeyPointFlags = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            KIGEOM::OVAL_CENTER | KIGEOM::OVAL_CAP_TIPS | KIGEOM::OVAL_SIDE_MIDPOINTS | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            | KIGEOM::OVAL_CARDINAL_EXTREMES; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    auto handlePadShape = [&]( PAD* aPad, PCB_LAYER_ID aLayer ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        addAnchor( aPad->GetPosition(), ORIGIN | SNAPPABLE, aPad, POINT_TYPE::PT_CENTER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        /// If we are getting a drag point, we don't want to center the edge of pads
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        if( aFrom ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        switch( aPad->GetShape( aLayer ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        case PAD_SHAPE::CIRCLE: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            const CIRCLE circle( aPad->ShapePos( aLayer ), aPad->GetSizeX() / 2 ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const KIGEOM::OVAL_KEY_POINT_FLAGS ovalKeyPointFlags = KIGEOM::OVAL_CENTER | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                                           | KIGEOM::OVAL_CAP_TIPS | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                                           | KIGEOM::OVAL_SIDE_MIDPOINTS | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                                           | KIGEOM::OVAL_CARDINAL_EXTREMES; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            for( const TYPED_POINT2I& pt : KIGEOM::GetCircleKeyPoints( circle, false ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    auto handlePadShape = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            [&]( PAD* aPad, PCB_LAYER_ID aLayer ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( pt.m_point, OUTLINE | SNAPPABLE, aPad, pt.m_types ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( aPad->GetPosition(), ORIGIN | SNAPPABLE, aPad, POINT_TYPE::PT_CENTER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        case PAD_SHAPE::OVAL: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            const OVAL oval( aPad->GetSize( aLayer ), aPad->GetPosition(), aPad->GetOrientation() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            for( const TYPED_POINT2I& pt : KIGEOM::GetOvalKeyPoints( oval, ovalKeyPointFlags ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( pt.m_point, OUTLINE | SNAPPABLE, aPad, pt.m_types ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                /// If we are getting a drag point, we don't want to center the edge of pads
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if( aFrom ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    return; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        case PAD_SHAPE::RECTANGLE: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        case PAD_SHAPE::TRAPEZOID: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        case PAD_SHAPE::ROUNDRECT: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        case PAD_SHAPE::CHAMFERED_RECT: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            VECTOR2I half_size( aPad->GetSize( aLayer ) / 2 ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            VECTOR2I trap_delta( 0, 0 ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                switch( aPad->GetShape( aLayer ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                case PAD_SHAPE::CIRCLE: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    const CIRCLE circle( aPad->ShapePos( aLayer ), aPad->GetSizeX() / 2 ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if( aPad->GetShape( aLayer ) == PAD_SHAPE::TRAPEZOID ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                trap_delta = aPad->GetDelta( aLayer ) / 2; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    for( const TYPED_POINT2I& pt : KIGEOM::GetCircleKeyPoints( circle, false ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( pt.m_point, OUTLINE | SNAPPABLE, aPad, pt.m_types ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            SHAPE_LINE_CHAIN corners; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                case PAD_SHAPE::OVAL: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    const OVAL oval( aPad->GetSize( aLayer ), aPad->GetPosition(), aPad->GetOrientation() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            corners.Append( -half_size.x - trap_delta.y, half_size.y + trap_delta.x ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            corners.Append( half_size.x + trap_delta.y, half_size.y - trap_delta.x ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            corners.Append( half_size.x - trap_delta.y, -half_size.y + trap_delta.x ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            corners.Append( -half_size.x + trap_delta.y, -half_size.y - trap_delta.x ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            corners.SetClosed( true ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    for( const TYPED_POINT2I& pt : KIGEOM::GetOvalKeyPoints( oval, ovalKeyPointFlags ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( pt.m_point, OUTLINE | SNAPPABLE, aPad, pt.m_types ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            corners.Rotate( aPad->GetOrientation() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            corners.Move( aPad->ShapePos( aLayer ) ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                case PAD_SHAPE::RECTANGLE: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                case PAD_SHAPE::TRAPEZOID: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                case PAD_SHAPE::ROUNDRECT: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                case PAD_SHAPE::CHAMFERED_RECT: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    VECTOR2I half_size( aPad->GetSize( aLayer ) / 2 ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    VECTOR2I trap_delta( 0, 0 ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            for( std::size_t ii = 0; ii < corners.GetSegmentCount(); ++ii ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const SEG& seg = corners.GetSegment( ii ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( seg.A, OUTLINE | SNAPPABLE, aPad, POINT_TYPE::PT_CORNER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( seg.Center(), OUTLINE | SNAPPABLE, aPad, POINT_TYPE::PT_MID ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if( aPad->GetShape( aLayer ) == PAD_SHAPE::TRAPEZOID ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        trap_delta = aPad->GetDelta( aLayer ) / 2; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if( ii == corners.GetSegmentCount() - 1 ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    addAnchor( seg.B, OUTLINE | SNAPPABLE, aPad, POINT_TYPE::PT_CORNER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    SHAPE_LINE_CHAIN corners; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    corners.Append( -half_size.x - trap_delta.y, half_size.y + trap_delta.x ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    corners.Append( half_size.x + trap_delta.y, half_size.y - trap_delta.x ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    corners.Append( half_size.x - trap_delta.y, -half_size.y + trap_delta.x ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    corners.Append( -half_size.x + trap_delta.y, -half_size.y - trap_delta.x ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    corners.SetClosed( true ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        default: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            const auto& outline = aPad->GetEffectivePolygon( aLayer, ERROR_INSIDE ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    corners.Rotate( aPad->GetOrientation() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    corners.Move( aPad->ShapePos( aLayer ) ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if( !outline->IsEmpty() ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for( const VECTOR2I& pt : outline->Outline( 0 ).CPoints() ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    addAnchor( pt, OUTLINE | SNAPPABLE, aPad ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    for( std::size_t ii = 0; ii < corners.GetSegmentCount(); ++ii ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        const SEG& seg = corners.GetSegment( ii ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( seg.A, OUTLINE | SNAPPABLE, aPad, POINT_TYPE::PT_CORNER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( seg.Center(), OUTLINE | SNAPPABLE, aPad, POINT_TYPE::PT_MID ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        if( ii == corners.GetSegmentCount() - 1 ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            addAnchor( seg.B, OUTLINE | SNAPPABLE, aPad, POINT_TYPE::PT_CORNER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        if( aPad->HasHole() ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // Holes are at the pad centre (it's the shape that may be offset)
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            const VECTOR2I hole_pos = aPad->GetPosition(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            const VECTOR2I hole_size = aPad->GetDrillSize(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            std::vector<TYPED_POINT2I> snap_pts; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                default: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    const auto& outline = aPad->GetEffectivePolygon( aLayer, ERROR_INSIDE ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if( hole_size.x == hole_size.y ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // Circle
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const CIRCLE circle( hole_pos, hole_size.x / 2 ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                snap_pts = KIGEOM::GetCircleKeyPoints( circle, true ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            else | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // Oval
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if( !outline->IsEmpty() ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        for( const VECTOR2I& pt : outline->Outline( 0 ).CPoints() ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            addAnchor( pt, OUTLINE | SNAPPABLE, aPad ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // For now there's no way to have an off-angle hole, so this is the
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // same as the pad. In future, this may not be true:
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // https://gitlab.com/kicad/code/kicad/-/issues/4124
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const OVAL oval( hole_size, hole_pos, aPad->GetOrientation() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                snap_pts = KIGEOM::GetOvalKeyPoints( oval, ovalKeyPointFlags ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            for( const TYPED_POINT2I& snap_pt : snap_pts ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( snap_pt.m_point, OUTLINE | SNAPPABLE, aPad, snap_pt.m_types ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if( aPad->HasHole() ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    // Holes are at the pad centre (it's the shape that may be offset)
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    const VECTOR2I hole_pos = aPad->GetPosition(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    const VECTOR2I hole_size = aPad->GetDrillSize(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const auto addRectPoints = [&]( const BOX2I& aBox, EDA_ITEM& aRelatedItem ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const VECTOR2I topRight( aBox.GetRight(), aBox.GetTop() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const VECTOR2I bottomLeft( aBox.GetLeft(), aBox.GetBottom() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    std::vector<TYPED_POINT2I> snap_pts; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const SEG first( aBox.GetOrigin(), topRight ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const SEG second( topRight, aBox.GetEnd() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const SEG third( aBox.GetEnd(), bottomLeft ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const SEG fourth( bottomLeft, aBox.GetOrigin() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if( hole_size.x == hole_size.y ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // Circle
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        const CIRCLE circle( hole_pos, hole_size.x / 2 ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        snap_pts = KIGEOM::GetCircleKeyPoints( circle, true ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    else | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // Oval
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        const int snapFlags = CORNER | SNAPPABLE; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // For now there's no way to have an off-angle hole, so this is the
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // same as the pad. In future, this may not be true:
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // https://gitlab.com/kicad/code/kicad/-/issues/4124
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        const OVAL oval( hole_size, hole_pos, aPad->GetOrientation() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        snap_pts = KIGEOM::GetOvalKeyPoints( oval, ovalKeyPointFlags ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        addAnchor( aBox.GetCenter(), snapFlags, &aRelatedItem, POINT_TYPE::PT_CENTER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    for( const TYPED_POINT2I& snap_pt : snap_pts ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( snap_pt.m_point, OUTLINE | SNAPPABLE, aPad, snap_pt.m_types ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        addAnchor( first.A,         snapFlags, &aRelatedItem, POINT_TYPE::PT_CORNER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        addAnchor( first.Center(),  snapFlags, &aRelatedItem, POINT_TYPE::PT_MID ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        addAnchor( second.A,        snapFlags, &aRelatedItem, POINT_TYPE::PT_CORNER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        addAnchor( second.Center(), snapFlags, &aRelatedItem, POINT_TYPE::PT_MID ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        addAnchor( third.A,         snapFlags, &aRelatedItem, POINT_TYPE::PT_CORNER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        addAnchor( third.Center(),  snapFlags, &aRelatedItem, POINT_TYPE::PT_MID ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        addAnchor( fourth.A,        snapFlags, &aRelatedItem, POINT_TYPE::PT_CORNER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        addAnchor( fourth.Center(), snapFlags, &aRelatedItem, POINT_TYPE::PT_MID ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const auto addRectPoints = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            [&]( const BOX2I& aBox, EDA_ITEM& aRelatedItem ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const VECTOR2I topRight( aBox.GetRight(), aBox.GetTop() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const VECTOR2I bottomLeft( aBox.GetLeft(), aBox.GetBottom() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const SEG first( aBox.GetOrigin(), topRight ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const SEG second( topRight, aBox.GetEnd() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const SEG third( aBox.GetEnd(), bottomLeft ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const SEG fourth( bottomLeft, aBox.GetOrigin() ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const int snapFlags = CORNER | SNAPPABLE; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( aBox.GetCenter(), snapFlags, &aRelatedItem, POINT_TYPE::PT_CENTER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( first.A,         snapFlags, &aRelatedItem, POINT_TYPE::PT_CORNER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( first.Center(),  snapFlags, &aRelatedItem, POINT_TYPE::PT_MID ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( second.A,        snapFlags, &aRelatedItem, POINT_TYPE::PT_CORNER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( second.Center(), snapFlags, &aRelatedItem, POINT_TYPE::PT_MID ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( third.A,         snapFlags, &aRelatedItem, POINT_TYPE::PT_CORNER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( third.Center(),  snapFlags, &aRelatedItem, POINT_TYPE::PT_MID ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( fourth.A,        snapFlags, &aRelatedItem, POINT_TYPE::PT_CORNER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( fourth.Center(), snapFlags, &aRelatedItem, POINT_TYPE::PT_MID ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const auto handleShape = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            [&]( PCB_SHAPE* shape ) | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -1329,26 +1303,18 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( start, ORIGIN | SNAPPABLE, shape, POINT_TYPE::PT_CENTER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( start + VECTOR2I( -r, 0 ), OUTLINE | SNAPPABLE, shape, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                   POINT_TYPE::PT_QUADRANT ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( start + VECTOR2I( r, 0 ), OUTLINE | SNAPPABLE, shape, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                   POINT_TYPE::PT_QUADRANT ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( start + VECTOR2I( 0, -r ), OUTLINE | SNAPPABLE, shape, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                   POINT_TYPE::PT_QUADRANT ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( start + VECTOR2I( 0, r ), OUTLINE | SNAPPABLE, shape, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                   POINT_TYPE::PT_QUADRANT ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( start + VECTOR2I( -r, 0 ), OUTLINE | SNAPPABLE, shape, POINT_TYPE::PT_QUADRANT ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( start + VECTOR2I( r, 0 ), OUTLINE | SNAPPABLE, shape, POINT_TYPE::PT_QUADRANT ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( start + VECTOR2I( 0, -r ), OUTLINE | SNAPPABLE, shape, POINT_TYPE::PT_QUADRANT ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( start + VECTOR2I( 0, r ), OUTLINE | SNAPPABLE, shape, POINT_TYPE::PT_QUADRANT ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    case SHAPE_T::ARC: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( shape->GetStart(), CORNER | SNAPPABLE, shape, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                   POINT_TYPE::PT_END ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( shape->GetEnd(), CORNER | SNAPPABLE, shape, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                   POINT_TYPE::PT_END ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( shape->GetArcMid(), CORNER | SNAPPABLE, shape, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                   POINT_TYPE::PT_MID ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( shape->GetCenter(), ORIGIN | SNAPPABLE, shape, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                   POINT_TYPE::PT_CENTER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( shape->GetStart(), CORNER | SNAPPABLE, shape, POINT_TYPE::PT_END ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( shape->GetEnd(), CORNER | SNAPPABLE, shape, POINT_TYPE::PT_END ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( shape->GetArcMid(), CORNER | SNAPPABLE, shape, POINT_TYPE::PT_MID ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( shape->GetCenter(), ORIGIN | SNAPPABLE, shape, POINT_TYPE::PT_CENTER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    case SHAPE_T::RECTANGLE: | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -1360,8 +1326,7 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    case SHAPE_T::SEGMENT: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( start, CORNER | SNAPPABLE, shape, POINT_TYPE::PT_END ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( end, CORNER | SNAPPABLE, shape, POINT_TYPE::PT_END ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( shape->GetCenter(), CORNER | SNAPPABLE, shape, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                   POINT_TYPE::PT_MID ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        addAnchor( shape->GetCenter(), CORNER | SNAPPABLE, shape, POINT_TYPE::PT_MID ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    case SHAPE_T::POLY: | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -1423,7 +1388,9 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            if( !isHighContrast | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                || PadstackUniqueLayerAppliesToLayer( pad->Padstack(), aLayer, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                                                      activeHighContrastPrimaryLayer ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                handlePadShape( pad, aLayer ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -1467,7 +1434,9 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            if( !isHighContrast | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                || PadstackUniqueLayerAppliesToLayer( pad->Padstack(), aLayer, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                                                      activeHighContrastPrimaryLayer ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                handlePadShape( pad, aLayer ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -1567,8 +1536,7 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        case PCB_MARKER_T: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        case PCB_TARGET_T: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                       POINT_TYPE::PT_CENTER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem, POINT_TYPE::PT_CENTER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        case PCB_VIA_T: | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -1584,8 +1552,7 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if( checkVisibility( aItem ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                           POINT_TYPE::PT_CENTER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem, POINT_TYPE::PT_CENTER ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -1703,10 +1670,9 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if( checkVisibility( aItem ) ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const PCB_REFERENCE_IMAGE& image = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        static_cast<const PCB_REFERENCE_IMAGE&>( *aItem ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const REFERENCE_IMAGE& refImg = image.GetReferenceImage(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const BOX2I            bbox = refImg.GetBoundingBox(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const PCB_REFERENCE_IMAGE& image = static_cast<const PCB_REFERENCE_IMAGE&>( *aItem ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const REFERENCE_IMAGE&     refImg = image.GetReferenceImage(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                const BOX2I                bbox = refImg.GetBoundingBox(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                addRectPoints( bbox, *aItem ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -1748,6 +1714,7 @@ PCB_GRID_HELPER::ANCHOR* PCB_GRID_HELPER::nearestAnchor( const VECTOR2I& aPos, i | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        else | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            const double dist = anchor.pos.SquaredDistance( aPos ); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if( dist < minDist ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // New minimum distance
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
				 | 
				
					
  |