예제 #1
0
void POINT_EDITOR::updateItem() const
{
    EDA_ITEM* item = m_editPoints->GetParent();

    switch( item->Type() )
    {
    case PCB_LINE_T:
    case PCB_MODULE_EDGE_T:
    {
        DRAWSEGMENT* segment = static_cast<DRAWSEGMENT*>( item );
        switch( segment->GetShape() )
        {
        case S_SEGMENT:
            if( isModified( m_editPoints->Point( SEG_START ) ) )
                segment->SetStart( wxPoint( m_editPoints->Point( SEG_START ).GetPosition().x,
                                            m_editPoints->Point( SEG_START ).GetPosition().y ) );

            else if( isModified( m_editPoints->Point( SEG_END ) ) )
                segment->SetEnd( wxPoint( m_editPoints->Point( SEG_END ).GetPosition().x,
                                          m_editPoints->Point( SEG_END ).GetPosition().y ) );

            break;

        case S_ARC:
        {
            const VECTOR2I& center = m_editPoints->Point( ARC_CENTER ).GetPosition();
            const VECTOR2I& start = m_editPoints->Point( ARC_START ).GetPosition();
            const VECTOR2I& end = m_editPoints->Point( ARC_END ).GetPosition();

            if( center != segment->GetCenter() )
            {
                wxPoint moveVector = wxPoint( center.x, center.y ) - segment->GetCenter();
                segment->Move( moveVector );

                m_editPoints->Point( ARC_START ).SetPosition( segment->GetArcStart() );
                m_editPoints->Point( ARC_END ).SetPosition( segment->GetArcEnd() );
            }

            else
            {
                segment->SetArcStart( wxPoint( start.x, start.y ) );

                VECTOR2D startLine = start - center;
                VECTOR2I endLine = end - center;
                double newAngle = RAD2DECIDEG( endLine.Angle() - startLine.Angle() );

                // Adjust the new angle to (counter)clockwise setting
                bool clockwise = ( segment->GetAngle() > 0 );

                if( clockwise && newAngle < 0.0 )
                    newAngle += 3600.0;
                else if( !clockwise && newAngle > 0.0 )
                    newAngle -= 3600.0;

                segment->SetAngle( newAngle );
            }

            break;
        }

        case S_CIRCLE:
        {
            const VECTOR2I& center = m_editPoints->Point( CIRC_CENTER ).GetPosition();
            const VECTOR2I& end = m_editPoints->Point( CIRC_END ).GetPosition();

            if( isModified( m_editPoints->Point( CIRC_CENTER ) ) )
            {
                wxPoint moveVector = wxPoint( center.x, center.y ) - segment->GetCenter();
                segment->Move( moveVector );
            }
            else
            {
                segment->SetEnd( wxPoint( end.x, end.y ) );
            }

            break;
        }

        default:        // suppress warnings
            break;
        }

        // Update relative coordinates for module edges
        if( EDGE_MODULE* edge = dyn_cast<EDGE_MODULE*>( item ) )
            edge->SetLocalCoord();

        break;
    }

    case PCB_ZONE_AREA_T:
    {
        ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
        zone->ClearFilledPolysList();
        CPolyLine* outline = zone->Outline();

        for( int i = 0; i < outline->GetCornersCount(); ++i )
        {
            VECTOR2I point = m_editPoints->Point( i ).GetPosition();
            outline->SetX( i, point.x );
            outline->SetY( i, point.y );
        }

        break;
    }

    case PCB_DIMENSION_T:
    {
        DIMENSION* dimension = static_cast<DIMENSION*>( item );

        // Check which point is currently modified and updated dimension's points respectively
        if( isModified( m_editPoints->Point( DIM_CROSSBARO ) ) )
        {
            VECTOR2D featureLine( m_editedPoint->GetPosition() - dimension->GetOrigin() );
            VECTOR2D crossBar( dimension->GetEnd() - dimension->GetOrigin() );

            if( featureLine.Cross( crossBar ) > 0 )
                dimension->SetHeight( -featureLine.EuclideanNorm() );
            else
                dimension->SetHeight( featureLine.EuclideanNorm() );
        }

        else if( isModified( m_editPoints->Point( DIM_CROSSBARF ) ) )
        {
            VECTOR2D featureLine( m_editedPoint->GetPosition() - dimension->GetEnd() );
            VECTOR2D crossBar( dimension->GetEnd() - dimension->GetOrigin() );

            if( featureLine.Cross( crossBar ) > 0 )
                dimension->SetHeight( -featureLine.EuclideanNorm() );
            else
                dimension->SetHeight( featureLine.EuclideanNorm() );
        }

        else if( isModified( m_editPoints->Point( DIM_FEATUREGO ) ) )
        {
            dimension->SetOrigin( wxPoint( m_editedPoint->GetPosition().x, m_editedPoint->GetPosition().y ) );
            m_editPoints->Point( DIM_CROSSBARO ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARO ),
                                                                             m_editPoints->Point( DIM_FEATUREGO ) ) );
            m_editPoints->Point( DIM_CROSSBARF ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARF ),
                                                                             m_editPoints->Point( DIM_FEATUREDO ) ) );
        }

        else if( isModified( m_editPoints->Point( DIM_FEATUREDO ) ) )
        {
            dimension->SetEnd( wxPoint( m_editedPoint->GetPosition().x, m_editedPoint->GetPosition().y ) );
            m_editPoints->Point( DIM_CROSSBARO ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARO ),
                                                                             m_editPoints->Point( DIM_FEATUREGO ) ) );
            m_editPoints->Point( DIM_CROSSBARF ).SetConstraint( new EC_LINE( m_editPoints->Point( DIM_CROSSBARF ),
                                                                             m_editPoints->Point( DIM_FEATUREDO ) ) );
        }

        break;
    }

    default:
        break;
    }
}
/**
 * Function ConvertOutlineToPolygon
 * build a polygon (with holes) from a DRAWSEGMENT list, which is expected to be
 * a outline, therefore a closed main outline with perhaps closed inner outlines.
 * These closed inner outlines are considered as holes in the main outline
 * @param aSegList the initial list of drawsegments (only lines, circles and arcs).
 * @param aPolygons will contain the complex polygon.
 * @param aTolerance is the max distance between points that is still accepted as connected (internal units)
 * @param aErrorText is a wxString to return error message.
 * @param aErrorLocation is the optional position of the error in the outline
 */
bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SET& aPolygons,
                              wxString* aErrorText, unsigned int aTolerance, wxPoint* aErrorLocation )
{
    if( aSegList.size() == 0 )
        return true;

    wxString msg;

    // Make a working copy of aSegList, because the list is modified during calculations
    std::vector< DRAWSEGMENT* > segList = aSegList;

    DRAWSEGMENT* graphic;
    wxPoint prevPt;

    // Find edge point with minimum x, this should be in the outer polygon
    // which will define the perimeter Edge.Cuts polygon.
    wxPoint xmin    = wxPoint( INT_MAX, 0 );
    int     xmini   = 0;

    for( size_t i = 0; i < segList.size(); i++ )
    {
        graphic = (DRAWSEGMENT*) segList[i];

        switch( graphic->GetShape() )
        {
        case S_SEGMENT:
            {
                if( graphic->GetStart().x < xmin.x )
                {
                    xmin    = graphic->GetStart();
                    xmini   = i;
                }

                if( graphic->GetEnd().x < xmin.x )
                {
                    xmin    = graphic->GetEnd();
                    xmini   = i;
                }
            }
            break;

        case S_ARC:
            // Freerouter does not yet understand arcs, so approximate
            // an arc with a series of short lines and put those
            // line segments into the !same! PATH.
            {
                wxPoint  pstart = graphic->GetArcStart();
                wxPoint  center = graphic->GetCenter();
                double   angle  = -graphic->GetAngle();
                double   radius = graphic->GetRadius();
                int      steps  = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );
                wxPoint  pt;

                for( int step = 1; step<=steps; ++step )
                {
                    double rotation = ( angle * step ) / steps;

                    pt = pstart;

                    RotatePoint( &pt, center, rotation );

                    if( pt.x < xmin.x )
                    {
                        xmin  = pt;
                        xmini = i;
                    }
                }
            }
            break;

        case S_CIRCLE:
            {
                wxPoint pt = graphic->GetCenter();

                // pt has minimum x point
                pt.x -= graphic->GetRadius();

                // when the radius <= 0, this is a mal-formed circle. Skip it
                if( graphic->GetRadius() > 0 && pt.x < xmin.x )
                {
                    xmin  = pt;
                    xmini = i;
                }
            }
            break;

        case S_CURVE:
            {
                graphic->RebuildBezierToSegmentsPointsList( graphic->GetWidth() );

                for( unsigned int jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
                {
                    wxPoint pt = graphic->GetBezierPoints()[jj];

                    if( pt.x < xmin.x )
                    {
                        xmin  = pt;
                        xmini = i;
                    }
                }
            }
            break;

        case S_POLYGON:
            {
                const auto poly = graphic->GetPolyShape();
                MODULE* module = aSegList[0]->GetParentModule();
                double orientation = module ? module->GetOrientation() : 0.0;
                VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );

                for( auto iter = poly.CIterate(); iter; iter++ )
                {
                    auto pt = *iter;
                    RotatePoint( pt, orientation );
                    pt += offset;

                    if( pt.x < xmin.x )
                    {
                        xmin.x = pt.x;
                        xmin.y = pt.y;
                        xmini = i;
                    }
                }
            }
            break;
        default:
            break;
        }
    }

    // Grab the left most point, assume its on the board's perimeter, and see if we
    // can put enough graphics together by matching endpoints to formulate a cohesive
    // polygon.

    graphic = (DRAWSEGMENT*) segList[xmini];

    // The first DRAWSEGMENT is in 'graphic', ok to remove it from 'items'
    segList.erase( segList.begin() + xmini );

    // Output the Edge.Cuts perimeter as circle or polygon.
    if( graphic->GetShape() == S_CIRCLE )
    {
        int steps = GetArcToSegmentCount( graphic->GetRadius(), ARC_LOW_DEF, 360.0 );
        TransformCircleToPolygon( aPolygons, graphic->GetCenter(), graphic->GetRadius(), steps );
    }
    else if( graphic->GetShape() == S_POLYGON )
    {
        MODULE* module = graphic->GetParentModule();     // NULL for items not in footprints
        double orientation = module ? module->GetOrientation() : 0.0;
        VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );

        aPolygons.NewOutline();

        for( auto it = graphic->GetPolyShape().CIterate( 0 ); it; it++ )
        {
            auto pt = *it;
            RotatePoint( pt, orientation );
            pt += offset;
            aPolygons.Append( pt );
        }
    }
    else
    {
        // Polygon start point. Arbitrarily chosen end of the
        // segment and build the poly from here.

        wxPoint startPt = wxPoint( graphic->GetEnd() );
        prevPt = graphic->GetEnd();
        aPolygons.NewOutline();
        aPolygons.Append( prevPt );

        // Do not append the other end point yet of this 'graphic', this first
        // 'graphic' might be an arc or a curve.

        for(;;)
        {
            switch( graphic->GetShape() )
            {
            case S_SEGMENT:
                {
                    wxPoint  nextPt;

                    // Use the line segment end point furthest away from
                    // prevPt as we assume the other end to be ON prevPt or
                    // very close to it.

                    if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
                        nextPt = graphic->GetEnd();
                    else
                        nextPt = graphic->GetStart();

                    aPolygons.Append( nextPt );
                    prevPt = nextPt;
                }
                break;

            case S_ARC:
                // We do not support arcs in polygons, so approximate
                // an arc with a series of short lines and put those
                // line segments into the !same! PATH.
                {
                    wxPoint pstart  = graphic->GetArcStart();
                    wxPoint pend    = graphic->GetArcEnd();
                    wxPoint pcenter = graphic->GetCenter();
                    double  angle   = -graphic->GetAngle();
                    double  radius  = graphic->GetRadius();
                    int     steps   = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );

                    if( !close_enough( prevPt, pstart, aTolerance ) )
                    {
                        wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aTolerance ) );

                        angle = -angle;
                        std::swap( pstart, pend );
                    }

                    wxPoint nextPt;

                    for( int step = 1; step<=steps; ++step )
                    {
                        double rotation = ( angle * step ) / steps;
                        nextPt = pstart;
                        RotatePoint( &nextPt, pcenter, rotation );

                        aPolygons.Append( nextPt );
                    }

                    prevPt = nextPt;
                }
                break;

            case S_CURVE:
                // We do not support Bezier curves in polygons, so approximate
                // with a series of short lines and put those
                // line segments into the !same! PATH.
                {
                    wxPoint  nextPt;
                    bool reverse = false;

                    // Use the end point furthest away from
                    // prevPt as we assume the other end to be ON prevPt or
                    // very close to it.

                    if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
                        nextPt = graphic->GetEnd();
                    else
                    {
                        nextPt = graphic->GetStart();
                        reverse = true;
                    }

                    if( reverse )
                    {
                        for( int jj = graphic->GetBezierPoints().size()-1; jj >= 0; jj-- )
                            aPolygons.Append( graphic->GetBezierPoints()[jj] );
                    }
                    else
                    {
                        for( size_t jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
                            aPolygons.Append( graphic->GetBezierPoints()[jj] );
                    }

                    prevPt = nextPt;
                }
                break;

            default:
                if( aErrorText )
                {
                    msg.Printf( "Unsupported DRAWSEGMENT type %s.",
                                BOARD_ITEM::ShowShape( graphic->GetShape() ) );

                    *aErrorText << msg << "\n";
                }

                if( aErrorLocation )
                    *aErrorLocation = graphic->GetPosition();

                return false;
            }

            // Get next closest segment.

            graphic = findPoint( prevPt, segList, aTolerance );

            // If there are no more close segments, check if the board
            // outline polygon can be closed.

            if( !graphic )
            {
                if( close_enough( startPt, prevPt, aTolerance ) )
                {
                    // Close the polygon back to start point
                    // aPolygons.Append( startPt ); // not needed
                }
                else
                {
                    if( aErrorText )
                    {
                        msg.Printf( _( "Unable to find segment with an endpoint of (%s, %s)." ),
                                    StringFromValue( MILLIMETRES, prevPt.x, true ),
                                    StringFromValue( MILLIMETRES, prevPt.y, true ) );

                        *aErrorText << msg << "\n";
                    }

                    if( aErrorLocation )
                        *aErrorLocation = prevPt;

                    return false;
                }
                break;
            }
        }
    }

    while( segList.size() )
    {
        // emit a signal layers keepout for every interior polygon left...
        int hole = aPolygons.NewHole();

        graphic = (DRAWSEGMENT*) segList[0];
        segList.erase( segList.begin() );

        // Both circles and polygons on the edge cuts layer are closed items that
        // do not connect to other elements, so we process them independently
        if( graphic->GetShape() == S_POLYGON )
        {
            MODULE* module = graphic->GetParentModule();     // NULL for items not in footprints
            double orientation = module ? module->GetOrientation() : 0.0;
            VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );

            for( auto it = graphic->GetPolyShape().CIterate(); it; it++ )
            {
                auto val = *it;
                RotatePoint( val, orientation );
                val += offset;

                aPolygons.Append( val, -1, hole );
            }
        }
        else if( graphic->GetShape() == S_CIRCLE )
        {
            // make a circle by segments;
            wxPoint  center  = graphic->GetCenter();
            double   angle   = 3600.0;
            wxPoint  start   = center;
            int      radius  = graphic->GetRadius();
            int      steps   = GetArcToSegmentCount( radius, ARC_LOW_DEF, 360.0 );
            wxPoint  nextPt;

            start.x += radius;

            for( int step = 0; step < steps; ++step )
            {
                double rotation = ( angle * step ) / steps;
                nextPt = start;
                RotatePoint( &nextPt.x, &nextPt.y, center.x, center.y, rotation );
                aPolygons.Append( nextPt, -1, hole );
            }
        }
        else
        {
            // Polygon start point. Arbitrarily chosen end of the
            // segment and build the poly from here.

            wxPoint startPt( graphic->GetEnd() );
            prevPt = graphic->GetEnd();
            aPolygons.Append( prevPt, -1, hole );

            // do not append the other end point yet, this first 'graphic' might be an arc
            for(;;)
            {
                switch( graphic->GetShape() )
                {
                case S_SEGMENT:
                    {
                        wxPoint nextPt;

                        // Use the line segment end point furthest away from
                        // prevPt as we assume the other end to be ON prevPt or
                        // very close to it.

                        if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
                        {
                            nextPt = graphic->GetEnd();
                        }
                        else
                        {
                            nextPt = graphic->GetStart();
                        }

                        prevPt = nextPt;
                        aPolygons.Append( prevPt, -1, hole );
                    }
                    break;

                case S_ARC:
                    // Freerouter does not yet understand arcs, so approximate
                    // an arc with a series of short lines and put those
                    // line segments into the !same! PATH.
                    {
                        wxPoint pstart  = graphic->GetArcStart();
                        wxPoint pend    = graphic->GetArcEnd();
                        wxPoint pcenter = graphic->GetCenter();
                        double  angle   = -graphic->GetAngle();
                        int     radius  = graphic->GetRadius();
                        int     steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );

                        if( !close_enough( prevPt, pstart, aTolerance ) )
                        {
                            wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aTolerance ) );

                            angle = -angle;
                            std::swap( pstart, pend );
                        }

                        wxPoint nextPt;

                        for( int step = 1; step <= steps; ++step )
                        {
                            double rotation = ( angle * step ) / steps;

                            nextPt = pstart;
                            RotatePoint( &nextPt, pcenter, rotation );

                            aPolygons.Append( nextPt, -1, hole );
                        }

                        prevPt = nextPt;
                    }
                    break;

                case S_CURVE:
                    // We do not support Bezier curves in polygons, so approximate
                    // with a series of short lines and put those
                    // line segments into the !same! PATH.
                    {
                        wxPoint  nextPt;
                        bool reverse = false;

                        // Use the end point furthest away from
                        // prevPt as we assume the other end to be ON prevPt or
                        // very close to it.

                        if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
                            nextPt = graphic->GetEnd();
                        else
                        {
                            nextPt = graphic->GetStart();
                            reverse = true;
                        }

                        if( reverse )
                        {
                            for( int jj = graphic->GetBezierPoints().size()-1; jj >= 0; jj-- )
                                aPolygons.Append( graphic->GetBezierPoints()[jj], -1, hole );
                        }
                        else
                        {
                            for( size_t jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
                                aPolygons.Append( graphic->GetBezierPoints()[jj], -1, hole );
                        }

                        prevPt = nextPt;
                    }
                    break;

                default:
                    if( aErrorText )
                    {
                        msg.Printf( "Unsupported DRAWSEGMENT type %s.",
                                    BOARD_ITEM::ShowShape( graphic->GetShape() ) );

                        *aErrorText << msg << "\n";
                    }

                    if( aErrorLocation )
                        *aErrorLocation = graphic->GetPosition();

                    return false;
                }

                // Get next closest segment.

                graphic = findPoint( prevPt, segList, aTolerance );

                // If there are no more close segments, check if polygon
                // can be closed.

                if( !graphic )
                {
                    if( close_enough( startPt, prevPt, aTolerance ) )
                    {
                        // Close the polygon back to start point
                        // aPolygons.Append( startPt, -1, hole );   // not needed
                    }
                    else
                    {
                        if( aErrorText )
                        {
                            msg.Printf( _( "Unable to find segment with an endpoint of (%s, %s)." ),
                                        StringFromValue( MILLIMETRES, prevPt.x, true ),
                                        StringFromValue( MILLIMETRES, prevPt.y, true ) );

                            *aErrorText << msg << "\n";
                        }

                        if( aErrorLocation )
                            *aErrorLocation = prevPt;

                        return false;
                    }
                    break;
                }
            }
        }
    }

    return true;
}
void GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos )
{
    VECTOR2I origin;

    switch( aItem->Type() )
    {
        case PCB_MODULE_T:
        {
            MODULE* mod = static_cast<MODULE*>( aItem );
            addAnchor( mod->GetPosition(), ORIGIN | SNAPPABLE, mod );

            for( D_PAD* pad = mod->Pads(); pad; pad = pad->Next() )
                addAnchor( pad->GetPosition(), CORNER | SNAPPABLE, pad );

            break;
        }


        case PCB_PAD_T:
        {
            D_PAD* pad = static_cast<D_PAD*>( aItem );
            addAnchor( pad->GetPosition(), CORNER | SNAPPABLE, pad );

            break;
        }

        case PCB_MODULE_EDGE_T:
        case PCB_LINE_T:
        {
            DRAWSEGMENT* dseg = static_cast<DRAWSEGMENT*>( aItem );
            VECTOR2I start = dseg->GetStart();
            VECTOR2I end = dseg->GetEnd();
            //LAYER_ID layer = dseg->GetLayer();

            switch( dseg->GetShape() )
            {
                case S_CIRCLE:
                {
                    int r = ( start - end ).EuclideanNorm();

                    addAnchor( start, ORIGIN | SNAPPABLE, dseg );
                    addAnchor( start + VECTOR2I( -r, 0 ), OUTLINE | SNAPPABLE, dseg );
                    addAnchor( start + VECTOR2I( r, 0 ), OUTLINE | SNAPPABLE, dseg );
                    addAnchor( start + VECTOR2I( 0, -r ), OUTLINE | SNAPPABLE, dseg );
                    addAnchor( start + VECTOR2I( 0, r ), OUTLINE | SNAPPABLE, dseg );
                    break;
                }

                case S_ARC:
                {
                    origin = dseg->GetCenter();
                    addAnchor( dseg->GetArcStart(), CORNER | SNAPPABLE, dseg );
                    addAnchor( dseg->GetArcEnd(), CORNER | SNAPPABLE, dseg );
                    addAnchor( origin, ORIGIN | SNAPPABLE, dseg );
                    break;
                }

                case S_SEGMENT:
                {
                    origin.x = start.x + ( start.x - end.x ) / 2;
                    origin.y = start.y + ( start.y - end.y ) / 2;
                    addAnchor( start, CORNER | SNAPPABLE, dseg );
                    addAnchor( end, CORNER | SNAPPABLE, dseg );
                    addAnchor( origin, ORIGIN, dseg );
                    break;
                }

                default:
                {
                    origin = dseg->GetStart();
                    addAnchor( origin, ORIGIN | SNAPPABLE, dseg );
                    break;
                }
            }
            break;
        }

        case PCB_TRACE_T:
        {
            TRACK* track = static_cast<TRACK*>( aItem );
            VECTOR2I start = track->GetStart();
            VECTOR2I end = track->GetEnd();
            origin.x = start.x + ( start.x - end.x ) / 2;
            origin.y = start.y + ( start.y - end.y ) / 2;
            addAnchor( start, CORNER | SNAPPABLE, track );
            addAnchor( end, CORNER | SNAPPABLE, track );
            addAnchor( origin, ORIGIN, track);
            break;
        }

        case PCB_VIA_T:
            addAnchor( aItem->GetPosition(), CORNER | SNAPPABLE, aItem );
            break;

        case PCB_ZONE_AREA_T:
        {
            const CPolyLine* outline = static_cast<const ZONE_CONTAINER*>( aItem )->Outline();
            int cornersCount = outline->GetCornersCount();

            SHAPE_LINE_CHAIN lc;
            lc.SetClosed( true );

            for( int i = 0; i < cornersCount; ++i )
            {
                const VECTOR2I p ( outline->GetPos( i ) );
                addAnchor( p, CORNER, aItem );
                lc.Append( p );
            }

            addAnchor( lc.NearestPoint( aRefPos ), OUTLINE, aItem );

            break;
        }

        case PCB_MODULE_TEXT_T:
        case PCB_TEXT_T:
            addAnchor( aItem->GetPosition(), ORIGIN, aItem );
        default:

        break;
   }
}
/**
 * Searches for a DRAWSEGMENT matching a given end point or start point in a list, and
 * if found, removes it from the TYPE_COLLECTOR and returns it, else returns NULL.
 * @param aPoint The starting or ending point to search for.
 * @param aList The list to remove from.
 * @param aLimit is the distance from \a aPoint that still constitutes a valid find.
 * @return DRAWSEGMENT* - The first DRAWSEGMENT that has a start or end point matching
 *   aPoint, otherwise NULL if none.
 */
static DRAWSEGMENT* findPoint( const wxPoint& aPoint, std::vector< DRAWSEGMENT* >& aList, unsigned aLimit )
{
    unsigned min_d = INT_MAX;
    int      ndx_min = 0;

    // find the point closest to aPoint and perhaps exactly matching aPoint.
    for( size_t i = 0; i < aList.size(); ++i )
    {
        DRAWSEGMENT*    graphic = aList[i];
        unsigned        d;

        switch( graphic->GetShape() )
        {
        case S_ARC:
            if( aPoint == graphic->GetArcStart() || aPoint == graphic->GetArcEnd() )
            {
                aList.erase( aList.begin() + i );
                return graphic;
            }

            d = close_ness( aPoint, graphic->GetArcStart() );
            if( d < min_d )
            {
                min_d = d;
                ndx_min = i;
            }

            d = close_ness( aPoint, graphic->GetArcEnd() );
            if( d < min_d )
            {
                min_d = d;
                ndx_min = i;
            }
            break;

        default:
            if( aPoint == graphic->GetStart() || aPoint == graphic->GetEnd() )
            {
                aList.erase( aList.begin() + i );
                return graphic;
            }

            d = close_ness( aPoint, graphic->GetStart() );
            if( d < min_d )
            {
                min_d = d;
                ndx_min = i;
            }

            d = close_ness( aPoint, graphic->GetEnd() );
            if( d < min_d )
            {
                min_d = d;
                ndx_min = i;
            }
        }
    }

    if( min_d <= aLimit )
    {
        DRAWSEGMENT* graphic = aList[ndx_min];
        aList.erase( aList.begin() + ndx_min );
        return graphic;
    }

    return NULL;
}