Commit 30e1aaec authored by Maciej Suminski's avatar Maciej Suminski
Browse files

Replacement of classes BOX2 and VECTOR2 with their extended versions

include/vector2d.h: Removed old version
include/math/math_util.h: rescale() for VECTOR2
include/math/vector2d.h: New version of VECTOR2
include/math/box2.h: New version of BOX2
common/drawframe.cpp: Refactorization of code, so it is compatible with new classes
include/plot_common.h, pcbnew/basepcbframe.cpp: Changed header inclusion path
CMakeLists.txt: Added definition to turn on WX_COMPATIBILITY for replacement classes
parent 2b929702
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -248,6 +248,9 @@ include(Functions)
#================================================
#================================================
include(CheckFindPackageResult)
include(CheckFindPackageResult)


# Turn on wxWidgets compatibility mode for some classes 
add_definitions(-DWX_COMPATIBILITY)

#######################
#######################
# Find OpenGL library #
# Find OpenGL library #
#######################
#######################
+27 −27
Original line number Original line Diff line number Diff line
@@ -42,7 +42,7 @@
#include <kicad_device_context.h>
#include <kicad_device_context.h>
#include <dialog_helpers.h>
#include <dialog_helpers.h>
#include <base_units.h>
#include <base_units.h>
#include <vector2d.h>
#include <math/box2.h>


#include <wx/fontdlg.h>
#include <wx/fontdlg.h>


@@ -753,7 +753,7 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
    DSIZE   clientSizeIU( clientSizeDU.x / scale, clientSizeDU.y / scale );
    DSIZE   clientSizeIU( clientSizeDU.x / scale, clientSizeDU.y / scale );


    // Full drawing or "page" rectangle in internal units
    // Full drawing or "page" rectangle in internal units
    DBOX    pageRectIU( 0, 0, GetPageSizeIU().x, GetPageSizeIU().y );
    DBOX    pageRectIU( wxPoint( 0, 0 ), wxSize( GetPageSizeIU().x, GetPageSizeIU().y ) );


    // The upper left corner of the client rectangle in internal units.
    // The upper left corner of the client rectangle in internal units.
    double xIU = aCenterPositionIU.x - clientSizeIU.x / 2.0;
    double xIU = aCenterPositionIU.x - clientSizeIU.x / 2.0;
@@ -763,11 +763,11 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
    if( screen->m_Center )
    if( screen->m_Center )
    {
    {
        // half page offset.
        // half page offset.
        xIU += pageRectIU.width  / 2.0;
        xIU += pageRectIU.GetWidth()  / 2.0;
        yIU += pageRectIU.height / 2.0;
        yIU += pageRectIU.GetHeight() / 2.0;
    }
    }


    DBOX    clientRectIU( xIU, yIU, clientSizeIU.x, clientSizeIU.y );
    DBOX    clientRectIU( wxPoint( xIU, yIU ), wxSize( clientSizeIU.x, clientSizeIU.y ) );
    wxPoint centerPositionIU;
    wxPoint centerPositionIU;


#if 1 || defined( USE_PCBNEW_NANOMETRES )
#if 1 || defined( USE_PCBNEW_NANOMETRES )
@@ -782,13 +782,13 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
        clientRectIU.MoveBottomTo( VIRT_MAX );
        clientRectIU.MoveBottomTo( VIRT_MAX );
#endif
#endif


    centerPositionIU.x = KiROUND( clientRectIU.x + clientRectIU.width/2 );
    centerPositionIU.x = KiROUND( clientRectIU.GetX() + clientRectIU.GetWidth() / 2 );
    centerPositionIU.y = KiROUND( clientRectIU.y + clientRectIU.height/2 );
    centerPositionIU.y = KiROUND( clientRectIU.GetY() + clientRectIU.GetHeight() / 2 );


    if( screen->m_Center )
    if( screen->m_Center )
    {
    {
        centerPositionIU.x -= KiROUND( pageRectIU.width  / 2.0 );
        centerPositionIU.x -= KiROUND( pageRectIU.GetWidth() / 2.0 );
        centerPositionIU.y -= KiROUND( pageRectIU.height  / 2.0 );
        centerPositionIU.y -= KiROUND( pageRectIU.GetHeight() / 2.0 );
    }
    }


    DSIZE   virtualSizeIU;
    DSIZE   virtualSizeIU;
@@ -799,26 +799,26 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
    }
    }
    else
    else
    {
    {
        double pageCenterX    = pageRectIU.x   + ( pageRectIU.width / 2 );
        double pageCenterX    = pageRectIU.GetX()   + ( pageRectIU.GetWidth() / 2 );
        double clientCenterX  = clientRectIU.x + ( clientRectIU.width / 2 );
        double clientCenterX  = clientRectIU.GetX() + ( clientRectIU.GetWidth() / 2 );


        if( clientRectIU.width > pageRectIU.width )
        if( clientRectIU.GetWidth() > pageRectIU.GetWidth() )
        {
        {
            if( pageCenterX > clientCenterX )
            if( pageCenterX > clientCenterX )
                virtualSizeIU.x = ( pageCenterX - clientRectIU.GetLeft() ) * 2;
                virtualSizeIU.x = ( pageCenterX - clientRectIU.GetLeft() ) * 2;
            else if( pageCenterX < clientCenterX )
            else if( pageCenterX < clientCenterX )
                virtualSizeIU.x = ( clientRectIU.GetRight() - pageCenterX ) * 2;
                virtualSizeIU.x = ( clientRectIU.GetRight() - pageCenterX ) * 2;
            else
            else
                virtualSizeIU.x = clientRectIU.width;
                virtualSizeIU.x = clientRectIU.GetWidth();
        }
        }
        else
        else
        {
        {
            if( pageCenterX > clientCenterX )
            if( pageCenterX > clientCenterX )
                virtualSizeIU.x = pageRectIU.width + ( (pageRectIU.GetLeft() - clientRectIU.GetLeft() ) * 2 );
                virtualSizeIU.x = pageRectIU.GetWidth() + ( (pageRectIU.GetLeft() - clientRectIU.GetLeft() ) * 2 );
            else if( pageCenterX < clientCenterX )
            else if( pageCenterX < clientCenterX )
                virtualSizeIU.x = pageRectIU.width + ( (clientRectIU.GetRight() - pageRectIU.GetRight() ) * 2 );
                virtualSizeIU.x = pageRectIU.GetWidth() + ( (clientRectIU.GetRight() - pageRectIU.GetRight() ) * 2 );
            else
            else
                virtualSizeIU.x = pageRectIU.width;
                virtualSizeIU.x = pageRectIU.GetWidth();
        }
        }
    }
    }


@@ -828,28 +828,28 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
    }
    }
    else
    else
    {
    {
        double pageCenterY   = pageRectIU.y   + ( pageRectIU.height / 2 );
        double pageCenterY   = pageRectIU.GetY()   + ( pageRectIU.GetHeight() / 2 );
        double clientCenterY = clientRectIU.y + ( clientRectIU.height / 2 );
        double clientCenterY = clientRectIU.GetY() + ( clientRectIU.GetHeight() / 2 );


        if( clientRectIU.height > pageRectIU.height )
        if( clientRectIU.GetHeight() > pageRectIU.GetHeight() )
        {
        {
            if( pageCenterY > clientCenterY )
            if( pageCenterY > clientCenterY )
                virtualSizeIU.y = ( pageCenterY - clientRectIU.GetTop() ) * 2;
                virtualSizeIU.y = ( pageCenterY - clientRectIU.GetTop() ) * 2;
            else if( pageCenterY < clientCenterY )
            else if( pageCenterY < clientCenterY )
                virtualSizeIU.y = ( clientRectIU.GetBottom() - pageCenterY ) * 2;
                virtualSizeIU.y = ( clientRectIU.GetBottom() - pageCenterY ) * 2;
            else
            else
                virtualSizeIU.y = clientRectIU.height;
                virtualSizeIU.y = clientRectIU.GetHeight();
        }
        }
        else
        else
        {
        {
            if( pageCenterY > clientCenterY )
            if( pageCenterY > clientCenterY )
                virtualSizeIU.y = pageRectIU.height +
                virtualSizeIU.y = pageRectIU.GetHeight() +
                                ( ( pageRectIU.GetTop() - clientRectIU.GetTop() ) * 2 );
                                ( ( pageRectIU.GetTop() - clientRectIU.GetTop() ) * 2 );
            else if( pageCenterY < clientCenterY )
            else if( pageCenterY < clientCenterY )
                virtualSizeIU.y = pageRectIU.height +
                virtualSizeIU.y = pageRectIU.GetHeight() +
                                ( ( clientRectIU.GetBottom() - pageRectIU.GetBottom() ) * 2 );
                                ( ( clientRectIU.GetBottom() - pageRectIU.GetBottom() ) * 2 );
            else
            else
                virtualSizeIU.y = pageRectIU.height;
                virtualSizeIU.y = pageRectIU.GetHeight();
        }
        }
    }
    }


@@ -866,8 +866,8 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
    }
    }
    else
    else
    {
    {
        screen->m_DrawOrg.x = -KiROUND( ( virtualSizeIU.x - pageRectIU.width )  / 2.0 );
        screen->m_DrawOrg.x = -KiROUND( ( virtualSizeIU.x - pageRectIU.GetWidth() )  / 2.0 );
        screen->m_DrawOrg.y = -KiROUND( ( virtualSizeIU.y - pageRectIU.height ) / 2.0 );
        screen->m_DrawOrg.y = -KiROUND( ( virtualSizeIU.y - pageRectIU.GetHeight() ) / 2.0 );
    }
    }


    /* Always set scrollbar pixels per unit to 1 unless you want the zoom
    /* Always set scrollbar pixels per unit to 1 unless you want the zoom
@@ -886,8 +886,8 @@ void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU )
    // center position at the center of client rectangle.
    // center position at the center of client rectangle.
    screen->SetScrollCenterPosition( centerPositionIU );
    screen->SetScrollCenterPosition( centerPositionIU );


    double posX = centerPositionIU.x - clientRectIU.width /2.0 - screen->m_DrawOrg.x;
    double posX = centerPositionIU.x - clientRectIU.GetWidth()  / 2.0 - screen->m_DrawOrg.x;
    double posY = centerPositionIU.y - clientRectIU.height/2.0 - screen->m_DrawOrg.y;
    double posY = centerPositionIU.y - clientRectIU.GetHeight() / 2.0 - screen->m_DrawOrg.y;


    // Convert scroll bar position to device units.
    // Convert scroll bar position to device units.
    posX = KiROUND( posX * scale );
    posX = KiROUND( posX * scale );

include/math/box2.h

0 → 100644
+483 −0
Original line number Original line Diff line number Diff line
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
 * Copyright (C) 2008-2011 Wayne Stambaugh <stambaughw@verizon.net>
 * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors.
 * Copyright (C) 2013 CERN
 *
 * 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 __BOX2_H
#define __BOX2_H

#include <math/vector2d.h>


template <class Vec>
class BOX2_TRAITS
{
};

template <>
class BOX2_TRAITS<VECTOR2I>
{
public:
    enum {
        c_max_size = INT_MAX - 1,
        c_min_coord_value = INT_MIN / 2 + 1
    };
};

/**
 * Class BOX2
 * handles a 2-D bounding box, built on top of an origin point
 * and size vector, both of templated class Vec
 */
template <class Vec>
class BOX2
{
private:
    Vec m_Pos;      // Rectangle Origin
    Vec m_Size;     // Rectangle Size

public:
    typedef typename Vec::coord_type    coord_type;
    typedef typename Vec::extended_type ecoord_type;

    BOX2() { };

    BOX2( const Vec& aPos, const Vec& aSize ) :
        m_Pos( aPos ),
        m_Size( aSize )
    { }

    void SetMaximum()
    {
        m_Pos.x  = m_Pos.y = BOX2_TRAITS<Vec>().c_min_coord_value;
        m_Size.x = m_Size.y = BOX2_TRAITS<Vec>().c_max_size;
    }

    Vec Centre() const
    {
        return Vec( m_Pos.x + ( m_Size.x / 2 ),
                    m_Pos.y + ( m_Size.y / 2 ) );
    }

    /**
     * @brief Compute the bounding box from a given list of points.
     *
     * @param aPointList is the list points of the object.
     */
    template <class Container>
    void Compute( const Container& aPointList )
    {
        Vec vmin, vmax;
        typename Container::const_iterator i;

        if( !aPointList.size() )
            return;

        vmin = vmax = aPointList[0];

        for( i = aPointList.begin(); i != aPointList.end(); ++i )
        {
            Vec p( *i );
            vmin.x  = std::min( vmin.x, p.x );
            vmin.y  = std::min( vmin.y, p.y );
            vmax.x  = std::max( vmax.x, p.x );
            vmax.y  = std::max( vmax.y, p.y );
        }

        SetOrigin( vmin );
        SetSize( vmax - vmin );
    }

    /**
     * Function Move
     * moves the rectangle by the \a aMoveVector.
     * @param aMoveVector A point that is the value to move this rectangle
     */
    void Move( const Vec& aMoveVector )
    {
        m_Pos += aMoveVector;
    }

    /**
     * Function Normalize
     * ensures that the height ant width are positive.
     */
    BOX2<Vec>& Normalize()
    {
        if( m_Size.y < 0 )
        {
            m_Size.y = -m_Size.y;
            m_Pos.y -= m_Size.y;
        }

        if( m_Size.x < 0 )
        {
            m_Size.x = -m_Size.x;
            m_Pos.x -= m_Size.x;
        }

        return *this;
    }

    /**
     * Function Contains
     * @param aPoint = the point to test
     * @return true if aPoint is inside the boundary box. A point on a edge is seen as inside
     */
    bool Contains( const Vec& aPoint ) const
    {
        Vec rel_pos = aPoint - m_Pos;
        Vec size    = m_Size;

        if( size.x < 0 )
        {
            size.x    = -size.x;
            rel_pos.x += size.x;
        }

        if( size.y < 0 )
        {
            size.y    = -size.y;
            rel_pos.y += size.y;
        }

        return (rel_pos.x >= 0) && (rel_pos.y >= 0) && ( rel_pos.y <= size.y) && ( rel_pos.x <= size.x);
    }

    /**
     * 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( coord_type x, coord_type y ) const { return Contains( Vec( x, y ) ); }

    /**
     * Function Contains
     * @param aRect = the BOX2 to test
     * @return true if aRect is Contained. A common edge is seen as contained
     */
    bool Contains( const BOX2<Vec>& aRect ) const
    {
        return Contains( aRect.GetOrigin() ) && Contains( aRect.GetEnd() );
    }

    const Vec& GetSize() const { return m_Size; }
    coord_type GetX() const { return m_Pos.x; }
    coord_type GetY() const { return m_Pos.y; }

    const Vec& GetOrigin() const { return m_Pos; }
    const Vec& GetPosition() const { return m_Pos; }
    const Vec GetEnd() const { return Vec( GetRight(), GetBottom() ); }

    coord_type GetWidth() const { return m_Size.x; }
    coord_type GetHeight() const { return m_Size.y; }
    coord_type GetRight() const { return m_Pos.x + m_Size.x; }
    coord_type GetBottom() const { return m_Pos.y + m_Size.y; }

    // Compatibility aliases
    coord_type GetLeft() const { return GetX(); }
    coord_type GetTop() const { return GetY(); }
    void MoveTopTo( coord_type aTop ) { m_Pos.y = aTop; }
    void MoveBottomTo( coord_type aBottom ) { m_Size.y = aBottom - m_Pos.y; }
    void MoveLeftTo( coord_type aLeft ) { m_Pos.x = aLeft; }
    void MoveRightTo( coord_type aRight ) { m_Size.x = aRight - m_Pos.x; }

    void SetOrigin( const Vec& pos ) { m_Pos = pos; }
    void SetOrigin( coord_type x, coord_type y ) { m_Pos.x = x; m_Pos.y = y; }
    void SetSize( const Vec& size ) { m_Size = size; }
    void SetSize( coord_type w, coord_type h ) { m_Size.x = w; m_Size.y = h; }
    void Offset( coord_type dx, coord_type dy ) { m_Pos.x += dx; m_Pos.y += dy; }
    void Offset( const Vec& offset )
    {
        m_Pos.x += offset.x; m_Pos.y +=
            offset.y;
    }

    void SetX( coord_type val ) { m_Pos.x = val; }
    void SetY( coord_type val ) { m_Pos.y = val; }
    void SetWidth( coord_type val ) { m_Size.x = val; }
    void SetHeight( coord_type val ) { m_Size.y = val; }
    void SetEnd( coord_type x, coord_type y ) { SetEnd( Vec( x, y ) ); }
    void SetEnd( const Vec& pos )
    {
        m_Size.x = pos.x - m_Pos.x; m_Size.y = pos.y - m_Pos.y;
    }

    /**
     * Function Intersects
     * @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 BOX2<Vec>& aRect ) const
    {
        // this logic taken from wxWidgets' geometry.cpp file:
        bool        rc;

        BOX2<Vec>   me( *this );
        BOX2<Vec>   rect( aRect );
        me.Normalize();         // ensure size is >= 0
        rect.Normalize();       // ensure size is >= 0

        // calculate the left common area coordinate:
        int  left   = std::max( me.m_Pos.x, rect.m_Pos.x );
        // calculate the right common area coordinate:
        int  right  = std::min( me.m_Pos.x + me.m_Size.x, rect.m_Pos.x + rect.m_Size.x );
        // calculate the upper common area coordinate:
        int  top    = std::max( me.m_Pos.y, aRect.m_Pos.y );
        // calculate the lower common area coordinate:
        int  bottom = std::min( me.m_Pos.y + me.m_Size.y, rect.m_Pos.y + rect.m_Size.y );

        // if a common area exists, it must have a positive (null accepted) size
        if( left <= right && top <= bottom )
            rc = true;
        else
            rc = false;

        return rc;
    }

    const std::string Format() const
    {
        std::stringstream ss;

        ss << "( box corner " << m_Pos.Format() << " w " << m_Size.x << " h " << m_Size.y << " )";

        return ss.str();
    }

    /**
     * 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.
     */
    BOX2<Vec>& Inflate( coord_type dx, coord_type dy )
    {
        if( m_Size.x >= 0 )
        {
            if( m_Size.x < -2 * dx )
            {
                // Don't allow deflate to eat more width than we have,
                m_Pos.x += m_Size.x / 2;
                m_Size.x = 0;
            }
            else
            {
                // The inflate is valid.
                m_Pos.x  -= dx;
                m_Size.x += 2 * dx;
            }
        }
        else    // size.x < 0:
        {
            if( m_Size.x > -2 * dx )
            {
                // Don't allow deflate to eat more width than we have,
                m_Pos.x -= m_Size.x / 2;
                m_Size.x = 0;
            }
            else
            {
                // The inflate is valid.
                m_Pos.x  += dx;
                m_Size.x -= 2 * dx; // m_Size.x <0: inflate when dx > 0
            }
        }

        if( m_Size.y >= 0 )
        {
            if( m_Size.y < -2 * dy )
            {
                // Don't allow deflate to eat more height than we have,
                m_Pos.y += m_Size.y / 2;
                m_Size.y = 0;
            }
            else
            {
                // The inflate is valid.
                m_Pos.y  -= dy;
                m_Size.y += 2 * dy;
            }
        }
        else    // size.y < 0:
        {
            if( m_Size.y > 2 * dy )
            {
                // Don't allow deflate to eat more height than we have,
                m_Pos.y -= m_Size.y / 2;
                m_Size.y = 0;
            }
            else
            {
                // The inflate is valid.
                m_Pos.y  += dy;
                m_Size.y -= 2 * dy; // m_Size.y <0: inflate when dy > 0
            }
        }

        return *this;
    }

    /**
     * Function Inflate
     * inflates the rectangle horizontally and vertically by \a aDelta. If \a aDelta
     * is negative the rectangle is deflated.
     */
    BOX2<Vec>& Inflate( int aDelta )
    {
        Inflate( aDelta, aDelta );
        return *this;
    }

    /**
     * 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.
     */
    BOX2<Vec>& Merge( const BOX2<Vec>& aRect )
    {
        Normalize();        // ensure width and height >= 0
        BOX2<Vec> rect = aRect;
        rect.Normalize();   // ensure width and height >= 0
        Vec  end = GetEnd();
        Vec  rect_end = rect.GetEnd();

        // Change origin and size in order to contain the given rect
        m_Pos.x = std::min( m_Pos.x, rect.m_Pos.x );
        m_Pos.y = std::min( m_Pos.y, rect.m_Pos.y );
        end.x   = std::max( end.x, rect_end.x );
        end.y   = std::max( end.y, rect_end.y );
        SetEnd( end );
        return *this;
    }

    /**
     * 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.
     */
    BOX2<Vec>& Merge( const Vec& aPoint )
    {
        Normalize();        // ensure width and height >= 0

        Vec end = GetEnd();
        // Change origin and size in order to contain the given rect
        m_Pos.x = std::min( m_Pos.x, aPoint.x );
        m_Pos.y = std::min( m_Pos.y, aPoint.y );
        end.x   = std::max( end.x, aPoint.x );
        end.y   = std::max( end.y, aPoint.y );
        SetEnd( end );
        return *this;
    }

    /**
     * Function GetArea
     * returns the area of the rectangle.
     * @return The area of the rectangle.
     */
    ecoord_type GetArea() const
    {
        return (ecoord_type) GetWidth() * (ecoord_type) GetHeight();
    }

    /**
     * Function GetArea
     * returns the length of the diagonal of the rectangle.
     * @return The area of the diagonal.
     */
    ecoord_type Diagonal() const
    {
        return m_Size.EuclideanNorm();
    }

    ecoord_type SquaredDistance( const Vec& aP ) const
    {
        ecoord_type x2 = m_Pos.x + m_Size.x;
        ecoord_type y2 = m_Pos.y + m_Size.y;
        ecoord_type xdiff = std::max( aP.x < m_Pos.x ? m_Pos.x - aP.x : m_Pos.x - x2, 0 );
        ecoord_type ydiff = std::max( aP.y < m_Pos.y ? m_Pos.y - aP.y : m_Pos.y - y2, 0 );
        return xdiff * xdiff + ydiff * ydiff;
    }

    ecoord_type Distance( const Vec& aP ) const
    {
        return sqrt( SquaredDistance( aP ) );
    }

    /**
     * Function SquaredDistance
     * returns the square of the minimum distance between self and box aBox
     * @param aBox: the other box
     * @return The distance, squared
     */
    ecoord_type SquaredDistance( const BOX2<Vec>& aBox ) const
    {
        ecoord_type s = 0;

        if( aBox.m_Pos.x + aBox.m_Size.x < m_Pos.x )
        {
            ecoord_type d = aBox.m_Pos.x + aBox.m_Size.x - m_Pos.x;
            s += d * d;
        }
        else if( aBox.m_Pos.x > m_Pos.x + m_Size.x )
        {
            ecoord_type d = aBox.m_Pos.x - m_Size.x - m_Pos.x;
            s += d * d;
        }

        if( aBox.m_Pos.y + aBox.m_Size.y < m_Pos.y )
        {
            ecoord_type d = aBox.m_Pos.y + aBox.m_Size.y - m_Pos.y;
            s += d * d;
        }
        else if( aBox.m_Pos.y > m_Pos.y + m_Size.y )
        {
            ecoord_type d = aBox.m_Pos.y - m_Size.y - m_Pos.y;
            s += d * d;
        }

        return s;
    }

    /**
     * Function Distance
     * returns the minimum distance between self and box aBox
     * @param aBox: the other box
     * @return The distance
     */
    ecoord_type Distance( const BOX2<Vec>& aBox ) const
    {
        return sqrt( SquaredDistance( aBox ) );
    }
};

/* Default specializations */
typedef BOX2<VECTOR2I>    BOX2I;
typedef BOX2<VECTOR2D>    BOX2D;

// FIXME should be removed to avoid multiple typedefs for the same type
typedef BOX2D             DBOX;

#endif
+97 −0
Original line number Original line Diff line number Diff line
/*
 * This program source code file is part of KICAD, a free EDA CAD application.
 *
 * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
 * Copyright (C) 2013 Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
 *
 * 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 __MATH_UTIL_H
#define __MATH_UTIL_H

#include <cmath>
#include <cstdlib>
#include <stdint.h>

/**
 * Function rescale()
 *
 * Scales a number (value) by rational (numerator/denominator). Numerator must be <= denominator.
 */

template<typename T> static T rescale( T numerator, T value, T denominator )
{
    return numerator * value / denominator;
}


// explicit specializations for integer types, taking care of overflow.
template<> int rescale( int numerator, int value, int denominator )
{
    return (int) ( (int64_t) numerator * (int64_t) value / (int64_t) denominator );
}

template<> int64_t rescale( int64_t numerator, int64_t value, int64_t denominator )
{
    uint64_t r = 0;
    int64_t sign = ( ( numerator < 0) ? -1 : 1 ) * ( denominator < 0 ? - 1: 1 ) * (value < 0 ? - 1 : 1);

    uint64_t a = abs( numerator );
    uint64_t b = abs( value );
    uint64_t c = abs( denominator );

    r = c / 2;

    if( b <= INT_MAX && c <= INT_MAX )
    {
        if( a <= INT_MAX )
            return sign * ( (a * b + r ) / c );
        else
            return sign * (a / c * b + (a % c * b + r) / c);
    } else {
        uint64_t a0 = a & 0xFFFFFFFF;
        uint64_t a1 = a >> 32;
        uint64_t b0 = b & 0xFFFFFFFF;
        uint64_t b1 = b >> 32;
        uint64_t t1 = a0 * b1 + a1 * b0;
        uint64_t t1a = t1 << 32;
        int i;
   
        a0 = a0 * b0 + t1a;
        a1 = a1 * b1 + (t1 >> 32) + (a0 < t1a);
        a0 += r;
        a1 += a0 < r;

        for( i = 63; i >= 0; i-- )
        {
            a1  += a1 + ( (a0 >> i) & 1 );
            t1  += t1;

            if( c <= a1 )
            {
                a1 -= c;
                t1++;
            }
        }

        return t1 * sign;
    }
};

#endif // __MATH_UTIL_H
Loading