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

    if( item->Type() == PCB_ZONE_AREA_T )
    {
        const SELECTION& selection = m_selectionTool->GetSelection();
        PCB_BASE_FRAME* frame = getEditFrame<PCB_BASE_FRAME>();

        ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
        CPolyLine* outline = zone->Outline();

        for( int i = 0; i < outline->GetCornersCount(); ++i )
        {
            if( VECTOR2I( outline->GetPos( i ) ) == aPoint->GetPosition() )
            {
                frame->OnModify();
                frame->SaveCopyInUndoList( selection.items, UR_CHANGED );
                outline->DeleteCorner( i );
                setEditedPoint( NULL );
                break;
            }
        }
    }
}
예제 #2
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;
    }
}
예제 #3
0
void POINT_EDITOR::addCorner( const VECTOR2I& aBreakPoint )
{
    EDA_ITEM* item = m_editPoints->GetParent();
    const SELECTION& selection = m_selectionTool->GetSelection();

    if( item->Type() == PCB_ZONE_AREA_T )
    {
        getEditFrame<PCB_BASE_FRAME>()->OnModify();
        getEditFrame<PCB_BASE_FRAME>()->SaveCopyInUndoList( selection.items, UR_CHANGED );

        ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
        CPolyLine* outline = zone->Outline();

        // Handle the last segment, so other segments can be easily handled in a loop
        unsigned int nearestIdx = outline->GetCornersCount() - 1, nextNearestIdx = 0;
        SEG side( VECTOR2I( outline->GetPos( nearestIdx ) ),
                  VECTOR2I( outline->GetPos( nextNearestIdx ) ) );
        unsigned int nearestDist = side.Distance( aBreakPoint );

        for( int i = 0; i < outline->GetCornersCount() - 1; ++i )
        {
            side = SEG( VECTOR2I( outline->GetPos( i ) ), VECTOR2I( outline->GetPos( i + 1 ) ) );

            unsigned int distance = side.Distance( aBreakPoint );
            if( distance < nearestDist )
            {
                nearestDist = distance;
                nearestIdx = i;
                nextNearestIdx = i + 1;
            }
        }

        // Find the point on the closest segment
        VECTOR2I sideOrigin( outline->GetPos( nearestIdx ) );
        VECTOR2I sideEnd( outline->GetPos( nextNearestIdx ) );
        SEG nearestSide( sideOrigin, sideEnd );
        VECTOR2I nearestPoint = nearestSide.NearestPoint( aBreakPoint );

        // Do not add points that have the same coordinates as ones that already belong to polygon
        // instead, add a point in the middle of the side
        if( nearestPoint == sideOrigin || nearestPoint == sideEnd )
            nearestPoint = ( sideOrigin + sideEnd ) / 2;

        outline->InsertCorner( nearestIdx, nearestPoint.x, nearestPoint.y );
    }

    else if( item->Type() == PCB_LINE_T || item->Type() == PCB_MODULE_EDGE_T )
    {
        bool moduleEdge = item->Type() == PCB_MODULE_EDGE_T;
        PCB_BASE_FRAME* frame = getEditFrame<PCB_BASE_FRAME>();

        frame->OnModify();

        if( moduleEdge )
            frame->SaveCopyInUndoList( getModel<BOARD>()->m_Modules, UR_MODEDIT );
        else
            frame->SaveCopyInUndoList( selection.items, UR_CHANGED );

        DRAWSEGMENT* segment = static_cast<DRAWSEGMENT*>( item );

        if( segment->GetShape() == S_SEGMENT )
        {
            SEG seg( segment->GetStart(), segment->GetEnd() );
            VECTOR2I nearestPoint = seg.NearestPoint( aBreakPoint );

            // Move the end of the line to the break point..
            segment->SetEnd( wxPoint( nearestPoint.x, nearestPoint.y ) );

            // and add another one starting from the break point
            DRAWSEGMENT* newSegment;

            if( moduleEdge )
            {
                EDGE_MODULE* edge = static_cast<EDGE_MODULE*>( segment );
                assert( segment->GetParent()->Type() == PCB_MODULE_T );
                newSegment = new EDGE_MODULE( *edge );
                edge->SetLocalCoord();
            }
            else
            {
                newSegment = new DRAWSEGMENT( *segment );
            }

            newSegment->ClearSelected();
            newSegment->SetStart( wxPoint( nearestPoint.x, nearestPoint.y ) );
            newSegment->SetEnd( wxPoint( seg.B.x, seg.B.y ) );

            if( moduleEdge )
            {
                static_cast<EDGE_MODULE*>( newSegment )->SetLocalCoord();
                getModel<BOARD>()->m_Modules->Add( newSegment );
            }
            else
            {
                getModel<BOARD>()->Add( newSegment );
            }

            getView()->Add( newSegment );
        }
    }
}
int BOARD::Test_Drc_Areas_Outlines_To_Areas_Outlines( ZONE_CONTAINER* aArea_To_Examine,
        bool            aCreate_Markers )
{
    int         nerrors = 0;

    // iterate through all areas
    for( int ia = 0; ia < GetAreaCount(); ia++ )
    {
        ZONE_CONTAINER* Area_Ref = GetArea( ia );
        CPolyLine*      refSmoothedPoly = Area_Ref->GetSmoothedPoly();

        if( !Area_Ref->IsOnCopperLayer() )
            continue;

        // When testing only a single area, skip all others
        if( aArea_To_Examine && (aArea_To_Examine != Area_Ref) )
            continue;

        for( int ia2 = 0; ia2 < GetAreaCount(); ia2++ )
        {
            ZONE_CONTAINER* area_to_test = GetArea( ia2 );
            CPolyLine*      testSmoothedPoly = area_to_test->GetSmoothedPoly();

            if( Area_Ref == area_to_test )
                continue;

            // test for same layer
            if( Area_Ref->GetLayer() != area_to_test->GetLayer() )
                continue;

            // Test for same net
            if( Area_Ref->GetNetCode() == area_to_test->GetNetCode() && Area_Ref->GetNetCode() >= 0 )
                continue;

            // test for different priorities
            if( Area_Ref->GetPriority() != area_to_test->GetPriority() )
                continue;

            // test for different types
            if( Area_Ref->GetIsKeepout() != area_to_test->GetIsKeepout() )
                continue;

            // Examine a candidate zone: compare area_to_test to Area_Ref

            // Get clearance used in zone to zone test.  The policy used to
            // obtain that value is now part of the zone object itself by way of
            // ZONE_CONTAINER::GetClearance().
            int zone2zoneClearance = Area_Ref->GetClearance( area_to_test );

            // Keepout areas have no clearance, so set zone2zoneClearance to 1
            // ( zone2zoneClearance = 0  can create problems in test functions)
            if( Area_Ref->GetIsKeepout() )
                zone2zoneClearance = 1;

            // test for some corners of Area_Ref inside area_to_test
            for( int ic = 0; ic < refSmoothedPoly->GetCornersCount(); ic++ )
            {
                int x = refSmoothedPoly->GetX( ic );
                int y = refSmoothedPoly->GetY( ic );

                if( testSmoothedPoly->TestPointInside( x, y ) )
                {
                    // COPPERAREA_COPPERAREA error: copper area ref corner inside copper area
                    if( aCreate_Markers )
                    {
                        wxString msg1   = Area_Ref->GetSelectMenuText();
                        wxString msg2   = area_to_test->GetSelectMenuText();
                        MARKER_PCB*  marker = new MARKER_PCB( COPPERAREA_INSIDE_COPPERAREA,
                                                              wxPoint( x, y ),
                                                              msg1, wxPoint( x, y ),
                                                              msg2, wxPoint( x, y ) );
                        Add( marker );
                    }

                    nerrors++;
                }
            }

            // test for some corners of area_to_test inside Area_Ref
            for( int ic2 = 0; ic2 < testSmoothedPoly->GetCornersCount(); ic2++ )
            {
                int x = testSmoothedPoly->GetX( ic2 );
                int y = testSmoothedPoly->GetY( ic2 );

                if( refSmoothedPoly->TestPointInside( x, y ) )
                {
                    // COPPERAREA_COPPERAREA error: copper area corner inside copper area ref
                    if( aCreate_Markers )
                    {
                        wxString msg1   = area_to_test->GetSelectMenuText();
                        wxString msg2   = Area_Ref->GetSelectMenuText();
                        MARKER_PCB*  marker = new MARKER_PCB( COPPERAREA_INSIDE_COPPERAREA,
                                                              wxPoint( x, y ),
                                                              msg1, wxPoint( x, y ),
                                                              msg2, wxPoint( x, y ) );
                        Add( marker );
                    }

                    nerrors++;
                }
            }

            // now test spacing between areas
            for( int icont = 0; icont < refSmoothedPoly->GetContoursCount(); icont++ )
            {
                int ic_start = refSmoothedPoly->GetContourStart( icont );
                int ic_end   = refSmoothedPoly->GetContourEnd( icont );

                for( int ic = ic_start; ic<=ic_end; ic++ )
                {
                    int ax1 = refSmoothedPoly->GetX( ic );
                    int ay1 = refSmoothedPoly->GetY( ic );
                    int ax2, ay2;

                    if( ic == ic_end )
                    {
                        ax2 = refSmoothedPoly->GetX( ic_start );
                        ay2 = refSmoothedPoly->GetY( ic_start );
                    }
                    else
                    {
                        ax2 = refSmoothedPoly->GetX( ic + 1 );
                        ay2 = refSmoothedPoly->GetY( ic + 1 );
                    }

                    for( int icont2 = 0; icont2 < testSmoothedPoly->GetContoursCount(); icont2++ )
                    {
                        int ic_start2 = testSmoothedPoly->GetContourStart( icont2 );
                        int ic_end2   = testSmoothedPoly->GetContourEnd( icont2 );

                        for( int ic2 = ic_start2; ic2<=ic_end2; ic2++ )
                        {
                            int bx1 = testSmoothedPoly->GetX( ic2 );
                            int by1 = testSmoothedPoly->GetY( ic2 );
                            int bx2, by2;

                            if( ic2 == ic_end2 )
                            {
                                bx2 = testSmoothedPoly->GetX( ic_start2 );
                                by2 = testSmoothedPoly->GetY( ic_start2 );
                            }
                            else
                            {
                                bx2 = testSmoothedPoly->GetX( ic2 + 1 );
                                by2 = testSmoothedPoly->GetY( ic2 + 1 );
                            }

                            int x, y;

                            int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
                                                                 0,
                                                                 ax1, ay1, ax2, ay2,
                                                                 0,
                                                                 zone2zoneClearance,
                                                                 &x, &y );

                            if( d < zone2zoneClearance )
                            {
                                // COPPERAREA_COPPERAREA error : intersect or too close
                                if( aCreate_Markers )
                                {
                                    wxString msg1   = Area_Ref->GetSelectMenuText();
                                    wxString msg2   = area_to_test->GetSelectMenuText();
                                    MARKER_PCB*  marker = new MARKER_PCB( COPPERAREA_CLOSE_TO_COPPERAREA,
                                                                          wxPoint( x, y ),
                                                                          msg1, wxPoint( x, y ),
                                                                          msg2, wxPoint( x, y ) );
                                    Add( marker );
                                }

                                nerrors++;
                            }
                        }
                    }
                }
            }
        }
    }

    return nerrors;
}