mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 10:13:19 +02:00
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.
107 lines
5.0 KiB
C++
107 lines
5.0 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2007-2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
|
* Copyright (C) 2007-2014 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 polygon_test_point_inside.cpp
|
|
*/
|
|
|
|
#include <cmath>
|
|
#include <vector>
|
|
|
|
#include "polygon_test_point_inside.h"
|
|
|
|
/* this algo uses the the Jordan curve theorem to find if a point is inside or outside a polygon:
|
|
* It run a semi-infinite line horizontally (increasing x, fixed y)
|
|
* out from the test point, and count how many edges it crosses.
|
|
* At each crossing, the ray switches between inside and outside.
|
|
* If odd count, the test point is inside the polygon
|
|
* This is called the Jordan curve theorem, or sometimes referred to as the "even-odd" test.
|
|
* Take care to starting and ending points of segments outlines, when the horizontal line crosses a segment outline
|
|
* exactly on an ending point:
|
|
* Because the starting point of a segment is also the ending point of the previous, only one must be used.
|
|
* And we do no use twice the same segment, so we do NOT use both starting and ending points of these 2 segments.
|
|
* So we must use only one ending point of each segment when calculating intersections
|
|
* but it cannot be always the starting or the ending point. This depend on relative position of 2 consectutive segments
|
|
* Here, the ending point above the Y reference position is used
|
|
* and the ending point below or equal the Y reference position is NOT used
|
|
* Obviously, others cases are irrelevant because there is not intersection.
|
|
*/
|
|
|
|
#define OUTSIDE false
|
|
#define INSIDE true
|
|
|
|
|
|
/* Function TestPointInsidePolygon (overlaid)
|
|
* same as previous, but use wxPoint and aCount corners
|
|
*/
|
|
bool TestPointInsidePolygon( const wxPoint *aPolysList, int aCount, const wxPoint &aRefPoint )
|
|
{
|
|
// 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 = 0, ice = aCount-1; ics < aCount; ice = ics++ )
|
|
{
|
|
int seg_startX = aPolysList[ics].x;
|
|
int seg_startY = aPolysList[ics].y;
|
|
int seg_endX = aPolysList[ice].x;
|
|
int seg_endY = aPolysList[ice].y;
|
|
|
|
/* Trivial cases: skip if ref above or below the segment to test */
|
|
if( ( seg_startY > aRefPoint.y ) && (seg_endY > aRefPoint.y ) )
|
|
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 <= aRefPoint.y ) && (seg_endY <= aRefPoint.y ) )
|
|
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) (aRefPoint.x - seg_startX);
|
|
double newrefy = (double) (aRefPoint.y - 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;
|
|
}
|