/* * 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; }
bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos ) { unsigned lim = m_Poly->m_CornersList.GetCornersCount(); m_CornerSelection = -1; // Set to not found // distance (in internal units) to detect a zone outline int min_dist = MIN_DIST_IN_MILS*IU_PER_MILS; 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_Poly->m_CornersList.IsEndContour ( item_pos ) || end_segm >= lim ) { unsigned tmp = first_corner_pos; first_corner_pos = end_segm; // first_corner_pos is now the beginning of the 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( refPos.x, refPos.y, m_Poly->m_CornersList.GetX( item_pos ), m_Poly->m_CornersList.GetY( item_pos ), m_Poly->m_CornersList.GetX( end_segm ), m_Poly->m_CornersList.GetY( end_segm ) ) ); if( dist < min_dist ) { m_CornerSelection = item_pos; min_dist = dist; } } return m_CornerSelection >= 0; }
/* 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 now the beginning of the 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; }
/* * Function TestForIntersectionOfStraightLineSegments * Test for intersection of line segments * If lines are parallel, returns false * If true, returns also intersection coords in x, y * if false, returns min. distance in dist (may be 0.0 if parallel) */ bool TestForIntersectionOfStraightLineSegments( int x1i, int y1i, int x1f, int y1f, int x2i, int y2i, int x2f, int y2f, int* x, int* y, double* d ) { double a, b, dist; // first, test for intersection if( x1i == x1f && x2i == x2f ) { // both segments are vertical, can't intersect } else if( y1i == y1f && y2i == y2f ) { // both segments are horizontal, can't intersect } else if( x1i == x1f && y2i == y2f ) { // first seg. vertical, second horizontal, see if they cross if( InRange( x1i, x2i, x2f ) && InRange( y2i, y1i, y1f ) ) { if( x ) *x = x1i; if( y ) *y = y2i; if( d ) *d = 0.0; return true; } } else if( y1i == y1f && x2i == x2f ) { // first seg. horizontal, second vertical, see if they cross if( InRange( y1i, y2i, y2f ) && InRange( x2i, x1i, x1f ) ) { if( x ) *x = x2i; if( y ) *y = y1i; if( d ) *d = 0.0; return true; } } else if( x1i == x1f ) { // first segment vertical, second oblique // get a and b for second line segment, so that y = a + bx; b = double( y2f - y2i ) / (x2f - x2i); a = (double) y2i - b * x2i; double x1, y1, x2, y2; int test = FindLineSegmentIntersection( a, b, x1i, y1i, x1f, y1f, &x1, &y1, &x2, &y2 ); if( test ) { if( InRange( y1, y1i, y1f ) && InRange( x1, x2i, x2f ) && InRange( y1, y2i, y2f ) ) { if( x ) *x = KiROUND( x1 ); if( y ) *y = KiROUND( y1 ); if( d ) *d = 0.0; return true; } } } else if( y1i == y1f ) { // first segment horizontal, second oblique // get a and b for second line segment, so that y = a + bx; b = double( y2f - y2i ) / (x2f - x2i); a = (double) y2i - b * x2i; double x1, y1, x2, y2; int test = FindLineSegmentIntersection( a, b, x1i, y1i, x1f, y1f, &x1, &y1, &x2, &y2 ); if( test ) { if( InRange( x1, x1i, x1f ) && InRange( x1, x2i, x2f ) && InRange( y1, y2i, y2f ) ) { if( x ) *x = KiROUND( x1 ); if( y ) *y = KiROUND( y1 ); if( d ) *d = 0.0; return true; } } } else if( x2i == x2f ) { // second segment vertical, first oblique // get a and b for first line segment, so that y = a + bx; b = double( y1f - y1i ) / (x1f - x1i); a = (double) y1i - b * x1i; double x1, y1, x2, y2; int test = FindLineSegmentIntersection( a, b, x2i, y2i, x2f, y2f, &x1, &y1, &x2, &y2 ); if( test ) { if( InRange( x1, x1i, x1f ) && InRange( y1, y1i, y1f ) && InRange( y1, y2i, y2f ) ) { if( x ) *x = KiROUND( x1 ); if( y ) *y = KiROUND( y1 ); if( d ) *d = 0.0; return true; } } } else if( y2i == y2f ) { // second segment horizontal, first oblique // get a and b for second line segment, so that y = a + bx; b = double( y1f - y1i ) / (x1f - x1i); a = (double) y1i - b * x1i; double x1, y1, x2, y2; int test = FindLineSegmentIntersection( a, b, x2i, y2i, x2f, y2f, &x1, &y1, &x2, &y2 ); if( test ) { if( InRange( x1, x1i, x1f ) && InRange( y1, y1i, y1f ) ) { if( x ) *x = KiROUND( x1 ); if( y ) *y = KiROUND( y1 ); if( d ) *d = 0.0; return true; } } } else { // both segments oblique if( long( y1f - y1i ) * (x2f - x2i) != long( y2f - y2i ) * (x1f - x1i) ) { // not parallel, get a and b for first line segment, so that y = a + bx; b = double( y1f - y1i ) / (x1f - x1i); a = (double) y1i - b * x1i; double x1, y1, x2, y2; int test = FindLineSegmentIntersection( a, b, x2i, y2i, x2f, y2f, &x1, &y1, &x2, &y2 ); // both segments oblique if( test ) { if( InRange( x1, x1i, x1f ) && InRange( y1, y1i, y1f ) ) { if( x ) *x = KiROUND( x1 ); if( y ) *y = KiROUND( y1 ); if( d ) *d = 0.0; return true; } } } } // don't intersect, get shortest distance between each endpoint and the other line segment dist = GetPointToLineSegmentDistance( x1i, y1i, x2i, y2i, x2f, y2f ); double xx = x1i; double yy = y1i; double dd = GetPointToLineSegmentDistance( x1f, y1f, x2i, y2i, x2f, y2f ); if( dd < dist ) { dist = dd; xx = x1f; yy = y1f; } dd = GetPointToLineSegmentDistance( x2i, y2i, x1i, y1i, x1f, y1f ); if( dd < dist ) { dist = dd; xx = x2i; yy = y2i; } dd = GetPointToLineSegmentDistance( x2f, y2f, x1i, y1i, x1f, y1f ); if( dd < dist ) { dist = dd; xx = x2f; yy = y2f; } if( x ) *x = KiROUND( xx ); if( y ) *y = KiROUND( yy ); if( d ) *d = dist; return false; }