const double DRAWSEGMENT::GetArcAngleStart() const { // due to the Y axis orient atan2 needs - y value double angleStart = ArcTangente( GetArcStart().y - GetCenter().y, GetArcStart().x - GetCenter().x ); // Normalize it to 0 ... 360 deg, to avoid discontinuity for angles near 180 deg // because 180 deg and -180 are very near angles when ampping betewwen -180 ... 180 deg. // and this is not easy to handle in calculations NORMALIZE_ANGLE_POS( angleStart ); return angleStart; }
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; } }
/** * 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; } }