/* * This program source code file is part of KiCad, a free EDA CAD application. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #define BOOST_TEST_NO_MAIN #include #include void TEST_CLEAR_ANCHORS( GRID_HELPER& helper ) { helper.clearAnchors(); } BOOST_AUTO_TEST_SUITE( GridHelperTest ) BOOST_AUTO_TEST_CASE( DefaultConstructor ) { GRID_HELPER helper; // Test default state BOOST_CHECK( helper.GetSnap() ); BOOST_CHECK( helper.GetUseGrid() ); // Test that manual setters work helper.SetGridSize( VECTOR2D( 100, 100 ) ); helper.SetOrigin( VECTOR2I( 50, 50 ) ); helper.SetGridSnapping( true ); VECTOR2I grid = helper.GetGrid(); BOOST_CHECK_EQUAL( grid.x, 100 ); BOOST_CHECK_EQUAL( grid.y, 100 ); VECTOR2I origin = helper.GetOrigin(); BOOST_CHECK_EQUAL( origin.x, 50 ); BOOST_CHECK_EQUAL( origin.y, 50 ); } BOOST_AUTO_TEST_CASE( AlignBasic ) { GRID_HELPER helper; helper.SetGridSize( VECTOR2D( 100, 100 ) ); helper.SetOrigin( VECTOR2I( 0, 0 ) ); helper.SetGridSnapping( true ); // Test basic alignment - should round to nearest grid point VECTOR2I aligned = helper.Align( VECTOR2I( 149, 251 ) ); BOOST_CHECK_EQUAL( aligned.x, 100 ); BOOST_CHECK_EQUAL( aligned.y, 300 ); // Test exact grid points aligned = helper.Align( VECTOR2I( 200, 300 ) ); BOOST_CHECK_EQUAL( aligned.x, 200 ); BOOST_CHECK_EQUAL( aligned.y, 300 ); // Test negative coordinates aligned = helper.Align( VECTOR2I( -149, -251 ) ); BOOST_CHECK_EQUAL( aligned.x, -100 ); BOOST_CHECK_EQUAL( aligned.y, -300 ); } BOOST_AUTO_TEST_CASE( AlignGridWithCustomGrid ) { GRID_HELPER helper; helper.SetGridSize( VECTOR2D( 50, 50 ) ); helper.SetOrigin( VECTOR2I( 0, 0 ) ); helper.SetGridSnapping( true ); VECTOR2I aligned = helper.AlignGrid( VECTOR2I( 26, 74 ) ); BOOST_CHECK_EQUAL( aligned.x, 50 ); BOOST_CHECK_EQUAL( aligned.y, 50 ); // Test AlignGrid with specific grid parameter aligned = helper.AlignGrid( VECTOR2I( 26, 74 ), VECTOR2D( 25, 25 ), VECTOR2D( 0, 0 ) ); BOOST_CHECK_EQUAL( aligned.x, 25 ); BOOST_CHECK_EQUAL( aligned.y, 75 ); } BOOST_AUTO_TEST_CASE( AlignWithOriginOffset ) { GRID_HELPER helper; helper.SetGridSize( VECTOR2D( 100, 100 ) ); helper.SetOrigin( VECTOR2I( 25, 25 ) ); helper.SetGridSnapping( true ); // When grid has an origin offset, alignment should work from the new reference point VECTOR2I aligned = helper.AlignGrid( VECTOR2I( 149, 251 ) ); BOOST_CHECK_EQUAL( aligned.x, 125 ); BOOST_CHECK_EQUAL( aligned.y, 225 ); } BOOST_AUTO_TEST_CASE( AlignWithAuxiliaryAxes ) { GRID_HELPER helper; helper.SetGridSize( VECTOR2D( 100, 100 ) ); helper.SetOrigin( VECTOR2I( 0, 0 ) ); helper.SetGridSnapping( true ); // Set auxiliary axis at (75, 75) helper.SetAuxAxes( true, VECTOR2I( 75, 75 ) ); // Point closer to aux axis than grid should snap to aux axis VECTOR2I aligned = helper.Align( VECTOR2I( 80, 80 ) ); BOOST_CHECK_EQUAL( aligned.x, 75 ); // Closer to aux axis X BOOST_CHECK_EQUAL( aligned.y, 75 ); // Closer to aux axis Y // Point closer to grid than aux axis should snap to grid aligned = helper.Align( VECTOR2I( 95, 95 ) ); BOOST_CHECK_EQUAL( aligned.x, 100 ); // Closer to grid BOOST_CHECK_EQUAL( aligned.y, 100 ); // Closer to grid // Disable aux axes helper.SetAuxAxes( false ); aligned = helper.Align( VECTOR2I( 80, 80 ) ); BOOST_CHECK_EQUAL( aligned.x, 100 ); // Should snap to grid only BOOST_CHECK_EQUAL( aligned.y, 100 ); } BOOST_AUTO_TEST_CASE( GridSnappingDisabled ) { GRID_HELPER helper; helper.SetGridSize( VECTOR2D( 100, 100 ) ); helper.SetOrigin( VECTOR2I( 0, 0 ) ); helper.SetGridSnapping( false ); // Disable grid snapping // When grid snapping is disabled, Align should return original point VECTOR2I original( 149, 251 ); VECTOR2I aligned = helper.Align( original ); BOOST_CHECK_EQUAL( aligned.x, original.x ); BOOST_CHECK_EQUAL( aligned.y, original.y ); // AlignGrid should still work regardless of grid snapping setting aligned = helper.AlignGrid( original ); BOOST_CHECK_EQUAL( aligned.x, 100 ); BOOST_CHECK_EQUAL( aligned.y, 300 ); } BOOST_AUTO_TEST_CASE( UseGridDisabled ) { GRID_HELPER helper; helper.SetGridSize( VECTOR2D( 100, 100 ) ); helper.SetOrigin( VECTOR2I( 0, 0 ) ); helper.SetGridSnapping( true ); helper.SetUseGrid( false ); // Disable grid usage // When grid usage is disabled, Align should return original point VECTOR2I original( 149, 251 ); VECTOR2I aligned = helper.Align( original ); BOOST_CHECK_EQUAL( aligned.x, original.x ); BOOST_CHECK_EQUAL( aligned.y, original.y ); } BOOST_AUTO_TEST_CASE( AsymmetricGrid ) { GRID_HELPER helper; helper.SetGridSize( VECTOR2D( 25, 75 ) ); // Different X and Y grid sizes helper.SetOrigin( VECTOR2I( 0, 0 ) ); helper.SetGridSnapping( true ); VECTOR2I aligned = helper.Align( VECTOR2I( 30, 100 ) ); BOOST_CHECK_EQUAL( aligned.x, 25 ); // Nearest 25-unit boundary BOOST_CHECK_EQUAL( aligned.y, 75 ); // Nearest 75-unit boundary aligned = helper.Align( VECTOR2I( 40, 120 ) ); BOOST_CHECK_EQUAL( aligned.x, 50 ); // Next 25-unit boundary BOOST_CHECK_EQUAL( aligned.y, 150 ); // Next 75-unit boundary } BOOST_AUTO_TEST_CASE( SnapFlags ) { GRID_HELPER helper; // Test snap flag getters/setters BOOST_CHECK( helper.GetSnap() ); // Default should be true helper.SetSnap( false ); BOOST_CHECK( !helper.GetSnap() ); helper.SetSnap( true ); BOOST_CHECK( helper.GetSnap() ); // Test grid usage flag BOOST_CHECK( helper.GetUseGrid() ); // Default should be true helper.SetUseGrid( false ); BOOST_CHECK( !helper.GetUseGrid() ); helper.SetUseGrid( true ); BOOST_CHECK( helper.GetUseGrid() ); } BOOST_AUTO_TEST_CASE( MaskOperations ) { GRID_HELPER helper; // Test mask operations helper.SetMask( GRID_HELPER::CORNER | GRID_HELPER::OUTLINE ); helper.SetMaskFlag( GRID_HELPER::SNAPPABLE ); helper.ClearMaskFlag( GRID_HELPER::CORNER ); // These don't have getters, so we can't verify the mask state directly // but we can verify the methods don't crash } BOOST_AUTO_TEST_CASE( SkipPoint ) { GRID_HELPER helper; // Test skip point operations helper.SetSkipPoint( VECTOR2I( 100, 100 ) ); helper.ClearSkipPoint(); // These methods should not crash } BOOST_AUTO_TEST_CASE( GridTypeAlignment ) { GRID_HELPER helper; helper.SetGridSize( VECTOR2D( 100, 100 ) ); helper.SetOrigin( VECTOR2I( 0, 0 ) ); helper.SetGridSnapping( true ); // Test alignment with specific grid type VECTOR2I aligned = helper.Align( VECTOR2I( 149, 251 ), GRID_CURRENT ); BOOST_CHECK_EQUAL( aligned.x, 100 ); BOOST_CHECK_EQUAL( aligned.y, 300 ); aligned = helper.AlignGrid( VECTOR2I( 149, 251 ), GRID_CURRENT ); BOOST_CHECK_EQUAL( aligned.x, 100 ); BOOST_CHECK_EQUAL( aligned.y, 300 ); } BOOST_AUTO_TEST_CASE( EdgeCases ) { GRID_HELPER helper; helper.SetGridSize( VECTOR2D( 1, 1 ) ); // Very small grid helper.SetOrigin( VECTOR2I( 0, 0 ) ); helper.SetGridSnapping( true ); // Test with very small grid VECTOR2I aligned = helper.Align( VECTOR2I( 5, 5 ) ); BOOST_CHECK_EQUAL( aligned.x, 5 ); BOOST_CHECK_EQUAL( aligned.y, 5 ); // Test with zero point aligned = helper.Align( VECTOR2I( 0, 0 ) ); BOOST_CHECK_EQUAL( aligned.x, 0 ); BOOST_CHECK_EQUAL( aligned.y, 0 ); // Test with large grid helper.SetGridSize( VECTOR2D( 10000, 10000 ) ); aligned = helper.Align( VECTOR2I( 3000, 7000 ) ); BOOST_CHECK_EQUAL( aligned.x, 0 ); // Closer to 0 than 10000 BOOST_CHECK_EQUAL( aligned.y, 10000 ); // Closer to 10000 than 0 } BOOST_AUTO_TEST_CASE( GetGridSize ) { GRID_HELPER helper; // Test GetGridSize with different grid types helper.SetGridSize( VECTOR2D( 50, 75 ) ); VECTOR2D gridSize = helper.GetGridSize( GRID_CURRENT ); BOOST_CHECK_EQUAL( gridSize.x, 50 ); BOOST_CHECK_EQUAL( gridSize.y, 75 ); // Other grid types should return the same in the base implementation gridSize = helper.GetGridSize( GRID_CONNECTABLE ); BOOST_CHECK_EQUAL( gridSize.x, 50 ); BOOST_CHECK_EQUAL( gridSize.y, 75 ); } BOOST_AUTO_TEST_CASE( VisibleGrid ) { GRID_HELPER helper; helper.SetVisibleGridSize( VECTOR2D( 25, 35 ) ); VECTOR2D visibleGrid = helper.GetVisibleGrid(); BOOST_CHECK_EQUAL( visibleGrid.x, 25 ); BOOST_CHECK_EQUAL( visibleGrid.y, 35 ); } BOOST_AUTO_TEST_CASE( SnapPointManagement ) { GRID_HELPER helper; // Initially should have no snapped point auto snappedPoint = helper.GetSnappedPoint(); BOOST_CHECK( !snappedPoint.has_value() ); // After clearing anchors, still no snapped point TEST_CLEAR_ANCHORS( helper ); snappedPoint = helper.GetSnappedPoint(); BOOST_CHECK( !snappedPoint.has_value() ); } BOOST_AUTO_TEST_SUITE_END()