Commit d3932f5f authored by Marco Mattila's avatar Marco Mattila
Browse files

Pcbnew: Fix add similar/cutout zone. Fix zone corner smoothing for zones with cutouts.

parent 0f09b337
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -65,7 +65,7 @@ void WinEDA_PcbFrame::Add_Similar_Zone( wxDC* DC, ZONE_CONTAINER* zone_container
    // Use the general event handle to set others params (like toolbar) */
    // Use the general event handle to set others params (like toolbar) */
    wxCommandEvent evt;
    wxCommandEvent evt;
    evt.SetId( ID_PCB_ZONES_BUTT );
    evt.SetId( ID_PCB_ZONES_BUTT );
    Process_Special_Functions( evt );
    OnSelectTool( evt );
}
}




@@ -91,7 +91,7 @@ void WinEDA_PcbFrame::Add_Zone_Cutout( wxDC* DC, ZONE_CONTAINER* zone_container
    // Use the general event handle to set others params (like toolbar) */
    // Use the general event handle to set others params (like toolbar) */
    wxCommandEvent evt;
    wxCommandEvent evt;
    evt.SetId( ID_PCB_ZONES_BUTT );
    evt.SetId( ID_PCB_ZONES_BUTT );
    Process_Special_Functions( evt );
    OnSelectTool( evt );
}
}




+153 −222
Original line number Original line Diff line number Diff line
@@ -907,141 +907,159 @@ void CPolyLine::RemoveContour( int icont )
}
}




int CPolyLine::Chamfer( unsigned int aIndex, unsigned int aDistance )
CPolyLine* CPolyLine::Chamfer( unsigned int aDistance )
{
{
    int x1, y1;
    CPolyLine* newPoly = new CPolyLine;
    long xa, ya, xb, yb, nx, ny;


    if( !aDistance )
    if( !aDistance )
        return 0;
    {
        newPoly->Copy( this );
        return newPoly;
    }


    x1 = corner[aIndex].x;
    for( int contour = 0; contour < GetNumContours(); contour++ )
    y1 = corner[aIndex].y;
    {
        unsigned int startIndex = GetContourStart( contour );
        unsigned int endIndex = GetContourEnd( contour );

        for( unsigned int index = startIndex; index <= endIndex; index++ )
        {
            int x1, y1, nx, ny;
            long long xa, ya, xb, yb;


    if( aIndex == 0 )
            x1 = corner[index].x;
            y1 = corner[index].y;

            if( index == startIndex )
            {
            {
        xa = corner[corner.size()-1].x - x1;
                xa = corner[endIndex].x - x1;
        ya = corner[corner.size()-1].y - y1;
                ya = corner[endIndex].y - y1;
            }
            }
            else
            else
            {
            {
        xa = corner[aIndex-1].x - x1;
                xa = corner[index-1].x - x1;
        ya = corner[aIndex-1].y - y1;
                ya = corner[index-1].y - y1;
            }
            }


    if( aIndex == corner.size()-1 )
            if( index == endIndex )
            {
            {
        xb = corner[0].x - x1;
                xb = corner[startIndex].x - x1;
        yb = corner[0].y - y1;
                yb = corner[startIndex].y - y1;
            }
            }
            else
            else
            {
            {
        xb = corner[aIndex+1].x - x1;
                xb = corner[index+1].x - x1;
        yb = corner[aIndex+1].y - y1;
                yb = corner[index+1].y - y1;
            }
            }


    // Move the first vertex into new position
            unsigned int lena = (unsigned int)sqrt( (double)(xa*xa + ya*ya) );
    nx = (long) ( (double) (aDistance*xa)/sqrt( (double) (xa*xa + ya*ya) ) );
            unsigned int lenb = (unsigned int)sqrt( (double)(xb*xb + yb*yb) );
    ny = (long) ( (double) (aDistance*ya)/sqrt( (double) (xa*xa + ya*ya) ) );
            unsigned int distance = aDistance;
    corner[aIndex].x = x1 + nx;
    corner[aIndex].y = y1 + ny;

    // Add one new vertex
    nx = (long) ( (double) (aDistance*xb)/sqrt( (double) (xb*xb + yb*yb) ) );
    ny = (long) ( (double) (aDistance*yb)/sqrt( (double) (xb*xb + yb*yb) ) );
    InsertCorner( aIndex, x1 + nx, y1 + ny );


    return 1; // Added one vertex
            // Chamfer one half of an edge at most
}
            if( 0.5*lena < distance )
                distance = 0.5*lena;


            if( 0.5*lenb < distance )
                distance = 0.5*lenb;


CPolyLine* CPolyLine::Chamfer( unsigned int aDistance )
            nx = (int) ( (double) (distance*xa)/sqrt( (double) (xa*xa + ya*ya) ) );
{
            ny = (int) ( (double) (distance*ya)/sqrt( (double) (xa*xa + ya*ya) ) );
    CPolyLine* newPoly = new CPolyLine;
    unsigned int lena, lenb;
    newPoly->Copy( this );


    for( unsigned int i = 0, index = 0; i < corner.size(); i++, index++ )
            if( index == startIndex )
    {
                newPoly->Start( GetLayer(), x1 + nx, y1 + ny, GetHatchStyle() );
        if( i == 0 )
            lena = GetEdgeLength( corner.size()-1 );
            else
            else
            lena = GetEdgeLength( i - 1 );
                newPoly->AppendCorner( x1 + nx, y1 + ny );
        lenb = GetEdgeLength( i );


        unsigned int distance = aDistance;
            nx = (int) ( (double) (distance*xb)/sqrt( (double) (xb*xb + yb*yb) ) );
            ny = (int) ( (double) (distance*yb)/sqrt( (double) (xb*xb + yb*yb) ) );
            newPoly->AppendCorner( x1 + nx, y1 + ny );
        }
        newPoly->Close();
    }


        // Chamfer one half of an edge at most
    return newPoly;
        if( 0.5*lena < distance )
}
            distance = (unsigned int) 0.5*lena;


        if( 0.5*lenb < distance )
            distance = (unsigned int) 0.5*lenb;


        // Chamfer this corner and keep tract of added vertices
CPolyLine* CPolyLine::Fillet( unsigned int aRadius, unsigned int aSegments )
        index += newPoly->Chamfer( index, distance );
{
    }
    CPolyLine* newPoly = new CPolyLine;


    if( !aRadius )
    {
        newPoly->Copy( this );
        return newPoly;
        return newPoly;
    }
    }


    for( int contour = 0; contour < GetNumContours(); contour++ )
    {
        unsigned int startIndex = GetContourStart( contour );
        unsigned int endIndex = GetContourEnd( contour );


int CPolyLine::Fillet( unsigned int aIndex, unsigned int aRadius,
        for( unsigned int index = startIndex; index <= endIndex; index++ )
                       unsigned int aSegments )
        {
        {

            int x1, y1; // Current vertex
            int x1, y1; // Current vertex
    int xa, ya; // Previous vertex
            long long xa, ya; // Previous vertex
    int xb, yb; // Next vertex
            long long xb, yb; // Next vertex
            double nx, ny;
            double nx, ny;


    if( !aRadius )
            x1 = corner[index].x;
        return 0;
            y1 = corner[index].y;

    x1 = corner[aIndex].x;
    y1 = corner[aIndex].y;


    if( aIndex == 0 )
            if( index == startIndex )
            {
            {
        xa = corner[corner.size()-1].x - x1;
                xa = corner[endIndex].x - x1;
        ya = corner[corner.size()-1].y - y1;
                ya = corner[endIndex].y - y1;
            }
            }
            else
            else
            {
            {
        xa = corner[aIndex-1].x - x1;
                xa = corner[index-1].x - x1;
        ya = corner[aIndex-1].y - y1;
                ya = corner[index-1].y - y1;
            }
            }


    if( aIndex == corner.size()-1 )
            if( index == endIndex )
            {
            {
        xb = corner[0].x - x1;
                xb = corner[startIndex].x - x1;
        yb = corner[0].y - y1;
                yb = corner[startIndex].y - y1;
            }
            }
            else
            else
            {
            {
        xb = corner[aIndex+1].x - x1;
                xb = corner[index+1].x - x1;
        yb = corner[aIndex+1].y - y1;
                yb = corner[index+1].y - y1;
            }
            }


            double lena = sqrt( (double) (xa*xa + ya*ya) );
            double lena = sqrt( (double) (xa*xa + ya*ya) );
            double lenb = sqrt( (double) (xb*xb + yb*yb) );
            double lenb = sqrt( (double) (xb*xb + yb*yb) );
            double cosine = ( xa*xb + ya*yb )/( lena*lenb );
            double cosine = ( xa*xb + ya*yb )/( lena*lenb );


            unsigned int radius = aRadius;
            double denom = sqrt( 2.0/( 1+cosine )-1 );

            // Limit rounding distance to one half of an edge
            if( 0.5*lena*denom < radius )
                radius = 0.5*lena*denom;

            if( 0.5*lenb*denom < radius )
                radius = 0.5*lenb*denom;

            // Calculate fillet arc absolute center point (xc, yx)
            // Calculate fillet arc absolute center point (xc, yx)
    double k = aRadius / sqrt( .5*( 1-cosine ) );
            double k = radius / sqrt( .5*( 1-cosine ) );
            double lenab = sqrt( ( xa/lena + xb/lenb )*( xa/lena + xb/lenb ) +
            double lenab = sqrt( ( xa/lena + xb/lenb )*( xa/lena + xb/lenb ) +
                                 ( ya/lena + yb/lenb )*( ya/lena + yb/lenb ) );
                                 ( ya/lena + yb/lenb )*( ya/lena + yb/lenb ) );
            double xc = x1 + k*( xa/lena + xb/lenb )/lenab;
            double xc = x1 + k*( xa/lena + xb/lenb )/lenab;
            double yc = y1 + k*( ya/lena + yb/lenb )/lenab;
            double yc = y1 + k*( ya/lena + yb/lenb )/lenab;


            // Calculate arc start and end vectors
            // Calculate arc start and end vectors
    k = aRadius / sqrt( 2/( 1+cosine )-1 );
            k = radius / sqrt( 2/( 1+cosine )-1 );
            double xs = x1 + k*xa/lena - xc;
            double xs = x1 + k*xa/lena - xc;
            double ys = y1 + k*ya/lena - yc;
            double ys = y1 + k*ya/lena - yc;
            double xe = x1 + k*xb/lenb - xc;
            double xe = x1 + k*xb/lenb - xc;
            double ye = y1 + k*yb/lenb - yc;
            double ye = y1 + k*yb/lenb - yc;


            // Cosine of arc angle
            // Cosine of arc angle
    double argument = ( xs*xe + ys*ye ) / ( aRadius*aRadius );
            double argument = ( xs*xe + ys*ye ) / ( radius*radius );


            if( argument < -1 ) // Just in case...
            if( argument < -1 ) // Just in case...
                argument = -1;
                argument = -1;
@@ -1055,63 +1073,33 @@ int CPolyLine::Fillet( unsigned int aIndex, unsigned int aRadius,


            if( tempSegments - (int)tempSegments > 0 )
            if( tempSegments - (int)tempSegments > 0 )
                tempSegments++;
                tempSegments++;
    aSegments = (unsigned int) tempSegments;
            unsigned int segments = (unsigned int) tempSegments;


    double deltaAngle = arcAngle / aSegments;
            double deltaAngle = arcAngle / segments;
            double startAngle = atan2( -ys, xs );
            double startAngle = atan2( -ys, xs );


            // Flip arc for inner corners
            // Flip arc for inner corners
            if( xa*yb - ya*xb <= 0 )
            if( xa*yb - ya*xb <= 0 )
                deltaAngle *= -1;
                deltaAngle *= -1;


    // Move first vertex into new position
            nx = xc + xs + 0.5;
            nx = xc + xs + 0.5;
            ny = yc + ys + 0.5;
            ny = yc + ys + 0.5;
    corner[aIndex].x = (int)nx;
            if( index == startIndex )
    corner[aIndex].y = (int)ny;
                newPoly->Start( GetLayer(), (int)nx, (int)ny, GetHatchStyle() );
            else
                newPoly->AppendCorner( (int)nx, (int)ny );


    // Add new vertices
            unsigned int nVertices = 0;
            unsigned int nVertices = 0;
    for( unsigned int j = 0; j < aSegments; j++ )
            for( unsigned int j = 0; j < segments; j++ )
            {
            {
        nx = xc + cos( startAngle + (j+1)*deltaAngle )*aRadius + 0.5;
                nx = xc + cos( startAngle + (j+1)*deltaAngle )*radius + 0.5;
        ny = yc - sin( startAngle + (j+1)*deltaAngle )*aRadius + 0.5;
                ny = yc - sin( startAngle + (j+1)*deltaAngle )*radius + 0.5;
        InsertCorner( aIndex + nVertices, (int)nx, (int)ny );
                newPoly->AppendCorner( (int)nx, (int)ny );
                nVertices++;
                nVertices++;
            }
            }

    return nVertices; // Return the number of added vertices
        }
        }

        newPoly->Close();

CPolyLine* CPolyLine::Fillet( unsigned int aRadius, unsigned int aSegments )
{
    CPolyLine* newPoly = new CPolyLine;
    unsigned int lena, lenb;
    newPoly->Copy( this );

    for( unsigned int i = 0, index = 0; i < corner.size(); i++, index++ )
    {
        if( i == 0 )
            lena = GetEdgeLength( corner.size()-1 );
        else
            lena = GetEdgeLength( i - 1 );
        lenb = GetEdgeLength( i );

        unsigned int radius = aRadius;
        double denom = sqrt( 2.0/( 1+GetCosine( i ) )-1 );

        // Limit rounding distance to one half of an edge
        if( 0.5*lena*denom < radius )
            radius = (unsigned int) ( 0.5 * (double) lena * denom );

        if( 0.5*lenb*denom < radius )
            radius = (unsigned int) ( 0.5 * (double) lenb * denom );

        // Round this corner and keep tract of added vertices
        index += newPoly->Fillet( index, radius, aSegments );
    }
    }

    return newPoly;
    return newPoly;
}
}


@@ -1205,63 +1193,6 @@ int CPolyLine::GetEndContour( int ic )
}
}




unsigned int CPolyLine::GetEdgeLength( unsigned int aIndex )
{
    long xa, ya, xb, yb;
    xa = corner[aIndex].x;
    ya = corner[aIndex].y;

    if( aIndex == corner.size()-1 )
    {
        xb = corner[0].x;
        yb = corner[0].y;
    }
    else
    {
        xb = corner[aIndex+1].x;
        yb = corner[aIndex+1].y;
    }

    return (unsigned int) sqrt( (double) (xb-xa)*(xb-xa) + (yb-ya)*(yb-ya) );
}


double CPolyLine::GetCosine( unsigned int aIndex )
{
    int x1, y1;
    long xa, ya, xb, yb;
    x1 = corner[aIndex].x;
    y1 = corner[aIndex].y;

    if( aIndex == 0 )
    {
        xa = corner[corner.size()-1].x - x1;
        ya = corner[corner.size()-1].y - y1;
    }
    else
    {
        xa = corner[aIndex-1].x - x1;
        ya = corner[aIndex-1].y - y1;
    }

    if( aIndex == corner.size() - 1 )
    {
        xb = corner[0].x - x1;
        yb = corner[0].y - y1;
    }
    else
    {
        xb = corner[aIndex+1].x - x1;
        yb = corner[aIndex+1].y - y1;
    }

    double lena = sqrt( (double)xa*xa + ya*ya );
    double lenb = sqrt( (double)xb*xb + yb*yb );

    return ( xa*xb + ya*yb )/( lena*lenb );
}


CRect CPolyLine::GetBounds()
CRect CPolyLine::GetBounds()
{
{
    CRect r = GetCornerBounds();
    CRect r = GetCornerBounds();
+4 −40
Original line number Original line Diff line number Diff line
@@ -132,15 +132,6 @@ public:
    void       Close( int style = STRAIGHT, bool bDraw = false );
    void       Close( int style = STRAIGHT, bool bDraw = false );
    void       RemoveContour( int icont );
    void       RemoveContour( int icont );


    /**
     * Function Chamfer
     * chamfers a corner.
     * @param aIndex is the corner index.
     * @param aDistance is the chamfering distance.
     * @return int - The number of segments added.
     */
    int        Chamfer( unsigned int aIndex, unsigned int aDistance );

    /**
    /**
     * Function Chamfer
     * Function Chamfer
     * returns a chamfered version of a polygon.
     * returns a chamfered version of a polygon.
@@ -149,17 +140,6 @@ public:
     */
     */
    CPolyLine* Chamfer( unsigned int aDistance );
    CPolyLine* Chamfer( unsigned int aDistance );


    /**
     * Function Fillet
     * rounds a corner.
     * @param aIndex is the corner index.
     * @param aDistance is the fillet radius.
     * @param aSegments is the number of segments / 360 degrees.
     * @return int - The number of segments added.
     */
    int        Fillet( unsigned int aIndex, unsigned int aRadius,
                       unsigned int aSegments );

    /**
    /**
     * Function Fillet
     * Function Fillet
     * returns a filleted version of a polygon.
     * returns a filleted version of a polygon.
@@ -200,22 +180,6 @@ public:
    int        GetY( int ic );
    int        GetY( int ic );
    int        GetEndContour( int ic );
    int        GetEndContour( int ic );


    /**
     * Function GetEdgeLength
     * returns the length of the edge starting at given corner index.
     * @param aIndex is the corner index.
     * @return unsigned int - the length of the edge.
     */
    unsigned int GetEdgeLength( unsigned int aIndex );

    /**
     * Function GetCosine
     * returns the cosine between the two edge vectors at a corner.
     * @param aIndex is the corner index.
     * @return double - the cosine value.
     */
    double     GetCosine( unsigned int aIndex );

    int        GetUtility( int ic ) { return corner[ic].utility; };
    int        GetUtility( int ic ) { return corner[ic].utility; };
    void       SetUtility( int ic, int utility ) { corner[ic].utility = utility; };
    void       SetUtility( int ic, int utility ) { corner[ic].utility = utility; };
    int        GetSideStyle( int is );
    int        GetSideStyle( int is );