コード例 #1
0
/**
 * Function NormalizeAreaOutlines
 * Convert a self-intersecting polygon to one (or more) non self-intersecting polygon(s)
 * @param aNewPolygonList = a std::vector<CPolyLine*> reference where to store new CPolyLine
 * needed by the normalization
 * @return the polygon count (always >= 1, because there is at least one polygon)
 * There are new polygons only if the polygon count  is > 1
 */
int CPolyLine::NormalizeAreaOutlines( std::vector<CPolyLine*>* aNewPolygonList )
{

    SHAPE_POLY_SET polySet = ConvertPolyListToPolySet( m_CornersList );

    // We are expecting only one main outline, but this main outline can have holes
    // if holes: combine holes and remove them from the main outline.
    // Note also we are using SHAPE_POLY_SET::PM_STRICTLY_SIMPLE in polygon
    // calculations, but it is not mandatory. It is used mainly
    // because there is usually only very few vertices in area outlines
    SHAPE_POLY_SET::POLYGON& outline = polySet.Polygon( 0 );
    SHAPE_POLY_SET holesBuffer;

    // Move holes stored in outline to holesBuffer:
    // The first SHAPE_LINE_CHAIN is the main outline, others are holes
    while( outline.size() > 1 )
    {
        holesBuffer.AddOutline( outline.back() );
        outline.pop_back();
    }

    polySet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE);

    // If any hole, substract it to main outline
    if( holesBuffer.OutlineCount() )
    {
        holesBuffer.Simplify( SHAPE_POLY_SET::PM_FAST);
        polySet.BooleanSubtract( holesBuffer, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
    }

    RemoveAllContours();

    // Note: we can have more than outline, because a self intersecting outline will be
    // broken to non intersecting polygons, and removing holes can also create a few polygons
    for( int ii = 0; ii < polySet.OutlineCount(); ii++ )
    {
        CPolyLine* polyline = this;

        if( ii > 0 )
        {
            polyline = new CPolyLine;
            polyline->ImportSettings( this );
            aNewPolygonList->push_back( polyline );
        }

        SHAPE_POLY_SET pnew;
        pnew.NewOutline();
        pnew.Polygon( 0 ) = polySet.CPolygon( ii );

        polyline->m_CornersList = ConvertPolySetToPolyList( pnew );
    }

    return polySet.OutlineCount();
}
コード例 #2
0
bool BOARD::CombineAreas( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_ref,
                          ZONE_CONTAINER* area_to_combine )
{
    if( area_ref == area_to_combine )
    {
        wxASSERT( 0 );
        return false;
    }

    SHAPE_POLY_SET mergedOutlines = ConvertPolyListToPolySet( area_ref->Outline()->m_CornersList );
    SHAPE_POLY_SET areaToMergePoly = ConvertPolyListToPolySet( area_to_combine->Outline()->m_CornersList );

    mergedOutlines.BooleanAdd( areaToMergePoly );
    mergedOutlines.Simplify();

    // We should have one polygon with hole
    // We can have 2 polygons with hole, if the 2 initial polygons have only one common corner
    // and therefore cannot be merged (they are dectected as intersecting)
    // but we should never have more than 2 polys
    if( mergedOutlines.OutlineCount() > 2 )
    {
        wxLogMessage(wxT("BOARD::CombineAreas error: more than 2 polys after merging") );
        return false;
    }

    if( mergedOutlines.OutlineCount() > 1 )
        return false;

    area_ref->Outline()->m_CornersList = ConvertPolySetToPolyList( mergedOutlines );

    RemoveArea( aDeletedList, area_to_combine );

    area_ref->SetLocalFlags( 1 );
    area_ref->Outline()->Hatch();

    return true;
}
void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList_NG( BOARD* aPcb )
{
    int segsPerCircle;
    double correctionFactor;
    int outline_half_thickness = m_ZoneMinThickness / 2;


    std::unique_ptr<SHAPE_FILE_IO> dumper( new SHAPE_FILE_IO(
            g_DumpZonesWhenFilling ? "zones_dump.txt" : "", SHAPE_FILE_IO::IOM_APPEND ) );

    // Set the number of segments in arc approximations
    if( m_ArcToSegmentsCount == ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF  )
        segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF;
    else
        segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF;

    /* calculates the coeff to compensate radius reduction of holes clearance
     * due to the segment approx.
     * For a circle the min radius is radius * cos( 2PI / s_CircleToSegmentsCount / 2)
     * s_Correction is 1 /cos( PI/s_CircleToSegmentsCount  )
     */
    correctionFactor = 1.0 / cos( M_PI / (double) segsPerCircle );

    CPOLYGONS_LIST tmp;

    if(g_DumpZonesWhenFilling)
        dumper->BeginGroup("clipper-zone");

    SHAPE_POLY_SET solidAreas = ConvertPolyListToPolySet( m_smoothedPoly->m_CornersList );

    solidAreas.Inflate( -outline_half_thickness, segsPerCircle );
    solidAreas.Simplify( POLY_CALC_MODE );

    SHAPE_POLY_SET holes;

    if(g_DumpZonesWhenFilling)
        dumper->Write( &solidAreas, "solid-areas" );

    tmp.RemoveAllContours();
    buildFeatureHoleList( aPcb, holes );

    if(g_DumpZonesWhenFilling)
        dumper->Write( &holes, "feature-holes" );

    holes.Simplify( POLY_CALC_MODE );

    if (g_DumpZonesWhenFilling)
        dumper->Write( &holes, "feature-holes-postsimplify" );

    solidAreas.BooleanSubtract( holes, POLY_CALC_MODE );

    if (g_DumpZonesWhenFilling)
        dumper->Write( &solidAreas, "solid-areas-minus-holes" );

    SHAPE_POLY_SET areas_fractured = solidAreas;
    areas_fractured.Fracture( POLY_CALC_MODE );

    if (g_DumpZonesWhenFilling)
        dumper->Write( &areas_fractured, "areas_fractured" );

    m_FilledPolysList = areas_fractured;

    // Remove insulated islands:
    if( GetNetCode() > 0 )
        TestForCopperIslandAndRemoveInsulatedIslands( aPcb );

    SHAPE_POLY_SET thermalHoles;

    // Test thermal stubs connections and add polygons to remove unconnected stubs.
    // (this is a refinement for thermal relief shapes)
    if( GetNetCode() > 0 )
        BuildUnconnectedThermalStubsPolygonList( thermalHoles, aPcb, this,
                                                 correctionFactor, s_thermalRot );

    // remove copper areas corresponding to not connected stubs
    if( !thermalHoles.IsEmpty() )
    {
        thermalHoles.Simplify( POLY_CALC_MODE );
        // Remove unconnected stubs
        solidAreas.BooleanSubtract( thermalHoles, POLY_CALC_MODE );

        if( g_DumpZonesWhenFilling )
            dumper->Write( &thermalHoles, "thermal-holes" );

        // put these areas in m_FilledPolysList
        SHAPE_POLY_SET th_fractured = solidAreas;
        th_fractured.Fracture( POLY_CALC_MODE );

        if( g_DumpZonesWhenFilling )
            dumper->Write ( &th_fractured, "th_fractured" );

        m_FilledPolysList = th_fractured;

        if( GetNetCode() > 0 )
            TestForCopperIslandAndRemoveInsulatedIslands( aPcb );
    }

    if(g_DumpZonesWhenFilling)
        dumper->EndGroup();
}