diff --git a/qa/CMakeLists.txt b/qa/CMakeLists.txt index bd579a5972..330a2c81f7 100644 --- a/qa/CMakeLists.txt +++ b/qa/CMakeLists.txt @@ -9,3 +9,5 @@ if( KICAD_SCRIPTING_MODULES ) ) endif() + +add_subdirectory( geometry ) diff --git a/qa/data/fixtures_geometry.h b/qa/data/fixtures_geometry.h new file mode 100644 index 0000000000..e025d461f2 --- /dev/null +++ b/qa/data/fixtures_geometry.h @@ -0,0 +1,298 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 CERN + * @author Alejandro García Montoro + * + * 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 2 + * 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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __FIXTURES_H +#define __FIXTURES_H + +#include +#include +#include + +/** + * Common data for the tests: + * 1. holeyPolySet: A polyset containing one single squared outline with two holes: a + * non-convex pentagon and a triangle. + * 2.solidPolySet: A polyset with three empty outlines and no holes. + * 3. uniqueVertexPolySet: A polyset with one single outline that contains just one vertex. + * 4. emptyPolySet: A polyset with no outlines. + */ +struct CommonTestData +{ + // Polygon sets common for all the tests + SHAPE_POLY_SET emptyPolySet; + SHAPE_POLY_SET uniqueVertexPolySet; + SHAPE_POLY_SET solidPolySet; + SHAPE_POLY_SET holeyPolySet; + + // Vectors containing the information with which the polygons are populated. + std::vector uniquePoints; + std::vector holeyPoints; + std::vector holeySegments; + + /** + * Constructor. + */ + CommonTestData() + { + // UniqueVertexPolySet shall have a unique vertex + uniquePoints.push_back( VECTOR2I( 100, 50 ) ); + + // Populate the holey polygon set points with 12 points + + // Square + holeyPoints.push_back( VECTOR2I( 100,100 ) ); + holeyPoints.push_back( VECTOR2I( 0,100 ) ); + holeyPoints.push_back( VECTOR2I( 0,0 ) ); + holeyPoints.push_back( VECTOR2I( 100,0 ) ); + + // Pentagon + holeyPoints.push_back( VECTOR2I( 10,10 ) ); + holeyPoints.push_back( VECTOR2I( 10,20 ) ); + holeyPoints.push_back( VECTOR2I( 15,15 ) ); + holeyPoints.push_back( VECTOR2I( 20,20 ) ); + holeyPoints.push_back( VECTOR2I( 20,10 ) ); + + // Triangle + holeyPoints.push_back( VECTOR2I( 40,10 ) ); + holeyPoints.push_back( VECTOR2I( 40,20 ) ); + holeyPoints.push_back( VECTOR2I( 60,10 ) ); + + // Save the segments of the holeyPolySet. + holeySegments.push_back( SEG( holeyPoints[0], holeyPoints[1] ) ); + holeySegments.push_back( SEG( holeyPoints[1], holeyPoints[2] ) ); + holeySegments.push_back( SEG( holeyPoints[2], holeyPoints[3] ) ); + holeySegments.push_back( SEG( holeyPoints[3], holeyPoints[0] ) ); + + // Pentagon segments + holeySegments.push_back( SEG( holeyPoints[4], holeyPoints[5] ) ); + holeySegments.push_back( SEG( holeyPoints[5], holeyPoints[6] ) ); + holeySegments.push_back( SEG( holeyPoints[6], holeyPoints[7] ) ); + holeySegments.push_back( SEG( holeyPoints[7], holeyPoints[8] ) ); + holeySegments.push_back( SEG( holeyPoints[8], holeyPoints[4] ) ); + + // Triangle segments + holeySegments.push_back( SEG( holeyPoints[ 9], holeyPoints[10] ) ); + holeySegments.push_back( SEG( holeyPoints[10], holeyPoints[11] ) ); + holeySegments.push_back( SEG( holeyPoints[11], holeyPoints[9] ) ); + + // Auxiliary variables to store the contours that will be added to the polygons + SHAPE_LINE_CHAIN polyLine, hole; + + // Create a polygon set with a unique vertex + polyLine.Append( uniquePoints[0] ); + polyLine.SetClosed( true ); + uniqueVertexPolySet.AddOutline(polyLine); + + // Create a polygon set without holes + solidPolySet.NewOutline(); + solidPolySet.NewOutline(); + solidPolySet.NewOutline(); + + // Create a polygon set with holes + + // Adds a new squared outline + polyLine.Clear(); + + for( int i = 0; i < 4; i++ ) + polyLine.Append( holeyPoints[i] ); + + polyLine.SetClosed( true ); + + holeyPolySet.AddOutline(polyLine); + + // Adds a new hole (a pentagon) + for( int i = 4; i < 9; i++ ) + hole.Append( holeyPoints[i] ); + + hole.SetClosed( true ); + holeyPolySet.AddHole( hole ); + + + // Adds a new hole (a triangle) + hole.Clear(); + for( int i = 9; i < 12; i++ ) + hole.Append( holeyPoints[i] ); + + hole.SetClosed( true ); + holeyPolySet.AddHole( hole ); + } + + ~CommonTestData(){} +}; + +/** + * Fixture for the ChamferFillet test suite. It contains an instance of the common data and the + * holeyPolySet replicated as a CPolyLine, in order to test behaviour of old and new Chamfer and + * Fillet methods. + */ +struct ChamferFilletFixture { + // Structure to store the common data. + struct CommonTestData common; + + // CPolyLine representing the same polygon in polySet. + CPolyLine legacyPolyLine; + + /** + * Constructor. + */ + ChamferFilletFixture() + { + // Replicate the vertices in the polySet outline + legacyPolyLine.Start( 0, common.holeyPoints[0].x, common.holeyPoints[0].y, + CPolyLine::NO_HATCH ); + + for( int i = 1; i < 4; i++ ) + { + VECTOR2I point = common.holeyPoints[i]; + legacyPolyLine.AppendCorner( point.x, point.y ); + } + + legacyPolyLine.CloseLastContour(); + + // Add the non-convex pentagon hole + legacyPolyLine.Start( 0, common.holeyPoints[4].x, common.holeyPoints[4].y, + CPolyLine::NO_HATCH ); + + for( int i = 5; i < 9; i++ ) + { + VECTOR2I point = common.holeyPoints[i]; + legacyPolyLine.AppendCorner( point.x, point.y ); + } + + legacyPolyLine.CloseLastContour(); + + // Add the triangle hole + legacyPolyLine.Start( 0, common.holeyPoints[9].x, common.holeyPoints[9].y, + CPolyLine::NO_HATCH ); + + for( int i = 10; i < 12; i++ ) + { + VECTOR2I point = common.holeyPoints[i]; + legacyPolyLine.AppendCorner( point.x, point.y ); + } + + legacyPolyLine.CloseLastContour(); + } + + ~ChamferFilletFixture(){} +}; + +/** + * Fixture for the Collision test suite. It contains an instance of the common data and two + * vectors containing colliding and non-colliding points. + */ +struct CollisionFixture { + // Structure to store the common data. + struct CommonTestData common; + + // Vectors containing colliding and non-colliding points + std::vector collidingPoints, nonCollidingPoints; + + /** + * Constructor + */ + CollisionFixture() + { + // Create points colliding with the poly set. + + // Inside the polygon + collidingPoints.push_back( VECTOR2I( 10,90 ) ); + + // Inside the polygon, but on a re-entrant angle of a hole + collidingPoints.push_back( VECTOR2I( 15,16 ) ); + + // On a hole edge => inside the polygon + collidingPoints.push_back( VECTOR2I( 40,25 ) ); + + // On the outline edge => inside the polygon + collidingPoints.push_back( VECTOR2I( 0,10 ) ); + + // Create points not colliding with the poly set. + + // Completely outside of the polygon + nonCollidingPoints.push_back( VECTOR2I( 200,200 ) ); + + // Inside the outline and inside a hole => outside the polygon + nonCollidingPoints.push_back( VECTOR2I( 15,12 ) ); + } + + ~CollisionFixture(){} +}; + +/** +* Fixture for the Iterator test suite. It contains an instance of the common data, three polysets with null segments and a vector containing their points. +*/ +struct IteratorFixture { + // Structure to store the common data. + struct CommonTestData common; + + // Polygons to test whether the RemoveNullSegments method works + SHAPE_POLY_SET lastNullSegmentPolySet; + SHAPE_POLY_SET firstNullSegmentPolySet; + SHAPE_POLY_SET insideNullSegmentPolySet; + + // Null segments points + std::vector nullPoints; + + IteratorFixture() + { + nullPoints.push_back( VECTOR2I( 100,100 ) ); + nullPoints.push_back( VECTOR2I( 0,100 ) ); + nullPoints.push_back( VECTOR2I( 0, 0 ) ); + + // Create a polygon with its last segment null + SHAPE_LINE_CHAIN polyLine; + polyLine.Append( nullPoints[0] ); + polyLine.Append( nullPoints[1] ); + polyLine.Append( nullPoints[2] ); + polyLine.Append( nullPoints[2], true ); + polyLine.SetClosed( true ); + + lastNullSegmentPolySet.AddOutline(polyLine); + + // Create a polygon with its first segment null + polyLine.Clear(); + polyLine.Append( nullPoints[0] ); + polyLine.Append( nullPoints[0], true ); + polyLine.Append( nullPoints[1] ); + polyLine.Append( nullPoints[2] ); + polyLine.SetClosed( true ); + + firstNullSegmentPolySet.AddOutline(polyLine); + + // Create a polygon with an inside segment null + polyLine.Clear(); + polyLine.Append( nullPoints[0] ); + polyLine.Append( nullPoints[1] ); + polyLine.Append( nullPoints[1], true ); + polyLine.Append( nullPoints[2] ); + polyLine.SetClosed( true ); + + insideNullSegmentPolySet.AddOutline(polyLine); + } + + ~IteratorFixture(){} +}; + +#endif //__FIXTURES_H diff --git a/qa/geometry/CMakeLists.txt b/qa/geometry/CMakeLists.txt new file mode 100644 index 0000000000..51bd00e81d --- /dev/null +++ b/qa/geometry/CMakeLists.txt @@ -0,0 +1,53 @@ +# +# This program source code file is part of KiCad, a free EDA CAD application. +# +# Copyright (C) 2017 CERN +# @author Alejandro García Montoro +# +# 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 2 +# 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, you may find one here: +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html +# or you may search the http://www.gnu.org website for the version 2 license, +# or you may write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +find_package(Boost COMPONENTS system filesystem unit_test_framework REQUIRED) +find_package( wxWidgets 3.0.0 COMPONENTS gl aui adv html core net base xml stc REQUIRED ) + +add_executable(qa_geometry + test_module.cpp + test_chamfer_fillet.cpp + test_collision.cpp + test_iterator.cpp + test_segment.cpp +) + +include_directories( + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/polygon + ${CMAKE_SOURCE_DIR}/common/geometry +) + +target_link_libraries(qa_geometry + ${CMAKE_BINARY_DIR}/polygon/libpolygon.a + ${CMAKE_BINARY_DIR}/common/libcommon.a + ${CMAKE_BINARY_DIR}/bitmaps_png/libbitmaps.a + ${CMAKE_BINARY_DIR}/polygon/libpolygon.a + ${Boost_FILESYSTEM_LIBRARY} + ${Boost_SYSTEM_LIBRARY} + ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} + ${wxWidgets_LIBRARIES} +) + +add_dependencies( qa_geometry pcbnew ) diff --git a/qa/geometry/test_chamfer_fillet.cpp b/qa/geometry/test_chamfer_fillet.cpp new file mode 100644 index 0000000000..8d5c9f4754 --- /dev/null +++ b/qa/geometry/test_chamfer_fillet.cpp @@ -0,0 +1,159 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 CERN + * @author Alejandro García Montoro + * + * 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 2 + * 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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include + +#include + +/** + * Declares the ChamferFilletFixture struct as the boost test fixture. + */ +BOOST_FIXTURE_TEST_SUITE( ChamferFillet, ChamferFilletFixture ) + +/** + * Function lexicographicOrder + * defines a lexicographic order between two VECTOR2I objects. Used along with std::sort + * when checking that two polygons have the same vertices. + * @param i is a VECTOR2I object. + * @param j is a VECTOR2I object. + * @return bool - true if (i.x, i.y) < (j.x, j.y) using the lexicographic order, + * i.e., i.x < j.x or i.x = j.x and i.y < j.y; false in any other case. + */ +bool lexicographicOrder( VECTOR2I i, VECTOR2I j ) +{ + if( i.x != j.x ) + return( i.x < j.x ); + else + return( i.y < j.y ); +} + +/** + * Function TestLineChainEqualCPolyLine + * tests the equality between a SHAPE_LINE_CHAIN polygon and a polygon inside a + * CPolyLine object using Boost test suite. + * @param lineChain is a SHAPE_LINE_CHAIN polygon object. + * @param polyLine is a CPolyLine polygon object. + * @param contourIdx is the index of the contour inside polyLine that has to be tested + * against lineChain. + */ +void TestLineChainEqualCPolyLine(SHAPE_LINE_CHAIN& lineChain, CPolyLine& polyLine, + int contourIdx = 0) +{ + // Arrays to store the polygon points lexicographically ordered + std::vector chainPoints; + std::vector polyPoints; + + // Populate the array storing the new data with the lineChain corners + for (int pointIdx = 0; pointIdx < lineChain.PointCount(); pointIdx++) { + chainPoints.push_back(lineChain.Point(pointIdx)); + } + + int start = polyLine.GetContourStart(contourIdx); + int end = polyLine.GetContourEnd(contourIdx); + + // Populate the array storing the legacy data with the polyLine corners + for (int pointIdx = start; pointIdx <= end; pointIdx++) { + polyPoints.push_back( VECTOR2I(polyLine.GetX(pointIdx), polyLine.GetY(pointIdx)) ); + } + + // Order the vectors in a lexicographic way + std::sort(chainPoints.begin(), chainPoints.end(), lexicographicOrder); + std::sort(polyPoints.begin(), polyPoints.end(), lexicographicOrder); + + // Compare every point coordinate to check the equality + BOOST_CHECK_EQUAL_COLLECTIONS(chainPoints.begin(), chainPoints.end(), + polyPoints.begin(), polyPoints.end()); +} + +/** + * Tests the SHAPE_POLY_SET::ChamferPolygon, which has been refactored into SHAPE_POLY_SET from + * CPolyLine::Chamfer. Assuming the code in CPolyLine is right, this test ensures the behaviour of + * the new refactored code does not change anything. + */ +BOOST_AUTO_TEST_CASE( Chamfer ) +{ + SHAPE_POLY_SET::POLYGON actual; + CPolyLine expected; + + // Test different distances, up to the half of the minimum segment longitude + for (int distance = 0; distance < 5; distance++) { + // Chamfered polygon to be tested. + actual = common.holeyPolySet.ChamferPolygon( distance, 0 ); + + // Chamfered polygon assumed to be right. + expected = *legacyPolyLine.Chamfer( distance ); + + // Double check that there are no repeated corners in the legacy shape. + expected.RemoveNullSegments(); + + // Test equality + for (size_t contourIdx = 0; contourIdx < actual.size(); contourIdx++) + { + TestLineChainEqualCPolyLine(actual[contourIdx], expected, contourIdx); + } + } +} + +/** + * Tests the SHAPE_POLY_SET::FilletPolygon, which has been refactored into + * SHAPE_POLY_SET from CPolyLine::Fillet. + * Assuming the code in CPolyLine is right, this test ensures the behaviour of the new + * refactored code does not change anything. + */ +BOOST_AUTO_TEST_CASE( Fillet ) +{ + SHAPE_POLY_SET::POLYGON actual; + CPolyLine expected; + + // Test different radius, up to the half of the minimum segment longitude + for (int radius = 1; radius < 5; radius++) + { + // Test different number of segments + for (size_t segments = 1; segments < 100; segments++) + { + // Chamfered polygon to be tested. + actual = common.holeyPolySet.FilletPolygon( radius, segments, 0 ); + + // Chamfered polygon assumed to be right. + expected = *legacyPolyLine.Fillet( radius, segments ); + + // Double check that there are no repeated corners in the legacy shape. + expected.RemoveNullSegments(); + + // Test equality + for (size_t contourIdx = 0; contourIdx < actual.size(); contourIdx++) + { + TestLineChainEqualCPolyLine(actual[contourIdx], expected, contourIdx); + } + } + } +} + + +BOOST_AUTO_TEST_SUITE_END() diff --git a/qa/geometry/test_collision.cpp b/qa/geometry/test_collision.cpp new file mode 100644 index 0000000000..850b0d988a --- /dev/null +++ b/qa/geometry/test_collision.cpp @@ -0,0 +1,150 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 CERN + * @author Alejandro García Montoro + * + * 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 2 + * 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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include + +#include + +/** + * Declares the CollisionFixture as the boost test suite fixture. + */ +BOOST_FIXTURE_TEST_SUITE( Collision, CollisionFixture ) + +/** + * Simple dummy test to check that HasHoles() definition is right + */ +BOOST_AUTO_TEST_CASE( HasHoles ) +{ + BOOST_CHECK( !common.solidPolySet.HasHoles() ); + BOOST_CHECK( common.holeyPolySet.HasHoles() ); +} + +/** + * This test checks basic behaviour of PointOnEdge, testing if points on corners, outline edges + * and hole edges are detected as colliding. + */ +BOOST_AUTO_TEST_CASE( PointOnEdge ) +{ + // Check points on corners + BOOST_CHECK( common.holeyPolySet.PointOnEdge( VECTOR2I( 0,50 ) ) ); + + // Check points on outline edges + BOOST_CHECK( common.holeyPolySet.PointOnEdge( VECTOR2I( 0,10 ) ) ); + + // Check points on hole edges + BOOST_CHECK( common.holeyPolySet.PointOnEdge( VECTOR2I( 10,11 ) ) ); + + // Check points inside a hole -> not in edge + BOOST_CHECK( !common.holeyPolySet.PointOnEdge( VECTOR2I( 12,12 ) ) ); + + // Check points inside the polygon and outside any hole -> not on edge + BOOST_CHECK( !common.holeyPolySet.PointOnEdge( VECTOR2I( 90,90 ) ) ); + + // Check points outside the polygon -> not on edge + BOOST_CHECK( !common.holeyPolySet.PointOnEdge( VECTOR2I( 200,200 ) ) ); +} + +/** + * This test checks that the function Contains, whose behaviour has been updated to also manage + * holey polygons, does the right work. + */ +BOOST_AUTO_TEST_CASE( pointInPolygonSet ) +{ + // Check that the set contains the points that collide with it + for( const VECTOR2I& point : collidingPoints ) + { + BOOST_CHECK( common.holeyPolySet.Contains( point ) ); + } + + // Check that the set does not contain any point outside of it + for( const VECTOR2I& point : nonCollidingPoints ) + { + BOOST_CHECK( !common.holeyPolySet.Contains( point ) ); + } +} + +/** + * This test checks the behaviour of the Collide (with a point) method. + */ +BOOST_AUTO_TEST_CASE( Collide ) +{ + // When clearance = 0, the behaviour should be the same as with Contains + + // Check that the set collides with the colliding points + for( const VECTOR2I& point : collidingPoints ) + { + BOOST_CHECK( common.holeyPolySet.Collide( point, 0 ) ); + } + + // Check that the set does not collide with the non colliding points + for( const VECTOR2I& point : nonCollidingPoints ) + { + BOOST_CHECK( !common.holeyPolySet.Collide( point, 0 ) ); + } + + // Checks with clearance > 0 + + // Point at the offset zone outside of the outline => collision! + BOOST_CHECK( common.holeyPolySet.Collide( VECTOR2I( -1,10 ), 5 ) ); + + // Point at the offset zone outside of a hole => collision! + BOOST_CHECK( common.holeyPolySet.Collide( VECTOR2I( 11,11 ), 5 ) ); +} + +/** + * This test checks the behaviour of the CollideVertex method, testing whether the collision with + * vertices is well detected + */ +BOOST_AUTO_TEST_CASE( CollideVertex ) +{ + // Variable to store the index of the corner hit + SHAPE_POLY_SET::VERTEX_INDEX cornerHit; + + // Check that the set collides with the colliding points + for( const VECTOR2I& point : common.holeyPoints ) + { + BOOST_CHECK( common.holeyPolySet.CollideVertex( point, cornerHit, 0 ) ); + } +} + +/** + * This test checks the behaviour of the CollideVertex method, testing whether the collision with + * vertices is well detected + */ +BOOST_AUTO_TEST_CASE( CollideVertexWithClearance ) +{ + // Variable to store the index of the corner hit + SHAPE_POLY_SET::VERTEX_INDEX cornerHit; + + // Check that the set collides with the colliding points + for( const VECTOR2I& point : common.holeyPoints ) + { + BOOST_CHECK( common.holeyPolySet.CollideVertex( point + VECTOR2I(1,1), cornerHit, 2 ) ); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/qa/geometry/test_iterator.cpp b/qa/geometry/test_iterator.cpp new file mode 100644 index 0000000000..b4876a55fa --- /dev/null +++ b/qa/geometry/test_iterator.cpp @@ -0,0 +1,133 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 CERN + * @author Alejandro García Montoro + * + * 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 2 + * 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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include + +#include + +/** + * Declares the IteratorFixture as the boost test suite fixture. + */ +BOOST_FIXTURE_TEST_SUITE( PolygonIterator, IteratorFixture ) + +/** + * Checks whether the iteration on the vertices of a common polygon is correct. + */ +BOOST_AUTO_TEST_CASE( VertexIterator ) +{ + SHAPE_POLY_SET::ITERATOR iterator; + int vertexIndex = 0; + + for( iterator = common.holeyPolySet.IterateWithHoles(); iterator; iterator++ ) + { + BOOST_CHECK_EQUAL( common.holeyPoints[vertexIndex], *iterator ); + vertexIndex++; + } +} + +/** + * Checks whether the iteration on the segments of a common polygon is correct. + */ +BOOST_AUTO_TEST_CASE( SegmentIterator ) +{ + SHAPE_POLY_SET::SEGMENT_ITERATOR iterator; + int segmentIndex = 0; + + for( iterator = common.holeyPolySet.IterateSegmentsWithHoles(); iterator; iterator++ ){ + SEG segment = *iterator; + + BOOST_CHECK_EQUAL( common.holeySegments[segmentIndex].A, segment.A ); + BOOST_CHECK_EQUAL( common.holeySegments[segmentIndex].B, segment.B ); + + segmentIndex++; + } +} + +/** + * Checks whether the iteration on the segments of an empty polygon is correct. + */ +BOOST_AUTO_TEST_CASE( EmptyPolygon ) +{ + SHAPE_POLY_SET::SEGMENT_ITERATOR iterator; + + for( iterator = common.emptyPolySet.IterateSegmentsWithHoles(); iterator; iterator++ ) + { + BOOST_FAIL( "Empty set is being iterated!" ); + } +} + +/** + * Checks whether the iteration on the segments of a polygon with one vertex is correct. + */ +BOOST_AUTO_TEST_CASE( UniqueVertex ) +{ + SHAPE_POLY_SET::SEGMENT_ITERATOR iterator; + iterator = common.uniqueVertexPolySet.IterateSegmentsWithHoles(); + + SEG segment = *iterator; + BOOST_CHECK_EQUAL( segment.A, common.uniquePoints[0] ); + BOOST_CHECK_EQUAL( segment.B, common.uniquePoints[0] ); + + iterator++; + + BOOST_CHECK( !iterator ); +} + +/** + * Checks whether the counting of the total number of vertices is correct. + */ +BOOST_AUTO_TEST_CASE( TotalVertices ) +{ + BOOST_CHECK_EQUAL( common.emptyPolySet.TotalVertices(), 0 ); + BOOST_CHECK_EQUAL( common.uniqueVertexPolySet.TotalVertices(), 1 ); + BOOST_CHECK_EQUAL( common.solidPolySet.TotalVertices(), 0 ); + BOOST_CHECK_EQUAL( common.holeyPolySet.TotalVertices(), 12 ); +} + +/** + * Checks whether the removal of null segments, wherever they are placed, is correct. + */ +BOOST_AUTO_TEST_CASE( RemoveNullSegments ) +{ + SHAPE_POLY_SET polygonSets[3] = {lastNullSegmentPolySet, + firstNullSegmentPolySet, + insideNullSegmentPolySet}; + + for( SHAPE_POLY_SET polygonSet : polygonSets ) + { + BOOST_CHECK_EQUAL( polygonSet.TotalVertices(), 4 ); + BOOST_CHECK_EQUAL( polygonSet.RemoveNullSegments(), 1); + BOOST_CHECK_EQUAL( polygonSet.TotalVertices(), 3 ); + + BOOST_CHECK_EQUAL( polygonSet.CVertex(0), nullPoints[0] ); + BOOST_CHECK_EQUAL( polygonSet.CVertex(1), nullPoints[1] ); + BOOST_CHECK_EQUAL( polygonSet.CVertex(2), nullPoints[2] ); + } +} + + +BOOST_AUTO_TEST_SUITE_END() diff --git a/qa/geometry/test_module.cpp b/qa/geometry/test_module.cpp new file mode 100644 index 0000000000..79fe6a9038 --- /dev/null +++ b/qa/geometry/test_module.cpp @@ -0,0 +1,32 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 CERN + * @author Alejandro García Montoro + * + * 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 2 + * 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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * Main file for the geometry tests to be compiled + */ + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE "CPolyLine -> SHAPE_POLY_SET refactor module" + +#include diff --git a/qa/geometry/test_segment.cpp b/qa/geometry/test_segment.cpp new file mode 100644 index 0000000000..c37a7fa184 --- /dev/null +++ b/qa/geometry/test_segment.cpp @@ -0,0 +1,59 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 CERN + * @author Alejandro García Montoro + * + * 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 2 + * 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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include + +#include + +/** + * Declares the IteratorFixture as the boost test suite fixture. + */ +BOOST_FIXTURE_TEST_SUITE( SegmentReference, CommonTestData ) + +/** + * Checks whether the construction of a segment referencing external points works. + */ +BOOST_AUTO_TEST_CASE( SegmentReference ) +{ + VECTOR2I A( 10, 20 ); + VECTOR2I B( 100, 200 ); + + // Build a segment referencing the previous points + SEG segment(A, B); + + BOOST_CHECK_EQUAL( A, VECTOR2I( 10, 20) ); + BOOST_CHECK_EQUAL( B, VECTOR2I( 100, 200) ); + + // Modify the ends of the segments + segment.A += VECTOR2I( 10, 10 ); + segment.B += VECTOR2I( 100, 100 ); + + // Check that the original points are also modified + BOOST_CHECK_EQUAL( A, VECTOR2I( 20, 30) ); + BOOST_CHECK_EQUAL( B, VECTOR2I( 200, 300) ); +} + +BOOST_AUTO_TEST_SUITE_END()