void ZONE_CONTAINER::TransformSolidAreasShapesToPolygonSet(
        SHAPE_POLY_SET& aCornerBuffer, int aError ) const
{
    if( GetFilledPolysList().IsEmpty() )
        return;

    // add filled areas polygons
    aCornerBuffer.Append( m_FilledPolysList );
    auto board = GetBoard();
    int maxError = ARC_HIGH_DEF;

    if( board )
        maxError = board->GetDesignSettings().m_MaxError;

    // add filled areas outlines, which are drawn with thick lines
    for( int i = 0; i < m_FilledPolysList.OutlineCount(); i++ )
    {
        const SHAPE_LINE_CHAIN& path = m_FilledPolysList.COutline( i );

        for( int j = 0; j < path.PointCount(); j++ )
        {
            const VECTOR2I& a = path.CPoint( j );
            const VECTOR2I& b = path.CPoint( j + 1 );

            TransformRoundedEndsSegmentToPolygon( aCornerBuffer, wxPoint( a.x, a.y ),
                    wxPoint( b.x, b.y ), maxError, GetMinThickness() );
        }
    }
}
 /* Function TransformSolidAreasShapesToPolygonSet
 * Convert solid areas full shapes to polygon set
 * (the full shape is the polygon area with a thick outline)
 * Used in 3D view
 * Arcs (ends of segments) are approximated by segments
 * aCornerBuffer = a buffer to store the polygons
 * aCircleToSegmentsCount = the number of segments to approximate a circle
 * aCorrectionFactor = the correction to apply to arcs radius to roughly
 * keep arc radius when approximated by segments
 */
void ZONE_CONTAINER::TransformSolidAreasShapesToPolygonSet(
        SHAPE_POLY_SET& aCornerBuffer,
        int                    aCircleToSegmentsCount,
        double                 aCorrectionFactor )
{
    if( GetFilledPolysList().IsEmpty() )
        return;

    // add filled areas polygons
    aCornerBuffer.Append( m_FilledPolysList );

    // add filled areas outlines, which are drawn with thick lines
    for( int i = 0; i < m_FilledPolysList.OutlineCount(); i++ )
    {
        const SHAPE_LINE_CHAIN& path = m_FilledPolysList.COutline( i );

        for( int j = 0; j < path.PointCount(); j++ )
        {
            const VECTOR2I& a = path.CPoint( j );
            const VECTOR2I& b = path.CPoint( j + 1 );

            TransformRoundedEndsSegmentToPolygon( aCornerBuffer, wxPoint( a.x, a.y ), wxPoint( b.x, b.y ),
                                                    aCircleToSegmentsCount,
                                                    GetMinThickness() );
        }
    }
}
void CN_VISITOR::checkZoneZoneConnection( CN_ZONE* aZoneA, CN_ZONE* aZoneB )
{
    const auto refParent = static_cast<const ZONE_CONTAINER*>( aZoneA->Parent() );
    const auto testedParent = static_cast<const ZONE_CONTAINER*>( aZoneB->Parent() );

    if( testedParent->Type () != PCB_ZONE_AREA_T )
        return;

    if( aZoneB == aZoneA  || refParent == testedParent )
        return;

    if( aZoneB->Net() != aZoneA->Net() )
        return; // we only test zones belonging to the same net

    const auto& outline = refParent->GetFilledPolysList().COutline( aZoneA->SubpolyIndex() );

    for( int i = 0; i < outline.PointCount(); i++ )
    {
        if( aZoneB->ContainsPoint( outline.CPoint( i ) ) )
        {
            aZoneA->Connect( aZoneB );
            aZoneB->Connect( aZoneA );
            return;
        }
    }

    const auto& outline2 = testedParent->GetFilledPolysList().COutline( aZoneB->SubpolyIndex() );

    for( int i = 0; i < outline2.PointCount(); i++ )
    {
        if( aZoneA->ContainsPoint( outline2.CPoint( i ) ) )
        {
            aZoneA->Connect( aZoneB );
            aZoneB->Connect( aZoneA );
            return;
        }
    }
}