From 419718b596bec4f6a1817dd809e57369b77773a0 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Mon, 7 Jan 2019 20:24:11 +0100 Subject: [PATCH] Remove a useless qa test. It was added when refactoring the SHAPE_POLY_SET class, ande replace any use of CPolyLine class inside Kicad code. the CPolyLine related code is now not used. So this test nowadays makes no longer sense. --- polygon/CMakeLists.txt | 1 - polygon/PolyLine.cpp | 1396 ------------------- polygon/PolyLine.h | 494 ------- polygon/polygon_test_point_inside.cpp | 68 - polygon/polygon_test_point_inside.h | 19 - qa/data/fixtures_geometry.h | 57 - qa/shape_poly_set_refactor/CMakeLists.txt | 1 - qa/shape_poly_set_refactor/test_chamfer.cpp | 124 -- 8 files changed, 2160 deletions(-) delete mode 100644 polygon/PolyLine.cpp delete mode 100644 polygon/PolyLine.h delete mode 100644 qa/shape_poly_set_refactor/test_chamfer.cpp diff --git a/polygon/CMakeLists.txt b/polygon/CMakeLists.txt index cd5959ef31..4399614058 100644 --- a/polygon/CMakeLists.txt +++ b/polygon/CMakeLists.txt @@ -10,7 +10,6 @@ include_directories( set(POLYGON_SRCS math_for_graphics.cpp - PolyLine.cpp polygon_test_point_inside.cpp clipper.cpp ) diff --git a/polygon/PolyLine.cpp b/polygon/PolyLine.cpp deleted file mode 100644 index 8d7770b2c7..0000000000 --- a/polygon/PolyLine.cpp +++ /dev/null @@ -1,1396 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Few parts of this code come from FreePCB, released under the GNU General Public License V2. - * (see http://www.freepcb.com/ ) - * - * Copyright (C) 2012-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 2012-2015 KiCad Developers, see CHANGELOG.TXT for contributors. - * - * 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 - */ - -/** - * @file PolyLine.cpp - * @note implementation of CPolyLine class - */ - -// -// implementation for kicad, using clipper polygon clipping library -// for transformations not handled (at least for Kicad) by boost::polygon -// -#include -#include -#include - -#include -#include // KiROUND - -#include -#include -#include -#include -#include - - -CPolyLine::CPolyLine() -{ - m_hatchStyle = NO_HATCH; - m_hatchPitch = 0; - m_layer = F_Cu; - m_flags = 0; -} - -CPolyLine::CPolyLine( const CPolyLine& aCPolyLine) -{ - Copy( &aCPolyLine ); - m_HatchLines = aCPolyLine.m_HatchLines; // vector <> copy -} - - -// destructor, removes display elements -// -CPolyLine::~CPolyLine() -{ - UnHatch(); -} - - -/* - * Removes corners which create a null segment edge - * (i.e. when 2 successive corners are at the same location) - * returns the count of removed corners. - */ -int CPolyLine::RemoveNullSegments() -{ - int removed = 0; - unsigned startcountour = 0; - - for( unsigned icnt = 1; icnt < m_CornersList.GetCornersCount(); icnt ++ ) - { - unsigned last = icnt-1; - if( m_CornersList[icnt].end_contour ) - { - last = startcountour; - startcountour = icnt+1; - } - - if( ( m_CornersList[last].x == m_CornersList[icnt].x ) && - ( m_CornersList[last].y == m_CornersList[icnt].y ) ) - { - DeleteCorner( icnt ); - icnt--; - removed ++; - } - - if( m_CornersList[icnt].end_contour ) - { - startcountour = icnt+1; - icnt++; - } - } - - return removed; -} - - -/* Convert a self-intersecting polygon to one (or more) non self-intersecting polygon(s) - * and removes null segments. - * param aNewPolygonList = a std::vector reference where to store new CPolyLine - * needed by the normalization - * return the polygon count (always >= 1, because there is at least one polygon) - * There are new polygons only if the polygon count is > 1 - */ -int CPolyLine::NormalizeAreaOutlines( std::vector* aNewPolygonList ) -{ - SHAPE_POLY_SET polySet = ConvertPolyListToPolySet( m_CornersList ); - - // We are expecting only one main outline, but this main outline can have holes - // if holes: combine holes and remove them from the main outline. - // Note also we are using SHAPE_POLY_SET::PM_STRICTLY_SIMPLE in polygon - // calculations, but it is not mandatory. It is used mainly - // because there is usually only very few vertices in area outlines - SHAPE_POLY_SET::POLYGON& outline = polySet.Polygon( 0 ); - SHAPE_POLY_SET holesBuffer; - - // Move holes stored in outline to holesBuffer: - // The first SHAPE_LINE_CHAIN is the main outline, others are holes - while( outline.size() > 1 ) - { - holesBuffer.AddOutline( outline.back() ); - outline.pop_back(); - } - - polySet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE); - - // If any hole, substract it to main outline - if( holesBuffer.OutlineCount() ) - { - holesBuffer.Simplify( SHAPE_POLY_SET::PM_FAST); - polySet.BooleanSubtract( holesBuffer, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); - } - - RemoveAllContours(); - - // Note: we can have more than outline, because a self intersecting outline will be - // broken to non intersecting polygons, and removing holes can also create a few polygons - for( int ii = 0; ii < polySet.OutlineCount(); ii++ ) - { - CPolyLine* polyline = this; - - if( ii > 0 ) - { - polyline = new CPolyLine; - polyline->ImportSettings( this ); - aNewPolygonList->push_back( polyline ); - } - - SHAPE_POLY_SET pnew; - pnew.NewOutline(); - pnew.Polygon( 0 ) = polySet.CPolygon( ii ); - - polyline->m_CornersList = ConvertPolySetToPolyList( pnew ); - polyline->RemoveNullSegments(); - } - - return polySet.OutlineCount(); -} - - -/** - * Function ImportSettings - * Copy settings (layer, hatch styles) from aPoly - */ -void CPolyLine::ImportSettings( const CPolyLine * aPoly ) -{ - SetLayer( aPoly->GetLayer() ); - SetHatchStyle( aPoly->GetHatchStyle() ); - SetHatchPitch( aPoly->GetHatchPitch() ); -} - - -/* initialize a contour - * set layer, hatch style, and starting point - */ -void CPolyLine::Start( LAYER_NUM layer, int x, int y, int hatch ) -{ - m_layer = layer; - SetHatchStyle( (enum HATCH_STYLE) hatch ); - CPolyPt poly_pt( x, y ); - poly_pt.end_contour = false; - - m_CornersList.Append( poly_pt ); -} - - -// add a corner to unclosed polyline -// -void CPolyLine::AppendCorner( int x, int y ) -{ - UnHatch(); - CPolyPt poly_pt( x, y ); - poly_pt.end_contour = false; - - // add entries for new corner - m_CornersList.Append( poly_pt ); -} - - -// move corner of polyline -// -void CPolyLine::MoveCorner( int ic, int x, int y ) -{ - UnHatch(); - m_CornersList[ic].x = x; - m_CornersList[ic].y = y; - Hatch(); -} - - -// delete corner and adjust arrays -// -void CPolyLine::DeleteCorner( int ic ) -{ - UnHatch(); - int icont = GetContour( ic ); - int iend = GetContourEnd( icont ); - bool closed = icont < GetContoursCount() - 1 || GetClosed(); - - if( !closed ) - { - // open contour, must be last contour - m_CornersList.DeleteCorner( ic ); - } - else - { - // closed contour - m_CornersList.DeleteCorner( ic ); - - if( ic == iend ) - m_CornersList[ic - 1].end_contour = true; - } - - if( closed && GetContourSize( icont ) < 3 ) - { - // delete the entire contour - RemoveContour( icont ); - } -} - - -/** - * Function RemoveContour - * @param icont = contour number to remove - * remove a contour only if there is more than 1 contour - */ -void CPolyLine::RemoveContour( int icont ) -{ - UnHatch(); - int istart = GetContourStart( icont ); - int iend = GetContourEnd( icont ); - - int polycount = GetContoursCount(); - - if( icont == 0 && polycount == 1 ) - { - // remove the only contour - wxASSERT( 0 ); - } - else - { - // remove closed contour - for( int ic = iend; ic>=istart; ic-- ) - { - m_CornersList.DeleteCorner( ic ); - } - } - - Hatch(); -} - - -CPolyLine* CPolyLine::Chamfer( unsigned int aDistance ) -{ - // Null segments create serious issues in calculations. - // remove them: - RemoveNullSegments(); - - CPolyLine* newPoly = new CPolyLine; - - if( !aDistance ) - { - newPoly->Copy( this ); - return newPoly; - } - - int polycount = GetContoursCount(); - - for( int contour = 0; contour < polycount; contour++ ) - { - unsigned int startIndex = GetContourStart( contour ); - unsigned int endIndex = GetContourEnd( contour ); - - for( unsigned int index = startIndex; index <= endIndex; index++ ) - { - // Current vertex - int x1 = m_CornersList[index].x; - int y1 = m_CornersList[index].y; - double xa, ya; // Previous vertex - double xb, yb; // Next vertex - - if( index == startIndex ) - { - xa = m_CornersList[endIndex].x - x1; - ya = m_CornersList[endIndex].y - y1; - } - else - { - xa = m_CornersList[index - 1].x - x1; - ya = m_CornersList[index - 1].y - y1; - } - - if( index == endIndex ) - { - xb = m_CornersList[startIndex].x - x1; - yb = m_CornersList[startIndex].y - y1; - } - else - { - xb = m_CornersList[index + 1].x - x1; - yb = m_CornersList[index + 1].y - y1; - } - - double lena = hypot( xa, ya ); - double lenb = hypot( xb, yb ); - double distance = aDistance; - - // Chamfer one half of an edge at most - if( 0.5 * lena < distance ) - distance = 0.5 * lena; - - if( 0.5 * lenb < distance ) - distance = 0.5 * lenb; - - int nx1 = KiROUND( distance * xa / lena ); - int ny1 = KiROUND( distance * ya / lena ); - - if( index == startIndex ) - newPoly->Start( GetLayer(), x1 + nx1, y1 + ny1, GetHatchStyle() ); - else - newPoly->AppendCorner( x1 + nx1, y1 + ny1 ); - - int nx2 = KiROUND( distance * xb / lenb ); - int ny2 = KiROUND( distance * yb / lenb ); - - // Due to rounding errors, repeated corners could be added; this check prevents it - if(nx1 != nx2 || ny1 != ny2) - newPoly->AppendCorner( x1 + nx2, y1 + ny2 ); - } - - newPoly->CloseLastContour(); - } - - return newPoly; -} - - -CPolyLine* CPolyLine::Fillet( unsigned int aRadius, unsigned int aSegments ) -{ - // Null segments create serious issues in calculations. - // remove them: - RemoveNullSegments(); - - CPolyLine* newPoly = new CPolyLine; - - if( !aRadius ) - { - newPoly->Copy( this ); - return newPoly; - } - - int polycount = GetContoursCount(); - - for( int contour = 0; contour < polycount; contour++ ) - { - unsigned int startIndex = GetContourStart( contour ); - unsigned int endIndex = GetContourEnd( contour ); - - for( unsigned int index = startIndex; index <= endIndex; index++ ) - { - // Current vertex - int x1 = m_CornersList[index].x; - int y1 = m_CornersList[index].y; - double xa, ya; // Previous vertex - double xb, yb; // Next vertex - - if( index == startIndex ) - { - xa = m_CornersList[endIndex].x - x1; - ya = m_CornersList[endIndex].y - y1; - } - else - { - xa = m_CornersList[index - 1].x - x1; - ya = m_CornersList[index - 1].y - y1; - } - - if( index == endIndex ) - { - xb = m_CornersList[startIndex].x - x1; - yb = m_CornersList[startIndex].y - y1; - } - else - { - xb = m_CornersList[index + 1].x - x1; - yb = m_CornersList[index + 1].y - y1; - } - - double lena = hypot( xa, ya ); - double lenb = hypot( xb, yb ); - double cosine = ( xa * xb + ya * yb ) / ( lena * lenb ); - - double radius = aRadius; - double denom = sqrt( 2.0 / ( 1 + cosine ) - 1 ); - - // Do nothing in case of parallel edges - if( std::isinf( denom ) ) - continue; - - // Limit rounding distance to one half of an edge - if( 0.5 * lena * denom < radius ) - radius = 0.5 * lena * denom; - - if( 0.5 * lenb * denom < radius ) - radius = 0.5 * lenb * denom; - - // Calculate fillet arc absolute center point (xc, yx) - double k = radius / sqrt( .5 * ( 1 - cosine ) ); - double lenab = sqrt( ( xa / lena + xb / lenb ) * ( xa / lena + xb / lenb ) + - ( ya / lena + yb / lenb ) * ( ya / lena + yb / lenb ) ); - double xc = x1 + k * ( xa / lena + xb / lenb ) / lenab; - double yc = y1 + k * ( ya / lena + yb / lenb ) / lenab; - - // Calculate arc start and end vectors - k = radius / sqrt( 2 / ( 1 + cosine ) - 1 ); - double xs = x1 + k * xa / lena - xc; - double ys = y1 + k * ya / lena - yc; - double xe = x1 + k * xb / lenb - xc; - double ye = y1 + k * yb / lenb - yc; - - // Cosine of arc angle - double argument = ( xs * xe + ys * ye ) / ( radius * radius ); - - if( argument < -1 ) // Just in case... - argument = -1; - else if( argument > 1 ) - argument = 1; - - double arcAngle = acos( argument ); - - // Calculate the number of segments - double tempSegments = (double) aSegments * ( arcAngle / ( 2 * M_PI ) ); - - if( tempSegments - (int) tempSegments > 0 ) - tempSegments++; - - unsigned int segments = (unsigned int) tempSegments; - - double deltaAngle = arcAngle / segments; - double startAngle = atan2( -ys, xs ); - - // Flip arc for inner corners - if( xa * yb - ya * xb <= 0 ) - deltaAngle *= -1; - - double nx = xc + xs; - double ny = yc + ys; - - if( index == startIndex ) - newPoly->Start( GetLayer(), KiROUND( nx ), KiROUND( ny ), GetHatchStyle() ); - else - newPoly->AppendCorner( KiROUND( nx ), KiROUND( ny ) ); - - // Store the previous added corner to make a sanity check - int prevX = KiROUND(nx); - int prevY = KiROUND(ny); - - for( unsigned int j = 0; j < segments; j++ ) - { - nx = xc + cos( startAngle + (j + 1) * deltaAngle ) * radius; - ny = yc - sin( startAngle + (j + 1) * deltaAngle ) * radius; - - // Due to rounding errors, repeated corners could be added; this check prevents it - if(KiROUND(nx) != prevX || KiROUND(ny) != prevY) - { - newPoly->AppendCorner( KiROUND( nx ), KiROUND( ny ) ); - prevX = KiROUND(nx); - prevY = KiROUND(ny); - } - } - } - - newPoly->CloseLastContour(); - } - - return newPoly; -} - - -/** - * function RemoveAllContours - * removes all corners from the list. - * Others params are not changed - */ -void CPolyLine::RemoveAllContours() -{ - m_CornersList.RemoveAllContours(); -} - - -/** - * Function InsertCorner - * insert a new corner between two existing corners - * @param ic = index for the insertion point: the corner is inserted AFTER ic - * @param x, y = coordinates corner to insert - */ -void CPolyLine::InsertCorner( int ic, int x, int y ) -{ - UnHatch(); - - if( (unsigned) (ic) >= m_CornersList.GetCornersCount() ) - { - m_CornersList.Append( CPolyPt( x, y ) ); - } - else - { - m_CornersList.InsertCorner(ic, CPolyPt( x, y ) ); - } - - if( (unsigned) (ic + 1) < m_CornersList.GetCornersCount() ) - { - if( m_CornersList[ic].end_contour ) - { - m_CornersList[ic + 1].end_contour = true; - m_CornersList[ic].end_contour = false; - } - } - - Hatch(); -} - - -// undraw polyline by removing all graphic elements from display list -void CPolyLine::UnHatch() -{ - m_HatchLines.clear(); -} - - -const EDA_RECT CPolyLine::GetBoundingBox() -{ - int xmin = INT_MAX; - int ymin = INT_MAX; - int xmax = INT_MIN; - int ymax = INT_MIN; - - for( unsigned i = 0; i< m_CornersList.GetCornersCount(); i++ ) - { - xmin = std::min( xmin, m_CornersList[i].x ); - xmax = std::max( xmax, m_CornersList[i].x ); - ymin = std::min( ymin, m_CornersList[i].y ); - ymax = std::max( ymax, m_CornersList[i].y ); - } - - EDA_RECT r; - r.SetOrigin( wxPoint( xmin, ymin ) ); - r.SetEnd( wxPoint( xmax, ymax ) ); - - return r; -} - - -const EDA_RECT CPolyLine::GetBoundingBox( int icont ) -{ - int xmin = INT_MAX; - int ymin = INT_MAX; - int xmax = INT_MIN; - int ymax = INT_MIN; - int istart = GetContourStart( icont ); - int iend = GetContourEnd( icont ); - - for( int i = istart; i<=iend; i++ ) - { - xmin = std::min( xmin, m_CornersList[i].x ); - xmax = std::max( xmax, m_CornersList[i].x ); - ymin = std::min( ymin, m_CornersList[i].y ); - ymax = std::max( ymax, m_CornersList[i].y ); - } - - EDA_RECT r; - r.SetOrigin( wxPoint( xmin, ymin ) ); - r.SetEnd( wxPoint( xmax, ymax ) ); - - return r; -} - - -int CPolyLine::GetContoursCount() const -{ - return m_CornersList.GetContoursCount(); -} - - - -int CPOLYGONS_LIST::GetContoursCount() const -{ - if( !m_cornersList.size() ) - return 0; - - // count the number of corners flagged end_contour - int ncont = 0; - - for( unsigned ic = 0; ic < m_cornersList.size(); ic++ ) - if( m_cornersList[ic].end_contour ) - ncont++; - - // The last corner can be not yet flagged end_contour. - // It was not counted, but the polygon exists, so count it - if( !m_cornersList[m_cornersList.size() - 1].end_contour ) - ncont++; - - return ncont; -} - - -int CPolyLine::GetContour( int ic ) -{ - int ncont = 0; - - for( int i = 0; i max_x ) - max_x = m_CornersList[ic].x; - - if( m_CornersList[ic].y < min_y ) - min_y = m_CornersList[ic].y; - - if( m_CornersList[ic].y > max_y ) - max_y = m_CornersList[ic].y; - } - - // Calculate spacing between 2 hatch lines - int spacing; - - if( m_hatchStyle == DIAGONAL_EDGE ) - spacing = m_hatchPitch; - else - spacing = m_hatchPitch * 2; - - // set the "length" of hatch lines (the length on horizontal axis) - double hatch_line_len = m_hatchPitch; - - // To have a better look, give a slope depending on the layer - LAYER_NUM layer = GetLayer(); - int slope_flag = (layer & 1) ? 1 : -1; // 1 or -1 - double slope = 0.707106 * slope_flag; // 45 degrees slope - int max_a, min_a; - - if( slope_flag == 1 ) - { - max_a = KiROUND( max_y - slope * min_x ); - min_a = KiROUND( min_y - slope * max_x ); - } - else - { - max_a = KiROUND( max_y - slope * max_x ); - min_a = KiROUND( min_y - slope * min_x ); - } - - min_a = (min_a / spacing) * spacing; - - // calculate an offset depending on layer number, - // for a better look of hatches on a multilayer board - int offset = (layer * 7) / 8; - min_a += offset; - - // now calculate and draw hatch lines - int nc = m_CornersList.GetCornersCount(); - - // loop through hatch lines - #define MAXPTS 200 // Usually we store only few values per one hatch line - // depending on the compexity of the zone outline - - static std::vector pointbuffer; - pointbuffer.clear(); - pointbuffer.reserve( MAXPTS + 2 ); - - for( int a = min_a; a < max_a; a += spacing ) - { - // get intersection points for this hatch line - - // Note: because we should have an even number of intersections with the - // current hatch line and the zone outline (a closed polygon, - // or a set of closed polygons), if an odd count is found - // we skip this line (should not occur) - pointbuffer.clear(); - int i_start_contour = 0; - - for( int ic = 0; ic= MAXPTS ) // overflow - { - wxASSERT( 0 ); - break; - } - } - - // ensure we have found an even intersection points count - // because intersections are the ends of segments - // inside the polygon(s) and a segment has 2 ends. - // if not, this is a strange case (a bug ?) so skip this hatch - if( pointbuffer.size() % 2 != 0 ) - continue; - - // sort points in order of descending x (if more than 2) to - // ensure the starting point and the ending point of the same segment - // are stored one just after the other. - if( pointbuffer.size() > 2 ) - sort( pointbuffer.begin(), pointbuffer.end(), sort_ends_by_descending_X ); - - // creates lines or short segments inside the complex polygon - for( unsigned ip = 0; ip < pointbuffer.size(); ip += 2 ) - { - double dx = pointbuffer[ip + 1].x - pointbuffer[ip].x; - - // Push only one line for diagonal hatch, - // or for small lines < twice the line len - // else push 2 small lines - if( m_hatchStyle == DIAGONAL_FULL || fabs( dx ) < 2 * hatch_line_len ) - { - m_HatchLines.push_back( CSegment( pointbuffer[ip], pointbuffer[ip + 1] ) ); - } - else - { - double dy = pointbuffer[ip + 1].y - pointbuffer[ip].y; - slope = dy / dx; - - if( dx > 0 ) - dx = hatch_line_len; - else - dx = -hatch_line_len; - - double x1 = pointbuffer[ip].x + dx; - double x2 = pointbuffer[ip + 1].x - dx; - double y1 = pointbuffer[ip].y + dx * slope; - double y2 = pointbuffer[ip + 1].y - dx * slope; - - m_HatchLines.push_back( CSegment( pointbuffer[ip].x, - pointbuffer[ip].y, - KiROUND( x1 ), KiROUND( y1 ) ) ); - - m_HatchLines.push_back( CSegment( pointbuffer[ip + 1].x, - pointbuffer[ip + 1].y, - KiROUND( x2 ), KiROUND( y2 ) ) ); - } - } - } -} - - -// test to see if a point is inside polyline -// -bool CPolyLine::TestPointInside( int px, int py ) -{ - if( !GetClosed() ) - { - wxASSERT( 0 ); - } - - // Test all polygons. - // Since the first is the main outline, and other are holes, - // if the tested point is inside only one contour, it is inside the whole polygon - // (in fact inside the main outline, and outside all holes). - // if inside 2 contours (the main outline + an hole), it is outside the poly. - int polycount = GetContoursCount(); - bool inside = false; - - for( int icont = 0; icont < polycount; icont++ ) - { - int istart = GetContourStart( icont ); - int iend = GetContourEnd( icont ); - - // test point inside the current polygon - if( TestPointInsidePolygon( m_CornersList, istart, iend, px, py ) ) - inside = not inside; - } - - return inside; -} - - -// copy data from another CPolyLine, but don't draw it -void CPolyLine::Copy( const CPolyLine* src ) -{ - UnHatch(); - m_layer = src->m_layer; - m_hatchStyle = src->m_hatchStyle; - m_hatchPitch = src->m_hatchPitch; - m_flags = src->m_flags; - m_CornersList.RemoveAllContours(); - m_CornersList.Append( src->m_CornersList ); -} - - -/* - * return true if the corner aCornerIdx is on a hole inside the main outline - * and false if it is on the main outline - */ -bool CPolyLine::IsCutoutContour( int aCornerIdx ) -{ - int ncont = GetContour( aCornerIdx ); - - if( ncont == 0 ) // the first contour is the main outline, not an hole - return false; - - return true; -} - - -void CPolyLine::MoveOrigin( int x_off, int y_off ) -{ - UnHatch(); - - for( int ic = 0; ic < GetCornersCount(); ic++ ) - { - SetX( ic, GetX( ic ) + x_off ); - SetY( ic, GetY( ic ) + y_off ); - } - - Hatch(); -} - - -/* - * AppendArc: - * adds segments to current contour to approximate the given arc - */ -void CPolyLine::AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num ) -{ - // get radius - double radius = ::Distance( xi, yi, xf, yf ); - - // get angles of start pint and end point - double th_i = atan2( (double) (yi - yc), (double) (xi - xc) ); - double th_f = atan2( (double) (yf - yc), (double) (xf - xc) ); - double th_d = (th_f - th_i) / (num - 1); - double theta = th_i; - - // generate arc - for( int ic = 0; ic < num; ic++ ) - { - int x = xc + KiROUND( radius * cos( theta ) ); - int y = yc + KiROUND( radius * sin( theta ) ); - AppendCorner( x, y ); - theta += th_d; - } - - CloseLastContour(); -} - - -void CPolyLine::AppendBezier( int x1, int y1, int x2, int y2, int x3, int y3 ) -{ - std::vector polyPoints; - - BEZIER_POLY converter( x1, y1, x2, y2, x3, y3 ); - converter.GetPoly( polyPoints ); - - for( const auto& pt : polyPoints ) - AppendCorner( pt.x, pt.y ); -} - - -void CPolyLine::AppendBezier( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 ) -{ - std::vector polyPoints; - - BEZIER_POLY converter( x1, y1, x2, y2, x3, y3, x4, y4 ); - converter.GetPoly( polyPoints ); - - for( const auto& pt : polyPoints ) - AppendCorner( pt.x, pt.y ); -} - - -/* - * Function Distance - * Calculates the distance between a segment and a polygon (with holes): - * param aStart is the starting point of the segment. - * param aEnd is the ending point of the segment. - * param aWidth is the width of the segment. - * return distance between the segment and outline. - * 0 if segment intersects or is inside - */ -int CPolyLine::Distance( wxPoint aStart, wxPoint aEnd, int aWidth ) -{ - // We calculate the min dist between the segment and each outline segment - // However, if the segment to test is inside the outline, and does not cross - // any edge, it can be seen outside the polygon. - // Therefore test if a segment end is inside ( testing only one end is enough ) - if( TestPointInside( aStart.x, aStart.y ) ) - return 0; - - int distance = INT_MAX; - int polycount = GetContoursCount(); - - for( int icont = 0; icont < polycount; icont++ ) - { - int ic_start = GetContourStart( icont ); - int ic_end = GetContourEnd( icont ); - - // now test spacing between area outline and segment - for( int ic2 = ic_start; ic2 <= ic_end; ic2++ ) - { - int bx1 = GetX( ic2 ); - int by1 = GetY( ic2 ); - int bx2, by2; - - if( ic2 == ic_end ) - { - bx2 = GetX( ic_start ); - by2 = GetY( ic_start ); - } - else - { - bx2 = GetX( ic2 + 1 ); - by2 = GetY( ic2 + 1 ); - } - - int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2, 0, - aStart.x, aStart.y, aEnd.x, aEnd.y, - aWidth, - 1, // min clearance, should be > 0 - NULL, NULL ); - - if( distance > d ) - distance = d; - - if( distance <= 0 ) - return 0; - } - } - - return distance; -} - - -/* - * Function Distance - * Calculates the distance between a point and polygon (with holes): - * param aPoint is the coordinate of the point. - * return distance between the point and outline. - * 0 if the point is inside - */ -int CPolyLine::Distance( const wxPoint& aPoint ) -{ - // We calculate the dist between the point and each outline segment - // If the point is inside the outline, the dist is 0. - if( TestPointInside( aPoint.x, aPoint.y ) ) - return 0; - - int distance = INT_MAX; - int polycount = GetContoursCount(); - - for( int icont = 0; icont < polycount; icont++ ) - { - int ic_start = GetContourStart( icont ); - int ic_end = GetContourEnd( icont ); - - // now test spacing between area outline and segment - for( int ic2 = ic_start; ic2 <= ic_end; ic2++ ) - { - int bx1 = GetX( ic2 ); - int by1 = GetY( ic2 ); - int bx2, by2; - - if( ic2 == ic_end ) - { - bx2 = GetX( ic_start ); - by2 = GetY( ic_start ); - } - else - { - bx2 = GetX( ic2 + 1 ); - by2 = GetY( ic2 + 1 ); - } - - int d = KiROUND( GetPointToLineSegmentDistance( aPoint.x, aPoint.y, - bx1, by1, bx2, by2 ) ); - - if( distance > d ) - distance = d; - - if( distance <= 0 ) - return 0; - } - } - - return distance; -} - - -/* - * test is the point aPos is near (< aDistMax ) a vertex - * return int = the index of the first corner of the vertex, or -1 if not found. - */ -int CPolyLine::HitTestForEdge( const wxPoint& aPos, int aDistMax ) const -{ - unsigned lim = m_CornersList.GetCornersCount(); - int corner = -1; // Set to not found - unsigned first_corner_pos = 0; - - for( unsigned item_pos = 0; item_pos < lim; item_pos++ ) - { - unsigned end_segm = item_pos + 1; - - /* the last corner of the current outline is tested - * the last segment of the current outline starts at current corner, and ends - * at the first corner of the outline - */ - if( m_CornersList.IsEndContour ( item_pos ) || end_segm >= lim ) - { - unsigned tmp = first_corner_pos; - first_corner_pos = end_segm; // first_corner_pos is the beginning of next outline - end_segm = tmp; // end_segm is the beginning of the current outline - } - - // test the dist between segment and ref point - int dist = KiROUND( GetPointToLineSegmentDistance( - aPos.x, aPos.y, - m_CornersList.GetX( item_pos ), - m_CornersList.GetY( item_pos ), - m_CornersList.GetX( end_segm ), - m_CornersList.GetY( end_segm ) ) ); - - if( dist < aDistMax ) - { - corner = item_pos; - aDistMax = dist; - } - } - - return corner; -} - - -/* - * test is the point aPos is near (< aDistMax ) a corner - * return int = the index of corner of the, or -1 if not found. - */ -int CPolyLine::HitTestForCorner( const wxPoint& aPos, int aDistMax ) const -{ - int corner = -1; // Set to not found - wxPoint delta; - unsigned lim = m_CornersList.GetCornersCount(); - - for( unsigned item_pos = 0; item_pos < lim; item_pos++ ) - { - delta.x = aPos.x - m_CornersList.GetX( item_pos ); - delta.y = aPos.y - m_CornersList.GetY( item_pos ); - - // Calculate a distance: - int dist = std::max( abs( delta.x ), abs( delta.y ) ); - - if( dist < aDistMax ) // this corner is a candidate: - { - corner = item_pos; - aDistMax = dist; - } - } - - return corner; -} - - -/** - * Function IsPolygonSelfIntersecting - * Test a CPolyLine for self-intersection of vertex (all contours). - * - * @return : - * false if no intersecting sides - * true if intersecting sides - * When a CPolyLine is self intersectic, it need to be normalized. - * (converted to non intersecting polygons) - */ -bool CPolyLine::IsPolygonSelfIntersecting() -{ - // first, check for sides intersecting other sides - int n_cont = GetContoursCount(); - - // make bounding rect for each contour - std::vector cr; - cr.reserve( n_cont ); - - for( int icont = 0; icont is_end ) - is_next = is_start; - - int x1i = GetX( is ); - int y1i = GetY( is ); - int x1f = GetX( is_next ); - int y1f = GetY( is_next ); - - // check for intersection with any other sides - for( int icont2 = icont; icont2 < n_cont; icont2++ ) - { - if( !cr[icont].Intersects( cr[icont2] ) ) - { - // rectangles don't overlap, do nothing - } - else - { - int is2_start = GetContourStart( icont2 ); - int is2_end = GetContourEnd( icont2 ); - - for( int is2 = is2_start; is2<=is2_end; is2++ ) - { - int is2_prev = is2 - 1; - - if( is2_prev < is2_start ) - is2_prev = is2_end; - - int is2_next = is2 + 1; - - if( is2_next > is2_end ) - is2_next = is2_start; - - if( icont != icont2 - || ( is2 != is && is2 != is_prev && is2 != is_next && - is != is2_prev && is != is2_next ) - ) - { - int x2i = GetX( is2 ); - int y2i = GetY( is2 ); - int x2f = GetX( is2_next ); - int y2f = GetY( is2_next ); - int ret = FindSegmentIntersections( x1i, y1i, x1f, y1f, - x2i, y2i, x2f, y2f ); - if( ret ) - { - // intersection between non-adjacent sides - return true; - } - } - } - } - } - } - } - - return false; -} - - -const SHAPE_POLY_SET ConvertPolyListToPolySet( const CPOLYGONS_LIST& aList ) -{ - SHAPE_POLY_SET rv; - - unsigned corners_count = aList.GetCornersCount(); - - // Enter main outline: this is the first contour - unsigned ic = 0; - - if( !corners_count ) - return rv; - - int index = 0; - - while( ic < corners_count ) - { - int hole = -1; - - if( index == 0 ) - { - rv.NewOutline(); - hole = -1; - } - else - { - hole = rv.NewHole(); - } - - while( ic < corners_count ) - { - rv.Append( aList.GetX( ic ), aList.GetY( ic ), 0, hole ); - - if( aList.IsEndContour( ic ) ) - break; - - ic++; - } - ic++; - - index++; - } - - return rv; -} - - -const CPOLYGONS_LIST ConvertPolySetToPolyList(const SHAPE_POLY_SET& aPolyset) -{ - CPOLYGONS_LIST list; - CPolyPt corner, firstCorner; - - const SHAPE_POLY_SET::POLYGON& poly = aPolyset.CPolygon( 0 ); - - for( unsigned int jj = 0; jj < poly.size() ; jj++ ) - { - const SHAPE_LINE_CHAIN& path = poly[jj]; - - for( int i = 0; i < path.PointCount(); i++ ) - { - const VECTOR2I &v = path.CPoint( i ); - - corner.x = v.x; - corner.y = v.y; - corner.end_contour = false; - - if( i == 0 ) - firstCorner = corner; - - list.AddCorner( corner ); - } - - firstCorner.end_contour = true; - list.AddCorner( firstCorner ); - } - - return list; -} diff --git a/polygon/PolyLine.h b/polygon/PolyLine.h deleted file mode 100644 index 71c863e205..0000000000 --- a/polygon/PolyLine.h +++ /dev/null @@ -1,494 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Few parts of this code come from FreePCB, released under the GNU General Public License V2. - * (see http://www.freepcb.com/ ) - * - * Copyright (C) 2012-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 2008-2013 SoftPLC Corporation, Dick Hollenbeck - * Copyright (C) 2008-2013 Wayne Stambaugh - * Copyright (C) 2012-2015 KiCad Developers, see CHANGELOG.TXT for contributors. - * - * 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 - */ - - -/** - * @file PolyLine.h - * @note definition of CPolyLine class - */ - -// -// A polyline contains one or more contours, where each contour -// is defined by a list of corners and side-styles -// There may be multiple contours in a polyline. -// The last contour may be open or closed, any others must be closed. -// All of the corners and side-styles are concatenated into 2 arrays, -// separated by setting the end_contour flag of the last corner of -// each contour. -// -// When used for copper (or technical layers) areas, the first contour is the outer edge -// of the area, subsequent ones are "holes" in the copper. - -#ifndef POLYLINE_H -#define POLYLINE_H - -#include - -#include // for wxPoint definition -#include // for LAYER_NUM definition -#include // for EDA_RECT definition - -#include // fixme - -class CSegment -{ -public: - wxPoint m_Start; - wxPoint m_End; - - CSegment() { }; - CSegment( const wxPoint& aStart, const wxPoint& aEnd ) - { - m_Start = aStart; - m_End = aEnd; - } - - CSegment( int x0, int y0, int x1, int y1 ) - { - m_Start.x = x0; m_Start.y = y0; - m_End.x = x1; m_End.y = y1; - } -}; - -class CPolyPt : public wxPoint -{ -public: - CPolyPt( int aX = 0, int aY = 0, bool aEnd = false, int aUtility = 0 ) : - wxPoint( aX, aY ), end_contour( aEnd ), m_flags( aUtility ) - {} - - // / Pure copy constructor is here to dis-ambiguate from the - // / specialized CPolyPt( const wxPoint& ) constructor version below. - CPolyPt( const CPolyPt& aPt ) : - wxPoint( aPt.x, aPt.y ), end_contour( aPt.end_contour ), m_flags( aPt.m_flags ) - {} - - CPolyPt( const wxPoint& aPoint ) : - wxPoint( aPoint ), end_contour( false ), m_flags( 0 ) - {} - - - bool end_contour; - int m_flags; - - bool operator ==( const CPolyPt& cpt2 ) const - { return (x == cpt2.x) && (y == cpt2.y) && (end_contour == cpt2.end_contour); } - - bool operator !=( CPolyPt& cpt2 ) const - { return (x != cpt2.x) || (y != cpt2.y) || (end_contour != cpt2.end_contour); } -}; - - -#ifndef SWIG -/** - * CPOLYGONS_LIST handle a list of contours (polygons corners). - * Each corner is a CPolyPt item. - * The last cornet of each contour has its end_contour member = true - */ -class CPOLYGONS_LIST -{ -private: - std::vector m_cornersList; // array of points for corners -public: - CPOLYGONS_LIST() {}; - - CPolyPt& operator [](int aIdx) { return m_cornersList[aIdx]; } - - // Accessor: - const std::vector & GetList() const {return m_cornersList;} - - int GetX( int ic ) const { return m_cornersList[ic].x; } - void SetX( int ic, int aValue ) { m_cornersList[ic].x = aValue; } - int GetY( int ic ) const { return m_cornersList[ic].y; } - void SetY( int ic, int aValue ) { m_cornersList[ic].y = aValue; } - - bool IsEndContour( int ic ) const - { - return m_cornersList[ic].end_contour; - } - - const wxPoint& GetPos( int ic ) const { return m_cornersList[ic]; } - const CPolyPt& GetCorner( int ic ) const { return m_cornersList[ic]; } - - // vector <> methods - void reserve( int aSize ) { m_cornersList.reserve( aSize ); } - - - void RemoveAllContours( void ) { m_cornersList.clear(); } - CPolyPt& GetLastCorner() { return m_cornersList.back(); } - - unsigned GetCornersCount() const { return m_cornersList.size(); } - - void DeleteCorner( int aIdx ) - { - m_cornersList.erase( m_cornersList.begin() + aIdx ); - } - - // used only to erase an entire polygon - void DeleteCorners( int aIdFirstCorner, int aIdLastCorner ) - { - m_cornersList.erase( m_cornersList.begin() + aIdFirstCorner, - m_cornersList.begin() + aIdLastCorner + 1 ); - } - - void Append( const CPOLYGONS_LIST& aList ) - { - m_cornersList.insert( m_cornersList.end(), - aList.m_cornersList.begin(), - aList.m_cornersList.end() ); - } - - void Append( const CPolyPt& aItem ) - { - m_cornersList.push_back( aItem ); - } - - void Append( const wxPoint& aItem ) - { - CPolyPt item( aItem ); - - m_cornersList.push_back( aItem ); - } - - void InsertCorner( int aPosition, const CPolyPt& aItem ) - { - m_cornersList.insert( m_cornersList.begin() + aPosition + 1, aItem ); - } - - /** - * function AddCorner - * add a corner to the list - */ - void AddCorner( const CPolyPt& aCorner ) - { - m_cornersList.push_back( aCorner ); - } - - /** - * function CloseLastContour - * Set the .end_contour member of the last corner in list to true - */ - void CloseLastContour() - { - if( m_cornersList.size() > 0 ) - m_cornersList.back().end_contour = true; - } - - /** - * Function GetContoursCount. - * @return the number of polygons stored in list - * (number of corners flagged "end_contour" - */ - int GetContoursCount() const; -}; -#endif - - -class CPolyLine -{ -public: - enum HATCH_STYLE { NO_HATCH, DIAGONAL_FULL, DIAGONAL_EDGE }; // hatch styles - - // constructors/destructor - CPolyLine(); - CPolyLine( const CPolyLine& aCPolyLine); - ~CPolyLine(); - - /** - * Function ImportSettings - * Copy settings (layer, hatch styles) from aPoly - * @param aPoly is the CPolyLine to import settings - */ - void ImportSettings( const CPolyLine* aPoly ); - - // functions for modifying the CPolyLine contours - - /* initialize a contour - * set layer, hatch style, and starting point - */ - void Start( LAYER_NUM layer, int x, int y, int hatch ); - - void AppendCorner( int x, int y ); - void InsertCorner( int ic, int x, int y ); - - /** - * Function DeleteCorner - * remove the given corner. if it is the last point of a contour - * keep the controur closed by modifying the previous corner - * @param ic = the index of the corner to delete - */ - void DeleteCorner( int ic ); - void MoveCorner( int ic, int x, int y ); - - /** - * function CloseLastContour - * Set the .end_contour member of the last corner - * of the last contour to true - */ - void CloseLastContour() - { - m_CornersList.CloseLastContour(); - } - - void RemoveContour( int icont ); - - /** - * Function IsPolygonSelfIntersecting - * Test a CPolyLine for self-intersection of vertex (all contours). - * - * @return : - * false if no intersecting sides - * true if intersecting sides - * When a CPolyLine is self intersectic, it need to be normalized. - * (converted to non intersecting polygons) - */ - bool IsPolygonSelfIntersecting(); - - /** - * Function Chamfer - * returns a chamfered version of a polygon. - * @param aDistance is the chamfering distance. - * @return CPolyLine* - Pointer to new polygon. - */ - CPolyLine* Chamfer( unsigned int aDistance ); - - /** - * Function Fillet - * returns a filleted version of a polygon. - * @param aRadius is the fillet radius. - * @param aSegments is the number of segments / fillet. - * @return CPolyLine* - Pointer to new polygon. - */ - CPolyLine* Fillet( unsigned int aRadius, unsigned int aSegments ); - - /** - * Function RemoveNullSegments - * Removes corners which create a null segment edge - * (i.e. when 2 successive corners are at the same location) - * @return the count of removed corners. - */ - int RemoveNullSegments(); - - void RemoveAllContours( void ); - - // Remove or create hatch - void UnHatch(); - void Hatch(); - - // Transform functions - void MoveOrigin( int x_off, int y_off ); - - // misc. functions - /** - * @return the full bounding box of polygons - */ - const EDA_RECT GetBoundingBox(); - - /** - * @return the bounding box of a given polygon - * @param icont = the index of the polygon contour - * (0 = main contour, 1 ... n = other contours, usually holes) - */ - const EDA_RECT GetBoundingBox( int icont ); - - void Copy( const CPolyLine* src ); - bool TestPointInside( int x, int y ); - - /** - * @return true if the corner aCornerIdx is on a hole inside the main outline - * and false if it is on the main outline - */ - bool IsCutoutContour( int aCornerIdx ); - - /** - * Function AppendArc. - * Adds segments to current contour to approximate the given arc - */ - void AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num ); - - // access functions - void SetLayer( LAYER_NUM aLayer ) { m_layer = aLayer; } - LAYER_NUM GetLayer() const { return m_layer; } - - int GetCornersCount() const - { - return m_CornersList.GetCornersCount(); - } - - /** - * @return true if the last corner in corners list is flagged end_contour - */ - bool GetClosed(); - - /** - * Function GetContoursCount. - * @return the number of polygons stored in list - * (number of corners flagged "end_contour" - */ - int GetContoursCount() const; - - /** - * Function GetContour. - * @return the contour number containing the corner ic - * @param ic = the index of the corner in the corner list - */ - int GetContour( int ic ); - - /** - * Function GetContourStart. - * @return the index of the first corner (in corners list) of a contour - * @param icont = the index of the contour - */ - int GetContourStart( int icont ); - - /** - * Function GetContourEnd. - * @return the index of the last corner (in corners list) of a contour - * @param icont = the index of the contour - */ - int GetContourEnd( int icont ); - - /** - * Function GetContourSize. - * @return the corners count of a contour - * @param icont = the index of the contour - */ - int GetContourSize( int icont ); - - int GetX( int ic ) const { return m_CornersList.GetX( ic ); } - int GetY( int ic ) const { return m_CornersList.GetY( ic ); } - - /** - * Function IsEndContour. - * @return true if a corner is flagged end_contour - * @param ic= the index (in corners list) of the corner - */ - bool IsEndContour( int ic ) const { return m_CornersList.IsEndContour( ic ); } - - const wxPoint& GetPos( int ic ) const { return m_CornersList.GetPos( ic ); } - - int GetHatchPitch() const { return m_hatchPitch; } - static int GetDefaultHatchPitchMils() { return 20; } // default hatch pitch value in mils - - enum HATCH_STYLE GetHatchStyle() const { return m_hatchStyle; } - void SetHatch( int aHatchStyle, int aHatchPitch, bool aRebuildHatch ) - { - SetHatchPitch( aHatchPitch ); - m_hatchStyle = (enum HATCH_STYLE) aHatchStyle; - - if( aRebuildHatch ) - Hatch(); - } - - void SetX( int ic, int x ) - { - m_CornersList.SetX( ic, x ); - } - - void SetY( int ic, int y ) - { - m_CornersList.SetY( ic, y ); - } - - void SetHatchStyle( enum HATCH_STYLE style ) - { - m_hatchStyle = style; - } - - void SetHatchPitch( int pitch ) { m_hatchPitch = pitch; } - - /** - * Function NormalizeAreaOutlines - * Convert a self-intersecting polygon to one (or more) non self-intersecting polygon(s) - * Removes null segments. - * @param aNewPolygonList = a std::vector reference where to store new CPolyLine - * needed by the normalization - * @return the polygon count (always >= 1, because there is at least one polygon) - * There are new polygons only if the polygon count is > 1 - */ - int NormalizeAreaOutlines( std::vector* aNewPolygonList ); - - // Bezier Support - void AppendBezier( int x1, int y1, int x2, int y2, int x3, int y3 ); - void AppendBezier( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 ); - - /** - * Function Distance - * Calculates the distance between a point and the zone: - * @param aPoint the coordinate of the point. - * @return int = distance between the point and outline. - * 0 if the point is inside - */ - int Distance( const wxPoint& aPoint ); - - /** - * Function Distance - * Calculates the distance between a segment and the zone: - * @param aStart the starting point of the segment. - * @param aEnd the ending point of the segment. - * @param aWidth the width of the segment. - * @return int = distance between the segment and outline. - * 0 if segment intersects or is inside - */ - int Distance( wxPoint aStart, wxPoint aEnd, int aWidth ); - - /** - * Function HitTestForEdge - * test is the point aPos is near (< aDistMax ) a vertex - * @param aPos = the reference point - * @param aDistMax = the max distance between a vertex and the reference point - * @return int = the index of the first corner of the vertex, or -1 if not found. - */ - int HitTestForEdge( const wxPoint& aPos, int aDistMax ) const; - - /** - * Function HitTestForCorner - * test is the point aPos is near (< aDistMax ) a corner - * @param aPos = the reference point - * @param aDistMax = the max distance between a vertex and the corner - * @return int = the index of corner of the, or -1 if not found. - */ - int HitTestForCorner( const wxPoint& aPos, int aDistMax ) const; - -private: - LAYER_NUM m_layer; // layer to draw on - enum HATCH_STYLE m_hatchStyle; // hatch style, see enum above - int m_hatchPitch; // for DIAGONAL_EDGE hatched outlines, basic distance between 2 hatch lines - // and the len of eacvh segment - // for DIAGONAL_FULL, the pitch is twice this value - int m_flags; // a flag used in some calculations -public: - CPOLYGONS_LIST m_CornersList; // array of points for corners - std::vector m_HatchLines; // hatch lines showing the polygon area -}; - -const SHAPE_POLY_SET ConvertPolyListToPolySet( const CPOLYGONS_LIST& aList ); -const CPOLYGONS_LIST ConvertPolySetToPolyList( const SHAPE_POLY_SET& aPolyset ); - -#endif // #ifndef POLYLINE_H diff --git a/polygon/polygon_test_point_inside.cpp b/polygon/polygon_test_point_inside.cpp index 476de2df0d..4c34e1e971 100644 --- a/polygon/polygon_test_point_inside.cpp +++ b/polygon/polygon_test_point_inside.cpp @@ -51,74 +51,6 @@ #define OUTSIDE false #define INSIDE true -#if 1 // Will be removed whe deprecated CPOLYGONS_LIST will be rmoved -#include -bool TestPointInsidePolygon( const CPOLYGONS_LIST& aPolysList, - int aIdxstart, - int aIdxend, - int aRefx, - int aRefy) - -/** - * Function TestPointInsidePolygon - * test if a point is inside or outside a polygon. - * the polygon must have only lines (not arcs) for outlines. - * @param aPolysList: the list of polygons - * @param aIdxstart: the starting point of a given polygon in m_FilledPolysList. - * @param aIdxend: the ending point of this polygon in m_FilledPolysList. - * @param aRefx, aRefy: the point coordinate to test - * @return true if the point is inside, false for outside - */ -{ - // count intersection points to right of (refx,refy). If odd number, point (refx,refy) is inside polyline - int ics, ice; - int count = 0; - - // find all intersection points of line with polyline sides - for( ics = aIdxstart, ice = aIdxend; ics <= aIdxend; ice = ics++ ) - { - int seg_startX = aPolysList.GetX( ics ); - int seg_startY = aPolysList.GetY( ics ); - int seg_endX = aPolysList.GetX( ice ); - int seg_endY = aPolysList.GetY( ice ); - - /* Trivial cases: skip if ref above or below the segment to test */ - if( ( seg_startY > aRefy ) && (seg_endY > aRefy ) ) - continue; - - // segment below ref point, or one of its ends has the same Y pos as the ref point: skip - // So we eliminate one end point of 2 consecutive segments. - // Note: also we skip horizontal segments if ref point is on this horizontal line - // So reference points on horizontal segments outlines always are seen as outside the polygon - if( ( seg_startY <= aRefy ) && (seg_endY <= aRefy ) ) - continue; - - /* refy is between seg_startY and seg_endY. - * note: here: horizontal segments (seg_startY == seg_endY) are skipped, - * either by the first test or by the second test - * see if an horizontal semi infinite line from refx is intersecting the segment - */ - - // calculate the x position of the intersection of this segment and the semi infinite line - // this is more easier if we move the X,Y axis origin to the segment start point: - seg_endX -= seg_startX; - seg_endY -= seg_startY; - double newrefx = (double) (aRefx - seg_startX); - double newrefy = (double) (aRefy - seg_startY); - - // Now calculate the x intersection coordinate of the line from (0,0) to (seg_endX,seg_endY) - // with the horizontal line at the new refy position - // the line slope = seg_endY/seg_endX; - // and the x pos relative to the new origin is intersec_x = refy/slope - // Note: because horizontal segments are skipped, 1/slope exists (seg_endY never == O) - double intersec_x = (newrefy * seg_endX) / seg_endY; - if( newrefx < intersec_x ) // Intersection found with the semi-infinite line from refx to infinite - count++; - } - - return count & 1 ? INSIDE : OUTSIDE; -} -#endif /* Function TestPointInsidePolygon (overlaid) * same as previous, but use wxPoint and aCount corners diff --git a/polygon/polygon_test_point_inside.h b/polygon/polygon_test_point_inside.h index ee2ca40e9e..07e25eb534 100644 --- a/polygon/polygon_test_point_inside.h +++ b/polygon/polygon_test_point_inside.h @@ -34,25 +34,6 @@ public: #endif -#if 1 // set to 0 when deprecated CPOLYGONS_LIST will be removed -class CPOLYGONS_LIST; - -/** - * Function TestPointInsidePolygon - * test if a point is inside or outside a polygon. - * @param aPolysList: the list of polygons - * @param aIdxstart: the starting point of a given polygon in m_FilledPolysList. - * @param aIdxend: the ending point of the polygon in m_FilledPolysList. - * @param aRefx, aRefy: the point coordinate to test - * @return true if the point is inside, false for outside - */ -bool TestPointInsidePolygon( const CPOLYGONS_LIST& aPolysList, - int aIdxstart, - int aIdxend, - int aRefx, - int aRefy); -#endif - /** * Function TestPointInsidePolygon (overlaid) * same as previous, but mainly use wxPoint diff --git a/qa/data/fixtures_geometry.h b/qa/data/fixtures_geometry.h index e025d461f2..b7c97c001c 100644 --- a/qa/data/fixtures_geometry.h +++ b/qa/data/fixtures_geometry.h @@ -27,7 +27,6 @@ #include #include -#include /** * Common data for the tests: @@ -141,62 +140,6 @@ struct CommonTestData ~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 diff --git a/qa/shape_poly_set_refactor/CMakeLists.txt b/qa/shape_poly_set_refactor/CMakeLists.txt index d6b72aeb0b..6c023eb94b 100644 --- a/qa/shape_poly_set_refactor/CMakeLists.txt +++ b/qa/shape_poly_set_refactor/CMakeLists.txt @@ -28,7 +28,6 @@ add_definitions(-DBOOST_TEST_DYN_LINK) add_executable( qa_shape_poly_set_refactor test_module.cpp - test_chamfer.cpp test_collision.cpp test_iterator.cpp test_segment.cpp diff --git a/qa/shape_poly_set_refactor/test_chamfer.cpp b/qa/shape_poly_set_refactor/test_chamfer.cpp deleted file mode 100644 index 7d8a168591..0000000000 --- a/qa/shape_poly_set_refactor/test_chamfer.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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( Chamfer, 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; - - // 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. - // CPolyline::Chamfer returns new CPolyline - take ownership - std::unique_ptr 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); - } - } -} - -BOOST_AUTO_TEST_SUITE_END()