/* generate shapes of graphic items (outlines) on layer aLayer as polygons,
 * and adds these polygons to aCornerBuffer
 * aCornerBuffer = the buffer to store polygons
 * aInflateValue = a value to inflate shapes
 * aCircleToSegmentsCount = number of segments to approximate a circle
 * aCorrectionFactor = the correction to apply to the circle radius
 *  to generate the polygon.
 *  if aCorrectionFactor = 1.0, the polygon is inside the circle
 *  the radius of circle approximated by segments is
 *  initial radius * aCorrectionFactor
 */
void MODULE::TransformGraphicShapesWithClearanceToPolygonSet(
                        LAYER_NUM aLayer,
                        CPOLYGONS_LIST& aCornerBuffer,
                        int                    aInflateValue,
                        int                    aCircleToSegmentsCount,
                        double                 aCorrectionFactor )
{
    std::vector<TEXTE_MODULE *> texts;  // List of TEXTE_MODULE to convert
    EDGE_MODULE* outline;

    for( EDA_ITEM* item = GraphicalItems(); item != NULL; item = item->Next() )
    {
        switch( item->Type() )
        {
        case PCB_MODULE_TEXT_T:
            if( ((TEXTE_MODULE*)item)->GetLayer() == aLayer )
                texts.push_back( (TEXTE_MODULE *) item );
            break;

        case PCB_MODULE_EDGE_T:
            outline = (EDGE_MODULE*) item;
            if( outline->GetLayer() != aLayer )
                break;

            switch( outline->GetShape() )
            {
            case S_SEGMENT:
                TransformRoundedEndsSegmentToPolygon( aCornerBuffer,
                                           outline->GetStart(),
                                           outline->GetEnd(),
                                           aCircleToSegmentsCount,
                                           outline->GetWidth() );
                break;

            case S_CIRCLE:
                TransformRingToPolygon( aCornerBuffer, outline->GetCenter(),
                                outline->GetRadius(), aCircleToSegmentsCount,
                                outline->GetWidth() );
                break;

            case S_ARC:
                TransformArcToPolygon( aCornerBuffer,
                            outline->GetCenter(), outline->GetArcStart(),
                            outline->GetAngle(),
                            aCircleToSegmentsCount, outline->GetWidth() );
                break;

            case S_POLYGON:
                // for outline shape = S_POLYGON:
                // We must compute true coordinates from m_PolyPoints
                // which are relative to module position and module orientation = 0
                for( unsigned ii = 0; ii < outline->GetPolyPoints().size(); ii++ )
                {
                    CPolyPt corner( outline->GetPolyPoints()[ii] );
                    RotatePoint( &corner.x, &corner.y, GetOrientation() );
                    corner.x += GetPosition().x;
                    corner.y += GetPosition().y;
                    aCornerBuffer.Append( corner );
                }
                aCornerBuffer.CloseLastContour();
                break;

            default:
                DBG( printf( "Error: Shape %d not implemented!\n",
                        outline->GetShape() ); )
                break;
            }
                break;

            default:
                break;
        }
    }
 /* Function TransformOutlinesShapeWithClearanceToPolygon
  * Convert the zone filled areas polygons to polygons
  * inflated (optional) by max( aClearanceValue, the zone clearance)
  * and copy them in aCornerBuffer
  * param aClearanceValue = the clearance around polygons
  * param aAddClearance = true to add a clearance area to the polygon
  *                      false to create the outline polygon.
  */
void ZONE_CONTAINER::TransformOutlinesShapeWithClearanceToPolygon(
            CPOLYGONS_LIST& aCornerBuffer,
            int aClearanceValue, bool aAddClearance )
{
    // Creates the zone outlines polygon (with linked holes if any)
    CPOLYGONS_LIST zoneOutines;
    BuildFilledSolidAreasPolygons( NULL, &zoneOutines );

    // add clearance to outline
    int clearance = 0;
    if( aAddClearance )
    {
        clearance = GetClearance();
        if( aClearanceValue > clearance )
            clearance = aClearanceValue;
    }
    // Calculate the polygon with clearance
    // holes are linked to the main outline, so only one polygon should be created.
    KI_POLYGON_SET polyset_zone_solid_areas;
    std::vector<KI_POLY_POINT> cornerslist;
    unsigned ic = 0;
    unsigned corners_count = zoneOutines.GetCornersCount();
    while( ic < corners_count )
    {
        cornerslist.clear();
        KI_POLYGON poly;
        {
            for( ; ic < corners_count; ic++ )
            {
                CPolyPt* corner = &zoneOutines[ic];
                cornerslist.push_back( KI_POLY_POINT( corner->x, corner->y ) );
                if( corner->end_contour )
                {
                    ic++;
                    break;
                }
            }

            bpl::set_points( poly, cornerslist.begin(), cornerslist.end() );
            polyset_zone_solid_areas.push_back( poly );
        }
    }

    polyset_zone_solid_areas += clearance;

    // Put the resulting polygon in aCornerBuffer corners list
    for( unsigned ii = 0; ii < polyset_zone_solid_areas.size(); ii++ )
    {
        KI_POLYGON& poly = polyset_zone_solid_areas[ii];
        CPolyPt   corner( 0, 0, false );

        for( unsigned jj = 0; jj < poly.size(); jj++ )
        {
            KI_POLY_POINT point = *(poly.begin() + jj);
            corner.x = point.x();
            corner.y = point.y();
            corner.end_contour = false;
            aCornerBuffer.Append( corner );
        }

        aCornerBuffer.CloseLastContour();
    }
}