D_PAD::D_PAD( MODULE* parent ) : BOARD_CONNECTED_ITEM( parent, PCB_PAD_T ) { m_NumPadName = 0; m_Size.x = m_Size.y = Mils2iu( 60 ); // Default pad size 60 mils. m_Drill.x = m_Drill.y = Mils2iu( 30 ); // Default drill size 30 mils. m_Orient = 0; // Pad rotation in 1/10 degrees. m_LengthPadToDie = 0; if( m_Parent && m_Parent->Type() == PCB_MODULE_T ) { m_Pos = GetParent()->GetPosition(); } SetShape( PAD_SHAPE_CIRCLE ); // Default pad shape is PAD_CIRCLE. SetDrillShape( PAD_DRILL_SHAPE_CIRCLE ); // Default pad drill shape is a circle. m_Attribute = PAD_ATTRIB_STANDARD; // Default pad type is NORMAL (thru hole) m_LocalClearance = 0; m_LocalSolderMaskMargin = 0; m_LocalSolderPasteMargin = 0; m_LocalSolderPasteMarginRatio = 0.0; // Parameters for round rect only: m_padRoundRectRadiusScale = 0.25; // from IPC-7351C standard m_ZoneConnection = PAD_ZONE_CONN_INHERITED; // Use parent setting by default m_ThermalWidth = 0; // Use parent setting by default m_ThermalGap = 0; // Use parent setting by default // Set layers mask to default for a standard thru hole pad. m_layerMask = StandardMask(); SetSubRatsnest( 0 ); // used in ratsnest calculations m_boundingRadius = -1; }
ZONE_SETTINGS::ZONE_SETTINGS() { m_ZonePriority = 0; m_FillMode = 0; // Mode for filling zone : 1 use segments, 0 use polygons // Clearance value m_ZoneClearance = Mils2iu( ZONE_CLEARANCE_MIL ); // Min thickness value in filled areas (this is the minimum width of copper to fill solid areas) : m_ZoneMinThickness = Mils2iu( ZONE_THICKNESS_MIL ); m_NetcodeSelection = 0; // Net code selection for the current zone m_CurrentZone_Layer = FIRST_LAYER; // Layer used to create the current zone m_Zone_HatchingStyle = CPolyLine::DIAGONAL_EDGE; // Option to show the zone area (outlines only, short hatches or full hatches m_ArcToSegmentsCount = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF; // Option to select number of segments to approximate a circle // ARC_APPROX_SEGMENTS_COUNT_LOW_DEF // or ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF segments // thickness of the gap in thermal reliefs: m_ThermalReliefGap = Mils2iu( ZONE_THERMAL_RELIEF_GAP_MIL ); // thickness of the copper bridge in thermal reliefs: m_ThermalReliefCopperBridge = Mils2iu( ZONE_THERMAL_RELIEF_COPPER_WIDTH_MIL ); m_PadConnection = THERMAL_PAD; // How pads are covered by copper in zone m_Zone_45_Only = false; m_cornerSmoothingType = SMOOTHING_NONE; m_cornerRadius = 0; SetIsKeepout( false ); SetDoNotAllowCopperPour( false ); SetDoNotAllowVias( true ); SetDoNotAllowTracks( true ); }
void EDA_TEXT::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const throw( IO_ERROR ) { #ifndef GERBVIEW // Gerbview does not use EDA_TEXT::Format // and does not define FMT_IU, used here // however this function should exist if( !IsDefaultFormatting() ) { aFormatter->Print( aNestLevel+1, "(effects" ); if( ( m_Size.x != Mils2iu( DEFAULT_SIZE_TEXT ) ) || ( m_Size.y != Mils2iu( DEFAULT_SIZE_TEXT ) ) || ( m_Thickness != 0 ) || m_Bold || m_Italic ) { aFormatter->Print( 0, " (font" ); // Add font support here at some point in the future. if( ( m_Size.x != Mils2iu( DEFAULT_SIZE_TEXT ) ) || ( m_Size.y != Mils2iu( DEFAULT_SIZE_TEXT ) ) ) aFormatter->Print( 0, " (size %s %s)", FMT_IU( m_Size.GetHeight() ).c_str(), FMT_IU( m_Size.GetWidth() ).c_str() ); if( m_Thickness != 0 ) aFormatter->Print( 0, " (thickness %s)", FMT_IU( GetThickness() ).c_str() ); if( m_Bold ) aFormatter->Print( 0, " bold" ); if( IsItalic() ) aFormatter->Print( 0, " italic" ); aFormatter->Print( 0, ")"); } if( m_Mirror || ( m_HJustify != GR_TEXT_HJUSTIFY_CENTER ) || ( m_VJustify != GR_TEXT_VJUSTIFY_CENTER ) ) { aFormatter->Print( 0, " (justify"); if( m_HJustify != GR_TEXT_HJUSTIFY_CENTER ) aFormatter->Print( 0, (m_HJustify == GR_TEXT_HJUSTIFY_LEFT) ? " left" : " right" ); if( m_VJustify != GR_TEXT_VJUSTIFY_CENTER ) aFormatter->Print( 0, (m_VJustify == GR_TEXT_VJUSTIFY_TOP) ? " top" : " bottom" ); if( m_Mirror ) aFormatter->Print( 0, " mirror" ); aFormatter->Print( 0, ")" ); } // As of now the only place this is used is in Eeschema to hide or show the text. if( m_Attributs ) aFormatter->Print( 0, " hide" ); aFormatter->Print( 0, ")\n" ); } #endif }
bool EDA_TEXT::IsDefaultFormatting() const { return ( ( m_Size.x == Mils2iu( DEFAULT_SIZE_TEXT ) ) && ( m_Size.y == Mils2iu( DEFAULT_SIZE_TEXT ) ) && ( m_Attributs == 0 ) && ( m_Mirror == false ) && ( m_HJustify == GR_TEXT_HJUSTIFY_CENTER ) && ( m_VJustify == GR_TEXT_VJUSTIFY_CENTER ) && ( m_Thickness == 0 ) && ( m_Italic == false ) && ( m_Bold == false ) && ( m_MultilineAllowed == false ) ); }
void ZONE_SETTINGS::ExportSetting( ZONE_CONTAINER& aTarget, bool aFullExport ) const { aTarget.SetFillMode( m_FillMode ); aTarget.SetZoneClearance( m_ZoneClearance ); aTarget.SetMinThickness( m_ZoneMinThickness ); aTarget.SetArcSegmentCount( m_ArcToSegmentsCount ); aTarget.SetThermalReliefGap( m_ThermalReliefGap ); aTarget.SetThermalReliefCopperBridge( m_ThermalReliefCopperBridge ); aTarget.SetPadConnection( m_PadConnection ); aTarget.SetCornerSmoothingType( m_cornerSmoothingType ); aTarget.SetCornerRadius( m_cornerRadius ); aTarget.SetIsKeepout( GetIsKeepout() ); aTarget.SetDoNotAllowCopperPour( GetDoNotAllowCopperPour() ); aTarget.SetDoNotAllowVias( GetDoNotAllowVias() ); aTarget.SetDoNotAllowTracks( GetDoNotAllowTracks() ); if( aFullExport ) { aTarget.SetPriority( m_ZonePriority ); aTarget.SetNet( m_NetcodeSelection ); aTarget.SetLayer( m_CurrentZone_Layer ); aTarget.Outline()->SetLayer( m_CurrentZone_Layer ); } // call SetHatch last, because hatch lines will be rebuilt, // using new parameters values aTarget.Outline()->SetHatch( m_Zone_HatchingStyle, Mils2iu( 20 ), true ); }
bool DIALOG_TARGET_PROPERTIES::TransferDataFromWindow() { // Zero-size targets are hard to see/select. if( !m_Size.Validate( Mils2iu( 1 ), INT_MAX ) ) return false; BOARD_COMMIT commit( m_Parent ); commit.Modify( m_Target ); if( m_DC ) m_Target->Draw( m_Parent->GetCanvas(), m_DC, GR_XOR ); // Save old item in undo list, if is is not currently edited (will be later if so) bool pushCommit = ( m_Target->GetFlags() == 0 ); if( m_Target->GetFlags() != 0 ) // other edit in progress (MOVE, NEW ..) m_Target->SetFlags( IN_EDIT ); // set flag in edit to force // undo/redo/abort proper operation m_Target->SetWidth( m_Thickness.GetValue() ); m_Target->SetSize( m_Size.GetValue() ); m_Target->SetShape( m_TargetShape->GetSelection() ? 1 : 0 ); if( m_DC ) m_Target->Draw( m_Parent->GetCanvas(), m_DC, ( m_Target->IsMoving() ) ? GR_XOR : GR_OR ); if( pushCommit ) commit.Push( _( "Modified alignment target" ) ); return true; }
double StrToDoublePrecisionUnits( wxString aStr, char aAxe, wxString aActualConversion ) { wxString ls; double i; char u; ls = aStr; ls.Trim( true ); ls.Trim( false ); if( ls.Len() > 0 ) { u = ls[ls.Len() - 1]; while( ls.Len() > 0 && !( ls[ls.Len() - 1] == wxT( '.' ) || ls[ls.Len() - 1] == wxT( ',' ) || (ls[ls.Len() - 1] >= wxT( '0' ) && ls[ls.Len() - 1] <= wxT( '9' ) ) ) ) { ls = ls.Left( ls.Len() - 1 ); } while( ls.Len() > 0 && !( ls[0] == wxT( '-' ) || ls[0] == wxT( '+' ) || ls[0] == wxT( '.' ) || ls[0] == wxT( ',' ) || (ls[0] >= wxT( '0' ) && ls[0] <= wxT( '9' ) ) ) ) { ls = ls.Mid( 1 ); } if( u == wxT( 'm' ) ) { ls.ToDouble( &i ); #ifdef PCAD2KICAD_SCALE_SCH_TO_INCH_GRID if( aActualConversion == wxT( "SCH" ) || aActualConversion == wxT( "SCHLIB" ) ) i = i * (0.0254 / 0.025); #endif i = Millimeter2iu( i ); } else { ls.ToDouble( &i ); i = Mils2iu( i ); } } else i = 0.0; if( ( aActualConversion == wxT( "PCB" ) || aActualConversion == wxT( "SCH" ) ) && aAxe == wxT( 'Y' ) ) return -i; else return i; // Y axe is mirrored compared to P-Cad }
void DIALOG_PAGES_SETTINGS::OnOkClick( wxCommandEvent& event ) { if( !m_customSizeX.Validate( Mils2iu( MIN_PAGE_SIZE ), Mils2iu( m_maxPageSizeMils.x ) ) ) return; if( !m_customSizeY.Validate( Mils2iu( MIN_PAGE_SIZE ), Mils2iu( m_maxPageSizeMils.y ) ) ) return; if( SavePageSettings() ) { m_screen->SetModify(); if( LocalPrjConfigChanged() ) m_parent->SaveProjectSettings( false ); // Call the post processing (if any) after changes m_parent->OnPageSettingsChange(); } event.Skip(); }
double GERBVIEW_FRAME::BestZoom() { EDA_RECT bbox = GetGerberLayout()->ComputeBoundingBox(); // gives a size to bbox (current page size), if no item in list if( bbox.GetWidth() == 0 || bbox.GetHeight() == 0 ) { wxSize pagesize = GetPageSettings().GetSizeMils(); bbox.SetSize( wxSize( Mils2iu( pagesize.x ), Mils2iu( pagesize.y ) ) ); } // Compute best zoom: wxSize size = m_canvas->GetClientSize(); double x = (double) bbox.GetWidth() / (double) size.x; double y = (double) bbox.GetHeight() / (double) size.y; double best_zoom = std::max( x, y ) * 1.1; SetScrollCenterPosition( bbox.Centre() ); return best_zoom; }
EDA_TEXT::EDA_TEXT( const wxString& text ) { m_Size.x = m_Size.y = Mils2iu( DEFAULT_SIZE_TEXT ); // Width and height of font. m_Orient = 0; // Rotation angle in 0.1 degrees. m_Attributs = 0; m_Mirror = false; // display mirror if true m_HJustify = GR_TEXT_HJUSTIFY_CENTER; // Default horizontal justification is centered. m_VJustify = GR_TEXT_VJUSTIFY_CENTER; // Default vertical justification is centered. m_Thickness = 0; // thickness m_Italic = false; // true = italic shape. m_Bold = false; m_MultilineAllowed = false; // Set to true for multiline text. m_Text = text; }
void DIMENSION::AdjustDimensionDetails( bool aDoNotChangeText ) { const int arrowz = Mils2iu( 50 ); // size of arrows int ii; int measure, deltax, deltay; // value of the measure on X and Y axes int arrow_up_X = 0, arrow_up_Y = 0; // coordinates of arrow line / int arrow_dw_X = 0, arrow_dw_Y = 0; // coordinates of arrow line '\' int hx, hy; // dimension line interval double angle, angle_f; wxString msg; // Init layer : m_Text.SetLayer( GetLayer() ); // calculate the size of the dimension (text + line above the text) ii = m_Text.GetSize().y + m_Text.GetThickness() + (m_Width * 3); deltax = m_featureLineDO.x - m_featureLineGO.x; deltay = m_featureLineDO.y - m_featureLineGO.y; // Calculate dimension value measure = KiROUND( hypot( deltax, deltay ) ); angle = atan2( (double)deltay, (double)deltax ); // Calculation of parameters X and Y dimensions of the arrows and lines. hx = hy = ii; // Taking into account the slope of the side lines. if( measure ) { hx = abs( KiROUND( ( (double) deltay * hx ) / measure ) ); hy = abs( KiROUND( ( (double) deltax * hy ) / measure ) ); if( m_featureLineGO.x > m_crossBarO.x ) hx = -hx; if( m_featureLineGO.x == m_crossBarO.x ) hx = 0; if( m_featureLineGO.y > m_crossBarO.y ) hy = -hy; if( m_featureLineGO.y == m_crossBarO.y ) hy = 0; angle_f = angle + DEG2RAD( 27.5 ); arrow_up_X = wxRound( arrowz * cos( angle_f ) ); arrow_up_Y = wxRound( arrowz * sin( angle_f ) ); angle_f = angle - DEG2RAD( 27.5 ); arrow_dw_X = wxRound( arrowz * cos( angle_f ) ); arrow_dw_Y = wxRound( arrowz * sin( angle_f ) ); } int dx = KiROUND( m_Height * cos( angle + M_PI / 2 ) ); int dy = KiROUND( m_Height * sin( angle + M_PI / 2 ) ); m_crossBarO.x = m_featureLineGO.x + dx; m_crossBarO.y = m_featureLineGO.y + dy; m_crossBarF.x = m_featureLineDO.x + dx; m_crossBarF.y = m_featureLineDO.y + dy; m_arrowG1F.x = m_crossBarO.x + arrow_up_X; m_arrowG1F.y = m_crossBarO.y + arrow_up_Y; m_arrowG2F.x = m_crossBarO.x + arrow_dw_X; m_arrowG2F.y = m_crossBarO.y + arrow_dw_Y; /* The right arrow is symmetrical to the left. * / = -\ and \ = -/ */ m_arrowD1F.x = m_crossBarF.x - arrow_dw_X; m_arrowD1F.y = m_crossBarF.y - arrow_dw_Y; m_arrowD2F.x = m_crossBarF.x - arrow_up_X; m_arrowD2F.y = m_crossBarF.y - arrow_up_Y; m_featureLineGF.x = m_crossBarO.x + hx; m_featureLineGF.y = m_crossBarO.y + hy; m_featureLineDF.x = m_crossBarF.x + hx; m_featureLineDF.y = m_crossBarF.y + hy; // Calculate the better text position and orientation: wxPoint textPos; textPos.x = (m_crossBarF.x + m_featureLineGF.x) / 2; textPos.y = (m_crossBarF.y + m_featureLineGF.y) / 2; m_Text.SetTextPosition( textPos ); double newAngle = -RAD2DECIDEG( angle ); NORMALIZE_ANGLE_POS( newAngle ); if( newAngle > 900 && newAngle < 2700 ) newAngle -= 1800; m_Text.SetOrientation( newAngle ); if( !aDoNotChangeText ) { m_Value = measure; msg = ::CoordinateToString( m_Value ); SetText( msg ); } }
void ZONE_CONTAINER::SetCornerRadius( unsigned int aRadius ) { m_cornerRadius = aRadius; if( m_cornerRadius > (unsigned int) Mils2iu( MAX_ZONE_CORNER_RADIUS_MILS ) ) m_cornerRadius = Mils2iu( MAX_ZONE_CORNER_RADIUS_MILS ); };
int ZONE_CONTAINER::FillZoneAreasWithSegments() { int ics, ice; int count = 0; std::vector <int> x_coordinates; bool error = false; int istart, iend; // index of the starting and the endif corner of one filled area in m_FilledPolysList int margin = m_ZoneMinThickness * 2 / 10; int minwidth = Mils2iu( 2 ); margin = std::max ( minwidth, margin ); int step = m_ZoneMinThickness - margin; step = std::max( step, minwidth ); // Read all filled areas in m_FilledPolysList m_FillSegmList.clear(); istart = 0; int end_list = m_FilledPolysList.GetCornersCount()-1; for( int ic = 0; ic <= end_list; ic++ ) { CPolyPt* corner = &m_FilledPolysList[ic]; if ( corner->end_contour || (ic == end_list) ) { iend = ic; EDA_RECT rect = CalculateSubAreaBoundaryBox( istart, iend ); // Calculate the y limits of the zone int refy = rect.GetY(); int endy = rect.GetBottom(); for( ; refy < endy; refy += step ) { // find all intersection points of an infinite line with polyline sides x_coordinates.clear(); for( ics = istart, ice = iend; ics <= iend; ice = ics, ics++ ) { if ( m_FilledPolysList[ice].m_utility ) continue; int seg_startX = m_FilledPolysList[ics].x; int seg_startY = m_FilledPolysList[ics].y; int seg_endX = m_FilledPolysList[ice].x; int seg_endY = m_FilledPolysList[ice].y; /* Trivial cases: skip if ref above or below the segment to test */ if( ( seg_startY > refy ) && (seg_endY > refy ) ) continue; // segment below ref point, or its Y end pos on Y coordinate ref point: skip if( ( seg_startY <= refy ) && (seg_endY <= refy ) ) continue; /* at this point refy is between seg_startY and seg_endY * see if an horizontal line at Y = refy is intersecting this segment */ // calculate the x position of the intersection of this segment and the // infinite line this is more easier if we move the X,Y axis origin to // the segment start point: seg_endX -= seg_startX; seg_endY -= seg_startY; double newrefy = (double) (refy - seg_startY); double intersec_x; if ( seg_endY == 0 ) // horizontal segment on the same line: skip continue; // Now calculate the x intersection coordinate of the horizontal line at // y = newrefy and the segment from (0,0) to (seg_endX,seg_endY) with the // horizontal line at the new refy position the line slope is: // slope = seg_endY/seg_endX; and inv_slope = seg_endX/seg_endY // and the x pos relative to the new origin is: // intersec_x = refy/slope = refy * inv_slope // Note: because horizontal segments are already tested and skipped, slope // exists (seg_end_y not O) double inv_slope = (double)seg_endX / seg_endY; intersec_x = newrefy * inv_slope; x_coordinates.push_back((int) intersec_x + seg_startX); } // A line scan is finished: build list of segments // Sort intersection points by increasing x value: // So 2 consecutive points are the ends of a segment sort( x_coordinates.begin(), x_coordinates.end(), SortByXValues ); // Create segments if ( !error && ( x_coordinates.size() & 1 ) != 0 ) { // An even number of coordinates is expected, because a segment has 2 ends. // An if this algorithm always works, it must always find an even count. wxString msg = wxT("Fill Zone: odd number of points at y = "); msg << refy; wxMessageBox(msg ); error = true; } if ( error ) break; int iimax = x_coordinates.size()-1; for (int ii = 0; ii < iimax; ii +=2 ) { wxPoint seg_start, seg_end; count++; seg_start.x = x_coordinates[ii]; seg_start.y = refy; seg_end.x = x_coordinates[ii+1]; seg_end.y = refy; SEGMENT segment( seg_start, seg_end ); m_FillSegmList.push_back( segment ); } } //End examine segments in one area if ( error ) break; istart = iend + 1; // istart points the first corner of the next area } // End find one end of outline if ( error ) break; } // End examine all areas return count; }