void Draw3D_ArcSegment( const wxPoint& aCenterPos, const wxPoint& aStartPoint, double aArcAngle, int aWidth, int aThickness, int aZpos, double aBiuTo3DUnits ) { const int slice = SEGM_PER_CIRCLE; CPOLYGONS_LIST cornerBuffer; TransformArcToPolygon( cornerBuffer, aCenterPos, aStartPoint, aArcAngle, slice, aWidth ); Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits, false ); }
void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aError, bool ignoreLineWidth ) const { // The full width of the lines to create: int linewidth = ignoreLineWidth ? 0 : m_Width; linewidth += 2 * aClearanceValue; // Creating a reliable clearance shape for circles and arcs is not so easy, due to // the error created by segment approximation. // for a circle this is not so hard: create a polygon from a circle slightly bigger: // thickness = linewidth + s_error_max, and radius = initial radius + s_error_max/2 // giving a shape with a suitable internal radius and external radius // For an arc this is more tricky: TODO switch( m_Shape ) { case S_CIRCLE: TransformRingToPolygon( aCornerBuffer, GetCenter(), GetRadius(), aError, linewidth ); break; case S_ARC: TransformArcToPolygon( aCornerBuffer, GetCenter(), GetArcStart(), m_Angle, aError, linewidth ); break; case S_SEGMENT: TransformOvalClearanceToPolygon( aCornerBuffer, m_Start, m_End, linewidth, aError ); break; case S_POLYGON: if( IsPolyShapeValid() ) { // The polygon is expected to be a simple polygon // not self intersecting, no hole. MODULE* module = GetParentModule(); // NULL for items not in footprints double orientation = module ? module->GetOrientation() : 0.0; wxPoint offset; if( module ) offset = module->GetPosition(); // Build the polygon with the actual position and orientation: std::vector< wxPoint> poly; poly = BuildPolyPointsList(); for( unsigned ii = 0; ii < poly.size(); ii++ ) { RotatePoint( &poly[ii], orientation ); poly[ii] += offset; } // If the polygon is not filled, treat it as a closed set of lines if( !IsPolygonFilled() ) { for( size_t ii = 1; ii < poly.size(); ii++ ) { TransformOvalClearanceToPolygon( aCornerBuffer, poly[ii - 1], poly[ii], linewidth, aError ); } TransformOvalClearanceToPolygon( aCornerBuffer, poly.back(), poly.front(), linewidth, aError ); break; } // Generate polygons for the outline + clearance // This code is compatible with a polygon with holes linked to external outline // by overlapping segments. // Insert the initial polygon: aCornerBuffer.NewOutline(); for( unsigned ii = 0; ii < poly.size(); ii++ ) aCornerBuffer.Append( poly[ii].x, poly[ii].y ); if( linewidth ) // Add thick outlines { wxPoint corner1( poly[poly.size()-1] ); for( unsigned ii = 0; ii < poly.size(); ii++ ) { wxPoint corner2( poly[ii] ); if( corner2 != corner1 ) { TransformRoundedEndsSegmentToPolygon( aCornerBuffer, corner1, corner2, aError, linewidth ); } corner1 = corner2; } } } break; case S_CURVE: // Bezier curve { std::vector<wxPoint> ctrlPoints = { m_Start, m_BezierC1, m_BezierC2, m_End }; BEZIER_POLY converter( ctrlPoints ); std::vector< wxPoint> poly; converter.GetPoly( poly, m_Width ); for( unsigned ii = 1; ii < poly.size(); ii++ ) { TransformRoundedEndsSegmentToPolygon( aCornerBuffer, poly[ii - 1], poly[ii], aError, linewidth ); } } break; default: break; } }
bool D_PAD::buildCustomPadPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError ) { SHAPE_POLY_SET aux_polyset; for( unsigned cnt = 0; cnt < m_basicShapes.size(); ++cnt ) { const PAD_CS_PRIMITIVE& bshape = m_basicShapes[cnt]; switch( bshape.m_Shape ) { case S_CURVE: { std::vector<wxPoint> ctrlPoints = { bshape.m_Start, bshape.m_Ctrl1, bshape.m_Ctrl2, bshape.m_End }; BEZIER_POLY converter( ctrlPoints ); std::vector< wxPoint> poly; converter.GetPoly( poly, bshape.m_Thickness ); for( unsigned ii = 1; ii < poly.size(); ii++ ) { TransformRoundedEndsSegmentToPolygon( aux_polyset, poly[ii - 1], poly[ii], aError, bshape.m_Thickness ); } break; } case S_SEGMENT: // usual segment : line with rounded ends { TransformRoundedEndsSegmentToPolygon( aux_polyset, bshape.m_Start, bshape.m_End, aError, bshape.m_Thickness ); break; } case S_ARC: // Arc with rounded ends { TransformArcToPolygon( aux_polyset, bshape.m_Start, bshape.m_End, bshape.m_ArcAngle, aError, bshape.m_Thickness ); break; } case S_CIRCLE: // ring or circle { if( bshape.m_Thickness ) // ring TransformRingToPolygon( aux_polyset, bshape.m_Start, bshape.m_Radius, aError, bshape.m_Thickness ); else // Filled circle TransformCircleToPolygon( aux_polyset, bshape.m_Start, bshape.m_Radius, aError ); break; } case S_POLYGON: // polygon if( bshape.m_Poly.size() < 2 ) break; // Malformed polygon. { // Insert the polygon: const std::vector< wxPoint>& poly = bshape.m_Poly; aux_polyset.NewOutline(); if( bshape.m_Thickness ) { SHAPE_POLY_SET polyset; polyset.NewOutline(); for( unsigned ii = 0; ii < poly.size(); ii++ ) { polyset.Append( poly[ii].x, poly[ii].y ); } int numSegs = std::max( GetArcToSegmentCount( bshape.m_Thickness / 2, aError, 360.0 ), 6 ); polyset.Inflate( bshape.m_Thickness / 2, numSegs ); aux_polyset.Append( polyset ); } else for( unsigned ii = 0; ii < poly.size(); ii++ ) aux_polyset.Append( poly[ii].x, poly[ii].y ); } break; default: break; } } aux_polyset.Simplify( SHAPE_POLY_SET::PM_FAST ); // Merge all polygons with the initial pad anchor shape if( aux_polyset.OutlineCount() ) { aMergedPolygon->BooleanAdd( aux_polyset, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); aMergedPolygon->Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); } return aMergedPolygon->OutlineCount() <= 1; }
/* 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 TransformShapeWithClearanceToPolygon * Convert the track shape to a closed polygon * Used in filling zones calculations * Circles and arcs are approximated by segments * @param aCornerBuffer = a buffer to store the polygon * @param aClearanceValue = the clearance around the pad * @param aCircleToSegmentsCount = the number of segments to approximate a circle * @param aCorrectionFactor = the correction to apply to circles radius to keep * clearance when the circle is approxiamted by segment bigger or equal * to the real clearance value (usually near from 1.0) */ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aClearanceValue, int aCircleToSegmentsCount, double aCorrectionFactor ) const { // The full width of the lines to create: int linewidth = m_Width + (2 * aClearanceValue); switch( m_Shape ) { case S_CIRCLE: TransformRingToPolygon( aCornerBuffer, GetCenter(), GetRadius(), aCircleToSegmentsCount, linewidth ) ; break; case S_ARC: TransformArcToPolygon( aCornerBuffer, GetCenter(), GetArcStart(), m_Angle, aCircleToSegmentsCount, linewidth ); break; case S_SEGMENT: TransformRoundedEndsSegmentToPolygon( aCornerBuffer, m_Start, m_End, aCircleToSegmentsCount, linewidth ); break; case S_POLYGON: if ( GetPolyPoints().size() < 2 ) break; // Malformed polygon. { // The polygon is expected to be a simple polygon // not self intersecting, no hole. MODULE* module = GetParentModule(); // NULL for items not in footprints double orientation = module ? module->GetOrientation() : 0.0; // Build the polygon with the actual position and orientation: std::vector< wxPoint> poly; poly = GetPolyPoints(); for( unsigned ii = 0; ii < poly.size(); ii++ ) { RotatePoint( &poly[ii], orientation ); poly[ii] += GetPosition(); } // Generate polygons for the outline + clearance // This code is compatible with a polygon with holes linked to external outline // by overlapping segments. // Insert the initial polygon: aCornerBuffer.NewOutline(); for( unsigned ii = 0; ii < poly.size(); ii++ ) aCornerBuffer.Append( poly[ii].x, poly[ii].y ); if( linewidth ) // Add thick outlines { CPolyPt corner1( poly[poly.size()-1] ); for( unsigned ii = 0; ii < poly.size(); ii++ ) { CPolyPt corner2( poly[ii] ); if( corner2 != corner1 ) { TransformRoundedEndsSegmentToPolygon( aCornerBuffer, corner1, corner2, aCircleToSegmentsCount, linewidth ); } corner1 = corner2; } } } break; case S_CURVE: // Bezier curve (TODO: not yet in use) break; default: break; } }