From cc7825d00bb3807c5f55a960af71b446112f6b97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Garc=C3=ADa=20Montoro?= Date: Tue, 7 Mar 2017 13:11:24 +0100 Subject: [PATCH] Tests CPolyLine -> SHAPE_POLY_SET refactor. Adds BOOST tests to the qa folder included in the geometry subdirectory. The tests check whether the refactored code is consistent with the legacy code. They also check some of the new code, as the family of ITERATOR classes. --- qa/CMakeLists.txt | 2 + qa/data/fixtures_geometry.h | 298 ++++++++++++++++++++++++++++ qa/geometry/CMakeLists.txt | 53 +++++ qa/geometry/test_chamfer_fillet.cpp | 159 +++++++++++++++ qa/geometry/test_collision.cpp | 150 ++++++++++++++ qa/geometry/test_iterator.cpp | 133 +++++++++++++ qa/geometry/test_module.cpp | 32 +++ qa/geometry/test_segment.cpp | 59 ++++++ 8 files changed, 886 insertions(+) create mode 100644 qa/data/fixtures_geometry.h create mode 100644 qa/geometry/CMakeLists.txt create mode 100644 qa/geometry/test_chamfer_fillet.cpp create mode 100644 qa/geometry/test_collision.cpp create mode 100644 qa/geometry/test_iterator.cpp create mode 100644 qa/geometry/test_module.cpp create mode 100644 qa/geometry/test_segment.cpp 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()