Commit 1a97b31d authored by Marco Mattila's avatar Marco Mattila
Browse files

Combine DRAWSEGMENT and EDGE_MOD code in pcbnew.

parent e414f8da
Loading
Loading
Loading
Loading
+0 −45
Original line number Diff line number Diff line
@@ -168,51 +168,6 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon(
    }
}

/**
 * Function TransformShapeWithClearanceToPolygon
 * Convert the track shape to a closed polygon
 * Used in filling zones calculations
 * Circles and arcs are approximated by segments
 * @param aCornerBuffer = a buffer to store the polygon
 * @param aClearanceValue = the clearance around the pad
 * @param aCircleToSegmentsCount = the number of segments to approximate a circle
 * @param aCorrectionFactor = the correction to apply to circles radius to keep
 * clearance when the circle is approxiamted by segment bigger or equal
 * to the real clearance value (usually near from 1.0)
 */
void EDGE_MODULE::TransformShapeWithClearanceToPolygon(
    std::vector <CPolyPt>& aCornerBuffer,
    int                    aClearanceValue,
    int                    aCircleToSegmentsCount,
    double                 aCorrectionFactor )
{
    switch( m_Shape )
    {
    case S_CIRCLE:
        TransformArcToPolygon( aCornerBuffer, m_Start,         // Circle centre
                              m_End, 3600,
                              aCircleToSegmentsCount,
                              m_Width + (2 * aClearanceValue) );
        break;

    case S_ARC:
        TransformArcToPolygon( aCornerBuffer, m_Start,
                              m_End, m_Angle,
                              aCircleToSegmentsCount,
                              m_Width + (2 * aClearanceValue) );
        break;

    case S_SEGMENT:
        TransformRoundedEndsSegmentToPolygon(
            aCornerBuffer, m_Start, m_End,
            aCircleToSegmentsCount, m_Width + (2 * aClearanceValue) );
        break;

    default:
        break;
    }
}


/**
 * Function TransformShapeWithClearanceToPolygon
+186 −136
Original line number Diff line number Diff line
@@ -18,24 +18,24 @@
#include "protos.h"
#include "richio.h"

/* DRAWSEGMENT: constructor */
DRAWSEGMENT::DRAWSEGMENT( BOARD_ITEM* aParent, KICAD_T idtype ) :
    BOARD_ITEM( aParent, idtype )
{
    m_Width = m_Flags = m_Shape = m_Type = m_Angle = 0;
    m_Width = m_Flags = m_Type = m_Angle = 0;
    m_Shape = S_SEGMENT;
}


/* destructor */
DRAWSEGMENT:: ~DRAWSEGMENT()
{
}


/*******************************************/
void DRAWSEGMENT::Copy( DRAWSEGMENT* source )
/*******************************************/
{
    if( source == NULL )
        return;

    m_Type         = source->m_Type;
    m_Layer        = source->m_Layer;
    m_Width        = source->m_Width;
@@ -46,25 +46,17 @@ void DRAWSEGMENT::Copy( DRAWSEGMENT* source )
    m_TimeStamp    = source->m_TimeStamp;
    m_BezierC1     = source->m_BezierC1;
    m_BezierC2     = source->m_BezierC1;
    m_BezierPoints = source->m_BezierPoints;
}

/**
 * Function Rotate
 * Rotate this object.
 * @param aRotCentre - the rotation point.
 * @param aAngle - the rotation angle in 0.1 degree.
 */

void DRAWSEGMENT::Rotate( const wxPoint& aRotCentre, int aAngle )
{
    RotatePoint( &m_Start, aRotCentre, aAngle );
    RotatePoint( &m_End, aRotCentre, aAngle );
}

/**
 * Function Flip
 * Flip this object, i.e. change the board side for this object
 * @param aCentre - the rotation point.
 */

void DRAWSEGMENT::Flip( const wxPoint& aCentre )
{
    m_Start.y  = aCentre.y - (m_Start.y - aCentre.y);
@@ -79,20 +71,22 @@ void DRAWSEGMENT::Flip(const wxPoint& aCentre )

bool DRAWSEGMENT::Save( FILE* aFile ) const
{
    bool rc = false;

    if( fprintf( aFile, "$DRAWSEGMENT\n" ) != sizeof("$DRAWSEGMENT\n") - 1 )
        goto out;
        return false;

    fprintf( aFile, "Po %d %d %d %d %d %d\n",
             m_Shape,
             m_Start.x, m_Start.y,
             m_End.x, m_End.y, m_Width );
    if( m_Type != S_CURVE) {

    if( m_Type != S_CURVE )
    {
        fprintf( aFile, "De %d %d %d %lX %X\n",
                 m_Layer, m_Type, m_Angle,
                 m_TimeStamp, ReturnStatus() );
    } else {
    }
    else
    {
        fprintf( aFile, "De %d %d %d %lX %X %d %d %d %d\n",
                 m_Layer, m_Type, m_Angle,
                 m_TimeStamp, ReturnStatus(),
@@ -101,34 +95,29 @@ bool DRAWSEGMENT::Save( FILE* aFile ) const
    }

    if( fprintf( aFile, "$EndDRAWSEGMENT\n" ) != sizeof("$EndDRAWSEGMENT\n") - 1 )
        goto out;

    rc = true;
        return false;

out:
    return rc;
    return true;
}


/******************************************************************/
bool DRAWSEGMENT::ReadDrawSegmentDescr( LINE_READER* aReader )
/******************************************************************/

/* Read a DRAWSEGMENT from a file
 */
{
    char* Line;

    while( aReader->ReadLine() )
    {
        Line = aReader->Line();

        if( strnicmp( Line, "$End", 4 ) == 0 )
            return TRUE; /* End of description */

        if( Line[0] == 'P' )
        {
            sscanf( Line + 2, " %d %d %d %d %d %d",
                    &m_Shape, &m_Start.x, &m_Start.y,
                    &m_End.x, &m_End.y, &m_Width );

            if( m_Width < 0 )
                m_Width = 0;
        }
@@ -140,8 +129,10 @@ bool DRAWSEGMENT::ReadDrawSegmentDescr( LINE_READER* aReader )

            token = strtok( Line," " );

            for(int i=0; (token = strtok(NULL," ")) != NULL; i++){
            switch(i){
            for( int i = 0; (token = strtok( NULL," " )) != NULL; i++ )
            {
                switch( i )
                {
                case 0:
                    sscanf( token,"%d",&m_Layer );
                    break;
@@ -177,6 +168,7 @@ bool DRAWSEGMENT::ReadDrawSegmentDescr( LINE_READER* aReader )

            if( m_Layer < FIRST_NO_COPPER_LAYER )
                m_Layer = FIRST_NO_COPPER_LAYER;

            if( m_Layer > LAST_NO_COPPER_LAYER )
                m_Layer = LAST_NO_COPPER_LAYER;

@@ -224,6 +216,14 @@ wxPoint DRAWSEGMENT::GetEnd() const
}


MODULE* DRAWSEGMENT::GetParentModule() const
{
    if( m_Parent->Type() != TYPE_MODULE )
        return NULL;

    return (MODULE*) m_Parent;
}


void DRAWSEGMENT::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int draw_mode, const wxPoint& aOffset )
{
@@ -233,6 +233,7 @@ void DRAWSEGMENT::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int draw_mode, const wx
    int rayon;

    BOARD * brd =  GetBoard( );

    if( brd->IsLayerVisible( GetLayer() ) == false )
        return;

@@ -404,12 +405,63 @@ void DRAWSEGMENT::DisplayInfo( EDA_DRAW_FRAME* frame )
}


/**
 * Function HitTest
 * tests if the given wxPoint is within the bounds of this object.
 * @param aRefPos A wxPoint to test
 * @return bool - true if a hit, else false
 */
EDA_RECT DRAWSEGMENT::GetBoundingBox() const
{
    EDA_RECT bbox;

    bbox.SetOrigin( m_Start );

    switch( m_Shape )
    {
    case S_SEGMENT:
        bbox.SetEnd( m_End );
        bbox.Inflate( (m_Width / 2) + 1 );
        break;

    case S_CIRCLE:
        bbox.Inflate( GetRadius() + 1 );
        break;

    case S_ARC:
    {
        bbox.Inflate( GetRadius() + 1 );
    }
    break;

    case S_POLYGON:
    {
        wxPoint p_end;
        MODULE* module = GetParentModule();

        for( unsigned ii = 0; ii < m_PolyPoints.size(); ii++ )
        {
            wxPoint pt = m_PolyPoints[ii];

            if( module ) // Transform, if we belong to a module
            {
                RotatePoint( &pt, module->m_Orient );
                pt += module->m_Pos;
            }

            if( ii == 0 )
                p_end = pt;
            bbox.m_Pos.x = MIN( bbox.m_Pos.x, pt.x );
            bbox.m_Pos.y = MIN( bbox.m_Pos.y, pt.y );
            p_end.x   = MAX( p_end.x, pt.x );
            p_end.y   = MAX( p_end.y, pt.y );
        }

        bbox.SetEnd(p_end);
        bbox.Inflate( 1 );
        break;
    }
    }

    bbox.Inflate( (m_Width+1) / 2 );
    return bbox;
}


bool DRAWSEGMENT::HitTest( const wxPoint& aRefPos )
{
    /* Calculate coordinates to test relative to segment origin. */
@@ -453,21 +505,19 @@ bool DRAWSEGMENT::HitTest( const wxPoint& aRefPos )
        }
        break;

        default:
    case S_SEGMENT:
        if( TestSegmentHit( aRefPos, m_Start, m_End, m_Width / 2 ) )
            return true;
        break;

    default:
        wxASSERT( 0 );
        break;
    }
    return false;
}


/**
 * Function HitTest (overlayed)
 * tests if the given EDA_RECT intersect this object.
 * For now, for arcs and segments, an ending point must be inside this rect.
 * @param refArea : the given EDA_RECT
 * @return bool - true if a hit, else false
 */
bool DRAWSEGMENT::HitTest( EDA_RECT& refArea )
{
    switch( m_Shape )
+24 −1
Original line number Diff line number Diff line
@@ -22,7 +22,10 @@ public:
    wxPoint m_BezierC1;         // Bezier Control Point 1
    wxPoint m_BezierC2;         // Bezier Control Point 1

protected:
    std::vector<wxPoint> m_BezierPoints;
    std::vector<wxPoint> m_PolyPoints;

public:
    DRAWSEGMENT( BOARD_ITEM* aParent, KICAD_T idtype = TYPE_DRAWSEGMENT );
    ~DRAWSEGMENT();
@@ -41,7 +44,6 @@ public:
        return m_Start;
    }


    /**
     * Function GetStart
     * returns the starting point of the graphic
@@ -65,6 +67,17 @@ public:
        return wxRound( radius );
    }

    /**
     * Function GetParentModule
     * returns a pointer to the parent module, or NULL if DRAWSEGMENT does not
     * belong to a module.
     * @return MODULE* - pointer to the parent module or NULL.
     */
    MODULE* GetParentModule() const;

    std::vector<wxPoint>& GetBezierPoints() { return m_BezierPoints; };
    std::vector<wxPoint>& GetPolyPoints() { return m_PolyPoints; };

    /**
     * Function Save
     * writes the data structures for this object out to a FILE in "*.brd" format.
@@ -91,6 +104,16 @@ public:
    virtual void DisplayInfo( EDA_DRAW_FRAME* frame );


    /**
     * Function GetBoundingBox
     * returns the orthogonal, bounding box of this object for display purposes.
     * This box should be an enclosing perimeter for visible components of this
     * object, and the units should be in the pcb or schematic coordinate system.
     * It is OK to overestimate the size by a few counts.
     */
    virtual EDA_RECT GetBoundingBox() const;


    /**
     * Function HitTest
     * tests if the given wxPoint is within the bounds of this object.
+5 −195
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@
/*********************/

EDGE_MODULE::EDGE_MODULE( MODULE* parent ) :
    BOARD_ITEM( parent, TYPE_EDGE_MODULE )
    DRAWSEGMENT( parent, TYPE_EDGE_MODULE )
{
    m_Shape = S_SEGMENT;
    m_Angle = 0;
@@ -42,85 +42,15 @@ void EDGE_MODULE::Copy( EDGE_MODULE* source )
    if( source == NULL )
        return;

    m_Start  = source->m_Start;
    m_End    = source->m_End;
    m_Shape  = source->m_Shape;
    DRAWSEGMENT::Copy( source );

    m_Start0 = source->m_Start0;
    m_End0   = source->m_End0;
    m_Angle  = source->m_Angle;
    m_Layer  = source->m_Layer;
    m_Width  = source->m_Width;

    m_PolyPoints = source->m_PolyPoints;    // std::vector copy
}


/**
 * Function GetBoundingBox
 * returns the orthogonal, bounding box of this object for display purposes.
 * This box should be an enclosing perimeter for visible components of this
 * object, and the units should be in the pcb or schematic coordinate system.
 * It is OK to overestimate the size by a few counts.
 */
EDA_RECT EDGE_MODULE::GetBoundingBox() const
{
    EDA_RECT bbox;

    bbox.SetOrigin( m_Start );

    switch( m_Shape )
    {
    case S_SEGMENT:
        bbox.SetEnd( m_End );
        bbox.Inflate( (m_Width / 2) + 1 );
        break;

    case S_CIRCLE:
        bbox.Inflate( GetRadius() + 1 );
        break;

    case S_ARC:
    {
        bbox.Inflate( GetRadius() + 1 );
    }
    break;

    case S_POLYGON:
    {
        // We must compute true coordinates from m_PolyPoints
        // which are relative to module position, orientation 0

        wxPoint p_end;
        MODULE* Module = (MODULE*) m_Parent;
        for( unsigned ii = 0; ii < m_PolyPoints.size(); ii++ )
        {
            wxPoint pt = m_PolyPoints[ii];

            if( Module )
            {
                RotatePoint( &pt, Module->m_Orient );
                pt += Module->m_Pos;
            }

            if( ii == 0 )
                p_end = pt;
            bbox.m_Pos.x = MIN( bbox.m_Pos.x, pt.x );
            bbox.m_Pos.y = MIN( bbox.m_Pos.y, pt.y );
            p_end.x   = MAX( p_end.x, pt.x );
            p_end.y   = MAX( p_end.y, pt.y );
        }

        bbox.SetEnd(p_end);
        bbox.Inflate( 1 );
        break;
    }
    }

    bbox.Inflate( (m_Width+1) / 2 );
    return bbox;
}


void EDGE_MODULE::SetDrawCoord()
{
    MODULE* Module = (MODULE*) m_Parent;
@@ -158,6 +88,7 @@ void EDGE_MODULE::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int draw_mode, const wx
        return;

    BOARD * brd = GetBoard( );

    if( brd->IsLayerVisible( m_Layer ) == false )
        return;

@@ -481,127 +412,6 @@ int EDGE_MODULE::ReadDescr( LINE_READER* aReader )
}


wxPoint EDGE_MODULE::GetStart() const
{
    switch( m_Shape )
    {
    case S_ARC:
        return m_End;  // the start of the arc is held in field m_End, center point is in m_Start.

    case S_SEGMENT:
    default:
        return m_Start;
    }
}


wxPoint EDGE_MODULE::GetEnd() const
{
    wxPoint endPoint;         // start of arc

    switch( m_Shape )
    {
    case S_ARC:
        // rotate the starting point of the arc, given by m_End, through the
        // angle m_Angle to get the ending point of the arc.
        // m_Start is the arc centre
        endPoint  = m_End;         // m_End = start point of arc
        RotatePoint( &endPoint, m_Start, -m_Angle );
        return endPoint;   // after rotation, the end of the arc.
        break;

    case S_SEGMENT:
    default:
        return m_End;
    }
}


/**
 * Function HitTest
 * tests if the given wxPoint is within the bounds of this object.
 * @param refPos A wxPoint to test
 * @return bool - true if a hit, else false
 */
bool EDGE_MODULE::HitTest( const wxPoint& refPos )
{
    int rayon, dist;

    switch( m_Shape )
    {
    case S_SEGMENT:
        if( TestSegmentHit( refPos, m_Start, m_End, m_Width / 2 ) )
            return true;
        break;

    case S_CIRCLE:
        rayon = GetRadius();
        dist  = (int) hypot( (double) (refPos.x - m_Start.x), (double) (refPos.y - m_Start.y) );
        if( abs( rayon - dist ) <= (m_Width/2) )
            return true;
        break;

    case S_ARC:
        rayon = GetRadius();
        dist  = (int) hypot( (double) (refPos.x - m_Start.x), (double) (refPos.y - m_Start.y) );

        if( abs( rayon - dist ) > (m_Width/2) )
            break;

        int mouseAngle = ArcTangente( refPos.y - m_Start.y, refPos.x - m_Start.x );
        int stAngle    = ArcTangente( m_End.y - m_Start.y, m_End.x - m_Start.x );
        int endAngle   = stAngle + m_Angle;

        if( endAngle > 3600 )
        {
            stAngle  -= 3600;
            endAngle -= 3600;
        }

        if( (mouseAngle >= stAngle) && (mouseAngle <= endAngle) )
            return true;

        break;
    }

    return false;       // an unknown m_Shape also returns false
}


/**
 * Function HitTest (overlayed)
 * tests if the given EDA_RECT intersect this object.
 * For now, for arcs and segments, an ending point must be inside this rect.
 * @param refArea : the given EDA_RECT
 * @return bool - true if a hit, else false
 */
bool EDGE_MODULE::HitTest( EDA_RECT& refArea )
{
    switch(m_Shape)
    {
        case S_CIRCLE:
        {
            int radius = GetRadius();
            // Test if area intersects the circle:
            EDA_RECT area = refArea;
            area.Inflate(radius);
            if( area.Contains(m_Start) )
                return true;
        }
            break;

        case S_ARC:
        case S_SEGMENT:
            if( refArea.Contains( GetStart() ) )
                return true;
            if( refArea.Contains( GetEnd() ) )
                return true;
            break;
    }
    return false;
}


wxString EDGE_MODULE::GetSelectMenuText() const
{
    wxString text;
+3 −92
Original line number Diff line number Diff line
@@ -2,32 +2,21 @@
/* class_edge_module.h : EDGE_MODULE class definition. */
/*******************************************************/

#ifndef CLASS_DRAWSEGMENT_H
#ifndef _CLASS_EDGE_MOD_H_
#define _CLASS_EDGE_MOD_H_

#include "class_drawsegment.h"
#include "richio.h"

class Pcb3D_GLCanvas;


class EDGE_MODULE : public BOARD_ITEM
class EDGE_MODULE : public DRAWSEGMENT
{
public:
    int     m_Width;        // 0 = line, > 0 = tracks, bus ...
    wxPoint m_Start;        // Line start point and circle and arc center
    wxPoint m_End;          // Line end point and circle and arc starting point

    int     m_Shape;        // enum Track_Shapes
    wxPoint m_Start0;       // Start point or centre, relative to module origin, orient 0.
    wxPoint m_End0;         // End point, relative to module origin, orient 0.

    int     m_Angle;        // Arcs: angle in 0.1 degrees

    std::vector<wxPoint> m_PolyPoints;   /* For polygons: number of points (> 2)
                                          *  Coord are relative to Origin, orient 0
                                          *  m_Start0 and m_End0 are not used for polygons
                                          */

public:
    EDGE_MODULE( MODULE* parent );
    EDGE_MODULE( EDGE_MODULE* edge );
@@ -36,40 +25,6 @@ public:
    EDGE_MODULE* Next() const { return (EDGE_MODULE*) Pnext; }
    EDGE_MODULE* Back() const { return (EDGE_MODULE*) Pback; }


    /**
     * Function GetPosition
     * returns the position of this object.
     * @return const wxPoint& - The position of this object.
     */
    wxPoint& GetPosition()
    {
        return m_Start;
    }

    /**
     * Function GetStart
     * returns the starting point of the graphic
     */
    wxPoint      GetStart() const;

    /**
     * Function GetEnd
     * returns the ending point of the graphic
     */
    wxPoint      GetEnd() const;

    /**
     * Function GetRadius
     * returns the radius of this item
     * Has meaning only for arc and circle
     */
    int         GetRadius() const
    {
        double radius = hypot( (double) (m_End.x - m_Start.x), (double) (m_End.y - m_Start.y) );
        return wxRound( radius );
    }

    void             Copy( EDGE_MODULE* source ); // copy structure

    /**
@@ -100,32 +55,6 @@ public:
    void             DisplayInfo( EDA_DRAW_FRAME* frame );


    /**
     * Function GetBoundingBox
     * returns the orthogonal, bounding box of this object for display purposes.
     * This box should be an enclosing perimeter for visible components of this
     * object, and the units should be in the pcb or schematic coordinate system.
     * It is OK to overestimate the size by a few counts.
     */
    virtual EDA_RECT GetBoundingBox() const;

    /**
     * Function HitTest
     * tests if the given wxPoint is within the bounds of this object.
     * @param refPos A wxPoint to test
     * @return bool - true if a hit, else false
     */
    bool             HitTest( const wxPoint& refPos );

    /**
     * Function HitTest (overlayed)
     * tests if the given EDA_RECT intersect this object.
     * For now, for segments and arcs, an ending point must be inside this rect.
     * @param refArea the given EDA_RECT to test
     * @return bool - true if a hit, else false
     */
    bool         HitTest( EDA_RECT& refArea );

    /**
     * Function GetClass
     * returns the class name.
@@ -138,24 +67,6 @@ public:
        // return wxT( "EDGE" );  ?
    }


    /**
     * Function TransformShapeWithClearanceToPolygon
     * Convert the track shape to a closed polygon
     * Used in filling zones calculations
     * Circles and arcs are approximated by segments
     * @param aCornerBuffer = a buffer to store the polygon
     * @param aClearanceValue = the clearance around the pad
     * @param aCircleToSegmentsCount = the number of segments to approximate a circle
     * @param aCorrectionFactor = the correction to apply to circles radius to keep
     * clearance when the circle is approximated by segment bigger or equal
     * to the real clearance value (usually near from 1.0)
     */
    void TransformShapeWithClearanceToPolygon( std::vector <CPolyPt>& aCornerBuffer,
                                               int                    aClearanceValue,
                                               int                    aCircleToSegmentsCount,
                                               double                 aCorrectionFactor );

    virtual wxString GetSelectMenuText() const;

    virtual const char** GetMenuImage() const { return (const char**) show_mod_edge_xpm; }
Loading