2014-11-08 12:25:29 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
2018-01-29 10:37:29 +00:00
|
|
|
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
2014-11-08 12:25:29 +00:00
|
|
|
* Copyright (C) 2004-2014 KiCad Developers, see change_log.txt for contributors.
|
2018-01-29 10:37:29 +00:00
|
|
|
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
|
2014-11-08 12:25:29 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2018-01-29 10:37:29 +00:00
|
|
|
* @file eda_rect.h
|
2014-11-08 12:25:29 +00:00
|
|
|
*/
|
|
|
|
|
2018-01-29 10:37:29 +00:00
|
|
|
#ifndef EDA_RECT_H
|
|
|
|
#define EDA_RECT_H
|
2014-11-08 12:25:29 +00:00
|
|
|
|
2016-04-07 11:09:31 +00:00
|
|
|
#include <wx/gdicmn.h>
|
2017-03-07 12:06:00 +00:00
|
|
|
#include <math/box2.h>
|
2016-04-07 11:09:31 +00:00
|
|
|
|
2014-11-08 12:25:29 +00:00
|
|
|
/**
|
2020-01-10 14:31:00 +00:00
|
|
|
* EDA_RECT
|
2014-11-08 12:25:29 +00:00
|
|
|
* handles the component boundary box.
|
|
|
|
* This class is similar to wxRect, but some wxRect functions are very curious,
|
|
|
|
* and are working only if dimensions are >= 0 (not always the case in KiCad)
|
|
|
|
* and also KiCad needs some specific method.
|
|
|
|
* so I prefer this more suitable class
|
|
|
|
*/
|
|
|
|
class EDA_RECT
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
wxPoint m_Pos; // Rectangle Origin
|
|
|
|
wxSize m_Size; // Rectangle Size
|
2019-08-16 05:54:16 +00:00
|
|
|
bool m_init; // Is the rectangle initialized
|
2014-11-08 12:25:29 +00:00
|
|
|
|
|
|
|
public:
|
2019-08-16 05:54:16 +00:00
|
|
|
EDA_RECT() : m_init( false ) { };
|
2014-11-08 12:25:29 +00:00
|
|
|
|
|
|
|
EDA_RECT( const wxPoint& aPos, const wxSize& aSize ) :
|
|
|
|
m_Pos( aPos ),
|
2019-08-16 05:54:16 +00:00
|
|
|
m_Size( aSize ),
|
|
|
|
m_init( true )
|
2014-11-08 12:25:29 +00:00
|
|
|
{ }
|
|
|
|
|
2018-01-06 05:02:28 +00:00
|
|
|
virtual ~EDA_RECT() { };
|
|
|
|
|
2014-11-08 12:25:29 +00:00
|
|
|
wxPoint Centre() const
|
|
|
|
{
|
|
|
|
return wxPoint( m_Pos.x + ( m_Size.x >> 1 ),
|
|
|
|
m_Pos.y + ( m_Size.y >> 1 ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function Move
|
|
|
|
* moves the rectangle by the \a aMoveVector.
|
|
|
|
* @param aMoveVector A wxPoint that is the value to move this rectangle
|
|
|
|
*/
|
|
|
|
void Move( const wxPoint& aMoveVector );
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function Normalize
|
|
|
|
* ensures that the height ant width are positive.
|
|
|
|
*/
|
|
|
|
void Normalize();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function Contains
|
|
|
|
* @param aPoint = the wxPoint to test
|
|
|
|
* @return true if aPoint is inside the boundary box. A point on a edge is seen as inside
|
|
|
|
*/
|
|
|
|
bool Contains( const wxPoint& aPoint ) const;
|
2017-03-07 12:06:00 +00:00
|
|
|
|
2014-11-08 12:25:29 +00:00
|
|
|
/**
|
|
|
|
* Function Contains
|
|
|
|
* @param x = the x coordinate of the point to test
|
|
|
|
* @param y = the x coordinate of the point to test
|
|
|
|
* @return true if point is inside the boundary box. A point on a edge is seen as inside
|
|
|
|
*/
|
|
|
|
bool Contains( int x, int y ) const { return Contains( wxPoint( x, y ) ); }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function Contains
|
|
|
|
* @param aRect = the EDA_RECT to test
|
|
|
|
* @return true if aRect is Contained. A common edge is seen as contained
|
|
|
|
*/
|
|
|
|
bool Contains( const EDA_RECT& aRect ) const;
|
|
|
|
|
2017-11-27 18:47:58 +00:00
|
|
|
const wxSize GetSize() const { return m_Size; }
|
2016-07-19 17:35:25 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief GetSizeMax
|
|
|
|
* @return the max size dimension
|
|
|
|
*/
|
|
|
|
int GetSizeMax() const { return ( m_Size.x > m_Size.y )?m_Size.x:m_Size.y; }
|
|
|
|
|
2014-11-08 12:25:29 +00:00
|
|
|
int GetX() const { return m_Pos.x; }
|
|
|
|
int GetY() const { return m_Pos.y; }
|
|
|
|
|
2017-11-27 18:47:58 +00:00
|
|
|
const wxPoint GetOrigin() const { return m_Pos; }
|
|
|
|
const wxPoint GetPosition() const { return m_Pos; }
|
2014-11-08 12:25:29 +00:00
|
|
|
const wxPoint GetEnd() const { return wxPoint( m_Pos.x + m_Size.x, m_Pos.y + m_Size.y ); }
|
2017-04-22 20:07:29 +00:00
|
|
|
const wxPoint GetCenter() const { return wxPoint( m_Pos.x + ( m_Size.x / 2 ), m_Pos.y + ( m_Size.y / 2 ) ); }
|
2014-11-08 12:25:29 +00:00
|
|
|
|
|
|
|
int GetWidth() const { return m_Size.x; }
|
|
|
|
int GetHeight() const { return m_Size.y; }
|
|
|
|
int GetRight() const { return m_Pos.x + m_Size.x; }
|
|
|
|
int GetLeft() const { return m_Pos.x; }
|
2015-12-13 16:56:47 +00:00
|
|
|
int GetTop() const { return m_Pos.y; }
|
2014-11-08 12:25:29 +00:00
|
|
|
int GetBottom() const { return m_Pos.y + m_Size.y; } // Y axis from top to bottom
|
|
|
|
|
2019-08-16 05:54:16 +00:00
|
|
|
bool IsValid() const
|
2014-11-08 12:25:29 +00:00
|
|
|
{
|
2019-08-16 05:54:16 +00:00
|
|
|
return m_init;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetOrigin( const wxPoint &pos )
|
|
|
|
{
|
|
|
|
m_Pos = pos;
|
|
|
|
m_init = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetOrigin( int x, int y )
|
|
|
|
{
|
|
|
|
m_Pos.x = x;
|
|
|
|
m_Pos.y = y;
|
|
|
|
m_init = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetSize( const wxSize &size )
|
|
|
|
{
|
|
|
|
m_Size = size;
|
|
|
|
m_init = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetSize( int w, int h )
|
|
|
|
{
|
|
|
|
m_Size.x = w;
|
|
|
|
m_Size.y = h;
|
|
|
|
m_init = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Offset( int dx, int dy )
|
|
|
|
{
|
|
|
|
m_Pos.x += dx;
|
|
|
|
m_Pos.y += dy;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Offset( const wxPoint &offset )
|
|
|
|
{
|
|
|
|
m_Pos += offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetX( int val )
|
|
|
|
{
|
|
|
|
m_Pos.x = val;
|
|
|
|
m_init = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetY( int val )
|
|
|
|
{
|
|
|
|
m_Pos.y = val;
|
|
|
|
m_init = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetWidth( int val )
|
|
|
|
{
|
|
|
|
m_Size.x = val;
|
|
|
|
m_init = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetHeight( int val )
|
|
|
|
{
|
|
|
|
m_Size.y = val;
|
|
|
|
m_init = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetEnd( int x, int y )
|
|
|
|
{
|
|
|
|
SetEnd( wxPoint( x, y ) );
|
|
|
|
m_init = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetEnd( const wxPoint &pos )
|
|
|
|
{
|
|
|
|
m_Size.x = pos.x - m_Pos.x;
|
|
|
|
m_Size.y = pos.y - m_Pos.y;
|
|
|
|
m_init = true;
|
2014-11-08 12:25:29 +00:00
|
|
|
}
|
|
|
|
|
2015-06-18 14:56:08 +00:00
|
|
|
/**
|
|
|
|
* Function RevertYAxis
|
|
|
|
* Mirror the rectangle from the X axis (negate Y pos and size)
|
|
|
|
*/
|
|
|
|
void RevertYAxis()
|
|
|
|
{
|
|
|
|
m_Pos.y = -m_Pos.y;
|
|
|
|
m_Size.y = -m_Size.y;
|
|
|
|
Normalize();
|
|
|
|
}
|
|
|
|
|
2014-11-08 12:25:29 +00:00
|
|
|
/**
|
|
|
|
* Function Intersects
|
|
|
|
* tests for a common area between rectangles.
|
|
|
|
*
|
|
|
|
* @param aRect A rectangle to test intersection with.
|
|
|
|
* @return bool - true if the argument rectangle intersects this rectangle.
|
|
|
|
* (i.e. if the 2 rectangles have at least a common point)
|
|
|
|
*/
|
|
|
|
bool Intersects( const EDA_RECT& aRect ) const;
|
|
|
|
|
2017-04-23 00:06:56 +00:00
|
|
|
/**
|
|
|
|
* Tests for a common area between this rectangle,
|
|
|
|
* and a rectangle with arbitrary rotation
|
|
|
|
*
|
|
|
|
* @param aRect a rectangle to test intersection with
|
|
|
|
* @param aRot rectangle rotation (in 1/10 degrees)
|
|
|
|
*/
|
|
|
|
bool Intersects( const EDA_RECT& aRect, double aRot ) const;
|
|
|
|
|
2014-11-08 12:25:29 +00:00
|
|
|
/**
|
|
|
|
* Function Intersects
|
|
|
|
* tests for a common area between a segment and this rectangle.
|
|
|
|
*
|
|
|
|
* @param aPoint1 First point of the segment to test intersection with.
|
|
|
|
* @param aPoint2 Second point of the segment to test intersection with.
|
|
|
|
* @return bool - true if the argument segment intersects this rectangle.
|
|
|
|
* (i.e. if the segment and rectangle have at least a common point)
|
|
|
|
*/
|
|
|
|
bool Intersects( const wxPoint& aPoint1, const wxPoint& aPoint2 ) const;
|
|
|
|
|
2020-09-11 23:52:45 +00:00
|
|
|
/**
|
|
|
|
* Tests for intersection between a segment and this rectangle, returning the intersections
|
|
|
|
* @param aPoint1 is the first point of the segment to test intersection with
|
|
|
|
* @param aPoint2 is the second point of the segment to test intersection with
|
|
|
|
* @param aIntersection1 will be filled with the first intersection point, if any
|
|
|
|
* @param aIntersection2 will be filled with the second intersection point, if any
|
|
|
|
* @return true if the segment intersects the rect
|
|
|
|
*/
|
|
|
|
bool Intersects( const wxPoint& aPoint1, const wxPoint& aPoint2,
|
|
|
|
wxPoint* aIntersection1, wxPoint* aIntersection2 ) const;
|
|
|
|
|
2017-04-20 14:53:57 +00:00
|
|
|
/**
|
|
|
|
* Return the point in this rect that is closest to the provided point
|
|
|
|
*/
|
|
|
|
const wxPoint ClosestPointTo( const wxPoint& aPoint ) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the point in this rect that is farthest from the provided point
|
|
|
|
*/
|
|
|
|
const wxPoint FarthestPointTo( const wxPoint& aPoint ) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function IntersectsCircle
|
|
|
|
* tests for a common area between a circle and this rectangle
|
|
|
|
*
|
|
|
|
* @param aCenter center of the circle
|
|
|
|
* @param aRadius radius of the circle
|
|
|
|
*/
|
|
|
|
bool IntersectsCircle( const wxPoint& aCenter, const int aRadius ) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* IntersectsCircleEdge
|
|
|
|
* Tests for intersection between this rect and the edge (radius) of a circle
|
|
|
|
*
|
|
|
|
* @param aCenter center of the circle
|
|
|
|
* @param aRadius radius of the circle
|
|
|
|
* @param aWidth width of the circle edge
|
|
|
|
*/
|
|
|
|
bool IntersectsCircleEdge( const wxPoint& aCenter, const int aRadius, const int aWidth ) const;
|
|
|
|
|
2014-11-08 12:25:29 +00:00
|
|
|
/**
|
|
|
|
* Function operator(wxRect)
|
|
|
|
* overloads the cast operator to return a wxRect
|
|
|
|
* wxRect does not accept negative values for size, so ensure the
|
|
|
|
* wxRect size is always >= 0
|
|
|
|
*/
|
|
|
|
operator wxRect() const
|
|
|
|
{
|
|
|
|
EDA_RECT rect( m_Pos, m_Size );
|
|
|
|
rect.Normalize();
|
|
|
|
return wxRect( rect.m_Pos, rect.m_Size );
|
|
|
|
}
|
|
|
|
|
2017-03-07 12:06:00 +00:00
|
|
|
/**
|
|
|
|
* Function operator(BOX2I)
|
|
|
|
* overloads the cast operator to return a BOX2I
|
|
|
|
* @return BOX2I - this box shaped as a BOX2I object.
|
|
|
|
*/
|
|
|
|
operator BOX2I() const
|
|
|
|
{
|
|
|
|
EDA_RECT rect( m_Pos, m_Size );
|
|
|
|
rect.Normalize();
|
2017-12-10 22:04:23 +00:00
|
|
|
return BOX2I( rect.GetOrigin(), rect.GetSize() );
|
2017-03-07 12:06:00 +00:00
|
|
|
}
|
|
|
|
|
2014-11-08 12:25:29 +00:00
|
|
|
/**
|
|
|
|
* Function Inflate
|
|
|
|
* inflates the rectangle horizontally by \a dx and vertically by \a dy. If \a dx
|
|
|
|
* and/or \a dy is negative the rectangle is deflated.
|
|
|
|
*/
|
|
|
|
EDA_RECT& Inflate( wxCoord dx, wxCoord dy );
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function Inflate
|
|
|
|
* inflates the rectangle horizontally and vertically by \a aDelta. If \a aDelta
|
|
|
|
* is negative the rectangle is deflated.
|
|
|
|
*/
|
|
|
|
EDA_RECT& Inflate( int aDelta );
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function Merge
|
|
|
|
* modifies the position and size of the rectangle in order to contain \a aRect. It is
|
|
|
|
* mainly used to calculate bounding boxes.
|
|
|
|
* @param aRect The rectangle to merge with this rectangle.
|
|
|
|
*/
|
|
|
|
void Merge( const EDA_RECT& aRect );
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function Merge
|
|
|
|
* modifies the position and size of the rectangle in order to contain the given point.
|
|
|
|
* @param aPoint The point to merge with the rectangle.
|
|
|
|
*/
|
|
|
|
void Merge( const wxPoint& aPoint );
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function GetArea
|
|
|
|
* returns the area of the rectangle.
|
|
|
|
* @return The area of the rectangle.
|
|
|
|
*/
|
|
|
|
double GetArea() const;
|
|
|
|
|
2015-07-30 11:49:35 +00:00
|
|
|
/**
|
|
|
|
* Function Common
|
|
|
|
* returns the area that is common with another rectangle.
|
|
|
|
* @param aRect is the rectangle to find the common area with.
|
|
|
|
* @return The common area rect or 0-sized rectangle if there is no intersection.
|
|
|
|
*/
|
|
|
|
EDA_RECT Common( const EDA_RECT& aRect ) const;
|
|
|
|
|
2014-11-08 12:25:29 +00:00
|
|
|
/**
|
|
|
|
* Function GetBoundingBoxRotated
|
|
|
|
* @return the bounding box of this, after rotation
|
|
|
|
* @param aAngle = the rotation angle in 0.1 deg.
|
|
|
|
* @param aRotCenter = the rotation point.
|
|
|
|
* useful to calculate bounding box of rotated items, when
|
|
|
|
* rotation if not k*90 degrees
|
|
|
|
*/
|
2020-09-16 22:45:08 +00:00
|
|
|
const EDA_RECT GetBoundingBoxRotated( wxPoint aRotCenter, double aAngle ) const;
|
2014-11-08 12:25:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2018-01-29 10:37:29 +00:00
|
|
|
#endif // EDA_RECT_H
|