Move pads to EDA_ANGLE.
This commit is contained in:
parent
e048e51f5d
commit
d485eb2514
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 CERN
|
||||
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -96,7 +96,7 @@ size_t hash_fp_item( const EDA_ITEM* aItem, int aFlags )
|
|||
}
|
||||
|
||||
if( aFlags & HASH_ROT )
|
||||
hash_combine( ret, pad->GetOrientation() );
|
||||
hash_combine( ret, pad->GetOrientation().AsTenthsOfADegree() );
|
||||
|
||||
if( aFlags & HASH_NET )
|
||||
hash_combine( ret, pad->GetNetCode() );
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
|
||||
*
|
||||
* Copyright (C) 1992-2020 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see change_log.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -933,10 +933,10 @@ void AR_MATRIX::PlacePad( PAD* aPad, int color, int marge, AR_MATRIX::CELL_OP op
|
|||
}
|
||||
|
||||
// The pad is a rectangle ( horizontal or vertical )
|
||||
if( int( aPad->GetOrientation() ) % 900 == 0 )
|
||||
if( aPad->GetOrientation().IsCardinal() )
|
||||
{
|
||||
// Orientation turned 90 deg.
|
||||
if( aPad->GetOrientation() == 900 || aPad->GetOrientation() == 2700 )
|
||||
if( aPad->GetOrientation() == ANGLE_90 || aPad->GetOrientation() == ANGLE_270 )
|
||||
{
|
||||
std::swap( dx, dy );
|
||||
}
|
||||
|
@ -947,6 +947,7 @@ void AR_MATRIX::PlacePad( PAD* aPad, int color, int marge, AR_MATRIX::CELL_OP op
|
|||
else
|
||||
{
|
||||
TraceFilledRectangle( shape_pos.x - dx, shape_pos.y - dy, shape_pos.x + dx,
|
||||
shape_pos.y + dy, aPad->GetOrientation(), aPad->GetLayerSet(), color, op_logic );
|
||||
shape_pos.y + dy, aPad->GetOrientation().AsTenthsOfADegree(),
|
||||
aPad->GetLayerSet(), color, op_logic );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* This program source code file is part of KICAD, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016-2018 CERN
|
||||
* Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
|
@ -92,7 +92,7 @@ const VECTOR2I CN_ITEM::GetAnchor( int n ) const
|
|||
default: break; // Wicked witch
|
||||
}
|
||||
|
||||
if( pad->GetOrientation() )
|
||||
if( !pad->GetOrientation().IsZero() )
|
||||
RotatePoint( pt1, pad->ShapePos(), pad->GetOrientation() );
|
||||
|
||||
// Thermal spokes on circular pads form an 'X' instead of a '+'
|
||||
|
@ -112,7 +112,7 @@ const VECTOR2I CN_ITEM::GetAnchor( int n ) const
|
|||
default: break; // Wicked witch
|
||||
}
|
||||
|
||||
if( pad->GetOrientation() )
|
||||
if( !pad->GetOrientation().IsZero() )
|
||||
RotatePoint( pt1, pad->ShapePos(), pad->GetOrientation() );
|
||||
|
||||
const std::shared_ptr<SHAPE_POLY_SET>& padPolySet = pad->GetEffectivePolygon();
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2013 Dick Hollenbeck, dick@softplc.com
|
||||
* Copyright (C) 2008-2013 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -486,8 +486,8 @@ void DIALOG_PAD_PROPERTIES::initValues()
|
|||
|
||||
if( footprint )
|
||||
{
|
||||
double angle = m_dummyPad->GetOrientation();
|
||||
angle -= footprint->GetOrientation();
|
||||
EDA_ANGLE angle = m_dummyPad->GetOrientation();
|
||||
angle -= EDA_ANGLE( footprint->GetOrientation(), TENTHS_OF_A_DEGREE_T );
|
||||
m_dummyPad->SetOrientation( angle );
|
||||
|
||||
// Display parent footprint info
|
||||
|
@ -559,11 +559,11 @@ void DIALOG_PAD_PROPERTIES::initValues()
|
|||
m_clearance.ChangeValue( m_dummyPad->GetLocalClearance() );
|
||||
m_maskMargin.ChangeValue( m_dummyPad->GetLocalSolderMaskMargin() );
|
||||
m_spokeWidth.ChangeValue( m_dummyPad->GetThermalSpokeWidth() );
|
||||
m_spokeAngle.ChangeDoubleValue( m_dummyPad->GetThermalSpokeAngle() );
|
||||
m_spokeAngle.ChangeDoubleValue( m_dummyPad->GetThermalSpokeAngle().AsTenthsOfADegree() );
|
||||
m_thermalGap.ChangeValue( m_dummyPad->GetThermalGap() );
|
||||
m_pasteMargin.ChangeValue( m_dummyPad->GetLocalSolderPasteMargin() );
|
||||
m_pasteMarginRatio.ChangeDoubleValue( m_dummyPad->GetLocalSolderPasteMarginRatio() * 100.0 );
|
||||
m_pad_orientation.ChangeDoubleValue( m_dummyPad->GetOrientation() );
|
||||
m_pad_orientation.ChangeDoubleValue( m_dummyPad->GetOrientation().AsTenthsOfADegree() );
|
||||
|
||||
switch( m_dummyPad->GetZoneConnection() )
|
||||
{
|
||||
|
@ -1478,7 +1478,7 @@ void DIALOG_PAD_PROPERTIES::redraw()
|
|||
{
|
||||
PCB_SHAPE* dummyShape = (PCB_SHAPE*) m_primitives[select]->Clone();
|
||||
dummyShape->SetLayer( SELECTED_ITEMS_LAYER );
|
||||
dummyShape->Rotate( wxPoint( 0, 0), m_dummyPad->GetOrientation() );
|
||||
dummyShape->Rotate( VECTOR2I( 0, 0), m_dummyPad->GetOrientation().AsTenthsOfADegree() );
|
||||
dummyShape->Move( m_dummyPad->GetPosition() );
|
||||
|
||||
view->Add( dummyShape );
|
||||
|
@ -1655,8 +1655,8 @@ bool DIALOG_PAD_PROPERTIES::TransferDataFromWindow()
|
|||
VECTOR2I pt = m_currentPad->GetPosition() - footprint->GetPosition();
|
||||
RotatePoint( pt, -footprint->GetOrientation() );
|
||||
m_currentPad->SetPos0( pt );
|
||||
m_currentPad->SetOrientation( m_currentPad->GetOrientation() +
|
||||
footprint->GetOrientation() );
|
||||
m_currentPad->SetOrientation( m_currentPad->GetOrientation()
|
||||
+ EDA_ANGLE( footprint->GetOrientation(), TENTHS_OF_A_DEGREE_T ) );
|
||||
}
|
||||
|
||||
m_parent->SetMsgPanel( m_currentPad );
|
||||
|
@ -1719,11 +1719,11 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( PAD* aPad )
|
|||
aPad->SetLocalSolderPasteMargin( m_pasteMargin.GetValue() );
|
||||
aPad->SetLocalSolderPasteMarginRatio( m_pasteMarginRatio.GetDoubleValue() / 100.0 );
|
||||
aPad->SetThermalSpokeWidth( m_spokeWidth.GetValue() );
|
||||
aPad->SetThermalSpokeAngle( m_spokeAngle.GetDoubleValue() );
|
||||
aPad->SetThermalSpokeAngle( EDA_ANGLE( m_spokeAngle.GetDoubleValue(), TENTHS_OF_A_DEGREE_T ) );
|
||||
aPad->SetThermalGap( m_thermalGap.GetValue() );
|
||||
|
||||
// And rotation
|
||||
aPad->SetOrientation( m_pad_orientation.GetDoubleValue() );
|
||||
aPad->SetOrientation( EDA_ANGLE( m_pad_orientation.GetDoubleValue(), TENTHS_OF_A_DEGREE_T ) );
|
||||
|
||||
switch( m_ZoneConnectionChoice->GetSelection() )
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 KiCad Developers.
|
||||
* Copyright (C) 2021-2022 KiCad Developers.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -147,8 +147,8 @@ bool padsNeedUpdate( const PAD* a, const PAD* b )
|
|||
TEST( a->GetProperty(), b->GetProperty() );
|
||||
|
||||
// The pad orientation, for historical reasons is the pad rotation + parent rotation.
|
||||
TEST( NormalizeAnglePos( a->GetOrientation() - a->GetParent()->GetOrientation() ),
|
||||
NormalizeAnglePos( b->GetOrientation() - b->GetParent()->GetOrientation() ) );
|
||||
TEST( ( a->GetOrientation() - EDA_ANGLE( a->GetParent()->GetOrientation(), TENTHS_OF_A_DEGREE_T ) ).Normalize().AsTenthsOfADegree(),
|
||||
( b->GetOrientation() - EDA_ANGLE( b->GetParent()->GetOrientation(), TENTHS_OF_A_DEGREE_T ) ).Normalize().AsTenthsOfADegree() );
|
||||
|
||||
TEST( a->GetSize(), b->GetSize() );
|
||||
TEST( a->GetDelta(), b->GetDelta() );
|
||||
|
@ -169,7 +169,7 @@ bool padsNeedUpdate( const PAD* a, const PAD* b )
|
|||
TEST( a->GetZoneConnection(), b->GetZoneConnection() );
|
||||
TEST( a->GetThermalGap(), b->GetThermalGap() );
|
||||
TEST( a->GetThermalSpokeWidth(), b->GetThermalSpokeWidth() );
|
||||
TEST( a->GetThermalSpokeAngle(), b->GetThermalSpokeAngle() );
|
||||
TEST( a->GetThermalSpokeAngle().AsTenthsOfADegree(), b->GetThermalSpokeAngle().AsTenthsOfADegree() );
|
||||
TEST( a->GetCustomShapeInZoneOpt(), b->GetCustomShapeInZoneOpt() );
|
||||
|
||||
TEST( a->GetPrimitives().size(), b->GetPrimitives().size() );
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2011-2013 Lorenzo Marcantonio <l.marcantonio@logossrl.com>
|
||||
* Copyright (C) 2004-2017 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2004-2022 KiCad Developers, see change_log.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -126,13 +126,17 @@ static void build_pad_testpoints( BOARD *aPcb, std::vector <D356_RECORD>& aRecor
|
|||
else
|
||||
rk.y_size = pad->GetSize().y;
|
||||
|
||||
rk.rotation = -KiROUND( pad->GetOrientation() ) / 10;
|
||||
if( rk.rotation < 0 ) rk.rotation += 360;
|
||||
rk.rotation = - pad->GetOrientation().AsDegrees();
|
||||
|
||||
if( rk.rotation < 0 )
|
||||
rk.rotation += 360;
|
||||
|
||||
// the value indicates which sides are *not* accessible
|
||||
rk.soldermask = 3;
|
||||
|
||||
if( pad->GetLayerSet()[F_Mask] )
|
||||
rk.soldermask &= ~1;
|
||||
|
||||
if( pad->GetLayerSet()[B_Mask] )
|
||||
rk.soldermask &= ~2;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2020 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2015-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -402,7 +402,7 @@ std::string PLACE_FILE_EXPORTER::GenReportData()
|
|||
pad->GetPos0().y * conv_unit,
|
||||
pad->GetSize().x * conv_unit,
|
||||
pad->GetSize().y * conv_unit,
|
||||
( pad->GetOrientation() - footprint->GetOrientation()) / 10.0 );
|
||||
pad->GetOrientation().AsDegrees() - ( footprint->GetOrientation() / 10.0 ) );
|
||||
buffer += line;
|
||||
|
||||
sprintf( line, "drill %9.6f\n", pad->GetDrillSize().x * conv_unit );
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (C) 2016 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
|
||||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -591,7 +591,7 @@ static void CreatePadsShapesSection( FILE* aFile, BOARD* aPcb )
|
|||
VECTOR2I padOffset( 0, 0 );
|
||||
|
||||
TransformRoundChamferedRectToPolygon( outline, padOffset, pad->GetSize(),
|
||||
pad->GetOrientation(),
|
||||
pad->GetOrientation().AsTenthsOfADegree(),
|
||||
pad->GetRoundRectCornerRadius(),
|
||||
pad->GetChamferRectRatio(),
|
||||
pad->GetChamferPositions(), 0, maxError,
|
||||
|
@ -828,7 +828,7 @@ static void CreateShapesSection( FILE* aFile, BOARD* aPcb )
|
|||
pins.insert( pinname );
|
||||
}
|
||||
|
||||
double orient = pad->GetOrientation() - footprint->GetOrientation();
|
||||
double orient = pad->GetOrientation().AsTenthsOfADegree() - footprint->GetOrientation();
|
||||
NORMALIZE_ANGLE_POS( orient );
|
||||
|
||||
// Bottom side footprints use the flipped padstack
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019 CERN
|
||||
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -232,7 +233,7 @@ HYPERLYNX_PAD_STACK::HYPERLYNX_PAD_STACK( BOARD* aBoard, const PAD* aPad )
|
|||
m_board = aBoard;
|
||||
m_sx = aPad->GetSize().x;
|
||||
m_sy = aPad->GetSize().y;
|
||||
m_angle = 180.0 - ( aPad->GetOrientation() / 10.0 );
|
||||
m_angle = 180.0 - aPad->GetOrientation().AsDegrees();
|
||||
|
||||
if( m_angle < 0.0 )
|
||||
{
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
/**
|
||||
* @file export_idf.cpp
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013 Cirilo Bernardo
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -357,7 +353,7 @@ static void idf_export_footprint( BOARD* aPcb, FOOTPRINT* aFootprint, IDF3_BOARD
|
|||
// NOTE: The orientation of footprints and pads have
|
||||
// the opposite sense due to KiCad drawing on a
|
||||
// screen with a LH coordinate system
|
||||
double angle = pad->GetOrientation() / 10.0;
|
||||
double angle = pad->GetOrientation().AsDegrees();
|
||||
|
||||
// NOTE: Since this code assumes the scenario where
|
||||
// GetDrillSize().y is the length but idf_parser.cpp
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (C) 2009-2013 Lorenzo Mercantonio
|
||||
* Copyright (C) 2014-2017 Cirilo Bernardo
|
||||
* Copyright (C) 2018 Jean-Pierre Charras jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2004-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -699,17 +699,17 @@ void EXPORTER_PCB_VRML::ExportVrmlPadHole( PAD* aPad )
|
|||
if( pth )
|
||||
{
|
||||
m_holes.AddSlot( hole_x, -hole_y, hole_drill_w * 2.0 + PLATE_OFFSET,
|
||||
hole_drill_h * 2.0 + PLATE_OFFSET,
|
||||
aPad->GetOrientation()/10.0, true, true );
|
||||
hole_drill_h * 2.0 + PLATE_OFFSET,
|
||||
aPad->GetOrientation().AsDegrees(), true, true );
|
||||
|
||||
m_plated_holes.AddSlot( hole_x, -hole_y,
|
||||
hole_drill_w * 2.0, hole_drill_h * 2.0,
|
||||
aPad->GetOrientation()/10.0, true, false );
|
||||
hole_drill_w * 2.0, hole_drill_h * 2.0,
|
||||
aPad->GetOrientation().AsDegrees(), true, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_holes.AddSlot( hole_x, -hole_y, hole_drill_w * 2.0, hole_drill_h * 2.0,
|
||||
aPad->GetOrientation()/10.0, true, false );
|
||||
aPad->GetOrientation().AsDegrees(), true, false );
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2017 Jean_Pierre Charras <jp.charras at wanadoo.fr>
|
||||
* Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -141,7 +141,7 @@ void GENDRILL_WRITER_BASE::buildHolesList( DRILL_LAYER_PAIR aLayerPair,
|
|||
? HOLE_ATTRIBUTE::HOLE_MECHANICAL
|
||||
: HOLE_ATTRIBUTE::HOLE_PAD;
|
||||
new_hole.m_Tool_Reference = -1; // Flag is: Not initialized
|
||||
new_hole.m_Hole_Orient = pad->GetOrientation();
|
||||
new_hole.m_Hole_Orient = pad->GetOrientation().AsTenthsOfADegree();
|
||||
new_hole.m_Hole_Shape = 0; // hole shape: round
|
||||
new_hole.m_Hole_Diameter = std::min( pad->GetDrillSize().x, pad->GetDrillSize().y );
|
||||
new_hole.m_Hole_Size.x = new_hole.m_Hole_Size.y = new_hole.m_Hole_Diameter;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2015 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -1717,7 +1717,7 @@ void FOOTPRINT::SetOrientation( double aNewAngle )
|
|||
|
||||
for( PAD* pad : m_pads )
|
||||
{
|
||||
pad->SetOrientation( pad->GetOrientation() + angleChange );
|
||||
pad->SetOrientation( pad->GetOrientation() + EDA_ANGLE( angleChange, TENTHS_OF_A_DEGREE_T ) );
|
||||
pad->SetDrawCoord();
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -61,7 +61,7 @@ PAD::PAD( FOOTPRINT* parent ) :
|
|||
{
|
||||
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_orient = ANGLE_0; // Pad rotation.
|
||||
m_lengthPadToDie = 0;
|
||||
|
||||
if( m_parent && m_parent->Type() == PCB_FOOTPRINT_T )
|
||||
|
@ -87,7 +87,7 @@ PAD::PAD( FOOTPRINT* parent ) :
|
|||
|
||||
m_zoneConnection = ZONE_CONNECTION::INHERITED; // Use parent setting by default
|
||||
m_thermalSpokeWidth = 0; // Use parent setting by default
|
||||
m_thermalSpokeAngle = 450.0; // Default for circular pads
|
||||
m_thermalSpokeAngle = ANGLE_45; // Default for circular pads
|
||||
m_thermalGap = 0; // Use parent setting by default
|
||||
|
||||
m_customShapeClearanceArea = CUST_PAD_SHAPE_IN_ZONE_OUTLINE;
|
||||
|
@ -417,7 +417,7 @@ void PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const
|
|||
corners.Append( half_size.x - trap_delta.y, -half_size.y + trap_delta.x );
|
||||
corners.Append( -half_size.x + trap_delta.y, -half_size.y - trap_delta.x );
|
||||
|
||||
corners.Rotate( -DECIDEG2RAD( m_orient ) );
|
||||
corners.Rotate( - m_orient.AsRadians() );
|
||||
corners.Move( shapePos );
|
||||
|
||||
// GAL renders rectangles faster than 4-point polygons so it's worth checking if our
|
||||
|
@ -462,7 +462,8 @@ void PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const
|
|||
{
|
||||
SHAPE_POLY_SET outline;
|
||||
|
||||
TransformRoundChamferedRectToPolygon( outline, shapePos, GetSize(), m_orient,
|
||||
TransformRoundChamferedRectToPolygon( outline, shapePos, GetSize(),
|
||||
m_orient.AsTenthsOfADegree(),
|
||||
GetRoundRectCornerRadius(), GetChamferRectRatio(),
|
||||
GetChamferPositions(), 0, maxError, ERROR_INSIDE );
|
||||
|
||||
|
@ -482,7 +483,7 @@ void PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const
|
|||
{
|
||||
for( SHAPE* shape : primitive->MakeEffectiveShapes() )
|
||||
{
|
||||
shape->Rotate( -DECIDEG2RAD( m_orient ) );
|
||||
shape->Rotate( - m_orient.AsRadians() );
|
||||
shape->Move( shapePos );
|
||||
add( shape );
|
||||
}
|
||||
|
@ -609,10 +610,10 @@ void PAD::SetProperty( PAD_PROP aProperty )
|
|||
}
|
||||
|
||||
|
||||
void PAD::SetOrientation( double aAngle )
|
||||
void PAD::SetOrientation( const EDA_ANGLE& aAngle )
|
||||
{
|
||||
NORMALIZE_ANGLE_POS( aAngle );
|
||||
m_orient = aAngle;
|
||||
m_orient.Normalize();
|
||||
|
||||
SetDirty();
|
||||
}
|
||||
|
@ -1093,7 +1094,8 @@ void PAD::Rotate( const VECTOR2I& aRotCentre, double aAngle )
|
|||
{
|
||||
RotatePoint( m_pos, aRotCentre, aAngle );
|
||||
|
||||
m_orient = NormalizeAngle360Min( m_orient + aAngle );
|
||||
m_orient += EDA_ANGLE( aAngle, TENTHS_OF_A_DEGREE_T );
|
||||
m_orient.Normalize();
|
||||
|
||||
SetLocalCoord();
|
||||
|
||||
|
@ -1392,23 +1394,20 @@ void PAD::ImportSettingsFrom( const PAD& aMasterPad )
|
|||
SetAttribute( aMasterPad.GetAttribute() );
|
||||
SetProperty( aMasterPad.GetProperty() );
|
||||
|
||||
// I am not sure the m_LengthPadToDie must be imported, because this is
|
||||
// a parameter really specific to a given pad (JPC).
|
||||
// So this is currently non imported
|
||||
// I am not sure the m_LengthPadToDie should be imported, because this is a parameter
|
||||
// really specific to a given pad (JPC).
|
||||
#if 0
|
||||
SetPadToDieLength( aMasterPad.GetPadToDieLength() );
|
||||
#endif
|
||||
|
||||
// The pad orientation, for historical reasons is the
|
||||
// pad rotation + parent rotation.
|
||||
// So we have to manage this parent rotation
|
||||
double pad_rot = aMasterPad.GetOrientation();
|
||||
// The pad orientation, for historical reasons is the pad rotation + parent rotation.
|
||||
EDA_ANGLE pad_rot = aMasterPad.GetOrientation();
|
||||
|
||||
if( aMasterPad.GetParent() )
|
||||
pad_rot -= aMasterPad.GetParent()->GetOrientation();
|
||||
pad_rot -= EDA_ANGLE( aMasterPad.GetParent()->GetOrientation(), TENTHS_OF_A_DEGREE_T );
|
||||
|
||||
if( GetParent() )
|
||||
pad_rot += GetParent()->GetOrientation();
|
||||
pad_rot += EDA_ANGLE( GetParent()->GetOrientation(), TENTHS_OF_A_DEGREE_T );
|
||||
|
||||
SetOrientation( pad_rot );
|
||||
|
||||
|
@ -1440,8 +1439,7 @@ void PAD::ImportSettingsFrom( const PAD& aMasterPad )
|
|||
{
|
||||
case PAD_ATTRIB::SMD:
|
||||
case PAD_ATTRIB::CONN:
|
||||
// These pads do not have hole (they are expected to be only on one
|
||||
// external copper layer)
|
||||
// These pads do not have a hole (they are expected to be on one external copper layer)
|
||||
SetDrillSize( VECTOR2I( 0, 0 ) );
|
||||
break;
|
||||
|
||||
|
@ -1474,7 +1472,7 @@ void PAD::SwapData( BOARD_ITEM* aImage )
|
|||
{
|
||||
assert( aImage->Type() == PCB_PAD_T );
|
||||
|
||||
std::swap( *((PAD*) this), *((PAD*) aImage) );
|
||||
std::swap( *this, *static_cast<PAD*>( aImage ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1506,9 +1504,8 @@ void PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
|||
// This minimal value is mainly for very small pads, like SM0402.
|
||||
// Most of time pads are using the segment count given by aError value.
|
||||
const int pad_min_seg_per_circle_count = 16;
|
||||
double angle = m_orient;
|
||||
int dx = m_size.x / 2;
|
||||
int dy = m_size.y / 2;
|
||||
int dx = m_size.x / 2;
|
||||
int dy = m_size.y / 2;
|
||||
|
||||
VECTOR2I padShapePos = ShapePos(); // Note: for pad having a shape offset,
|
||||
// the pad position is NOT the shape position
|
||||
|
@ -1528,7 +1525,7 @@ void PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
|||
int half_width = std::min( dx, dy );
|
||||
VECTOR2I delta( dx - half_width, dy - half_width );
|
||||
|
||||
RotatePoint( delta, angle );
|
||||
RotatePoint( delta, m_orient );
|
||||
|
||||
TransformOvalToPolygon( aCornerBuffer, padShapePos - delta, padShapePos + delta,
|
||||
( half_width + aClearanceValue ) * 2, aError, aErrorLoc,
|
||||
|
@ -1544,8 +1541,8 @@ void PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
|||
int ddy = GetShape() == PAD_SHAPE::TRAPEZOID ? m_deltaSize.y / 2 : 0;
|
||||
|
||||
SHAPE_POLY_SET outline;
|
||||
TransformTrapezoidToPolygon( outline, padShapePos, m_size, angle, ddx, ddy,
|
||||
aClearanceValue, aError, aErrorLoc );
|
||||
TransformTrapezoidToPolygon( outline, padShapePos, m_size, m_orient.AsTenthsOfADegree(),
|
||||
ddx, ddy, aClearanceValue, aError, aErrorLoc );
|
||||
aCornerBuffer.Append( outline );
|
||||
break;
|
||||
}
|
||||
|
@ -1556,7 +1553,8 @@ void PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
|||
bool doChamfer = GetShape() == PAD_SHAPE::CHAMFERED_RECT;
|
||||
|
||||
SHAPE_POLY_SET outline;
|
||||
TransformRoundChamferedRectToPolygon( outline, padShapePos, m_size, angle,
|
||||
TransformRoundChamferedRectToPolygon( outline, padShapePos, m_size,
|
||||
m_orient.AsTenthsOfADegree(),
|
||||
GetRoundRectCornerRadius(),
|
||||
doChamfer ? GetChamferRectRatio() : 0,
|
||||
doChamfer ? GetChamferPositions() : 0,
|
||||
|
@ -1569,7 +1567,7 @@ void PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
|||
{
|
||||
SHAPE_POLY_SET outline;
|
||||
MergePrimitivesAsPolygon( &outline, aErrorLoc );
|
||||
outline.Rotate( -DECIDEG2RAD( m_orient ) );
|
||||
outline.Rotate( - m_orient.AsRadians() );
|
||||
outline.Move( VECTOR2I( m_pos ) );
|
||||
|
||||
if( aClearanceValue )
|
||||
|
@ -1677,7 +1675,7 @@ static struct PAD_DESC
|
|||
&PAD::SetThermalSpokeWidth, &PAD::GetThermalSpokeWidth,
|
||||
PROPERTY_DISPLAY::DISTANCE ) );
|
||||
propMgr.AddProperty( new PROPERTY<PAD, double>( _HKI( "Thermal Relief Spoke Angle" ),
|
||||
&PAD::SetThermalSpokeAngle, &PAD::GetThermalSpokeAngle,
|
||||
&PAD::SetThermalSpokeAngleDegrees, &PAD::GetThermalSpokeAngleDegrees,
|
||||
PROPERTY_DISPLAY::DEGREE ) );
|
||||
propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Thermal Relief Gap" ),
|
||||
&PAD::SetThermalGap, &PAD::GetThermalGap,
|
||||
|
|
58
pcbnew/pad.h
58
pcbnew/pad.h
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -29,6 +29,7 @@
|
|||
#include <zones.h>
|
||||
#include <board_connected_item.h>
|
||||
#include <convert_to_biu.h>
|
||||
#include <eda_angle.h>
|
||||
#include <geometry/shape_poly_set.h>
|
||||
#include <geometry/shape_compound.h>
|
||||
#include <pad_shapes.h>
|
||||
|
@ -331,24 +332,25 @@ public:
|
|||
/**
|
||||
* Set the rotation angle of the pad.
|
||||
*
|
||||
* If \a aAngle is outside of 0 - 3600, then it will be normalized.
|
||||
*
|
||||
* @param aAngle in tenths of degrees.
|
||||
* If \a aAngle is outside of 0 - 360, then it will be normalized.
|
||||
*/
|
||||
void SetOrientation( double aAngle );
|
||||
void SetOrientation( const EDA_ANGLE& aAngle );
|
||||
|
||||
|
||||
/**
|
||||
* Set orientation in degrees.
|
||||
* Return the rotation angle of the pad.
|
||||
*/
|
||||
void SetOrientationDegrees( double aOrientation ) { SetOrientation( aOrientation*10.0 ); }
|
||||
EDA_ANGLE GetOrientation() const { return m_orient; }
|
||||
|
||||
/**
|
||||
* Return the rotation angle of the pad in a variety of units (the basic call returns
|
||||
* tenths of degrees).
|
||||
*/
|
||||
double GetOrientation() const { return m_orient; }
|
||||
double GetOrientationDegrees() const { return m_orient/10.0; }
|
||||
double GetOrientationRadians() const { return m_orient*M_PI/1800; }
|
||||
// For property system
|
||||
void SetOrientationDegrees( double aOrientation )
|
||||
{
|
||||
SetOrientation( EDA_ANGLE( aOrientation, DEGREES_T ) );
|
||||
}
|
||||
double GetOrientationDegrees() const
|
||||
{
|
||||
return m_orient.AsDegrees();
|
||||
}
|
||||
|
||||
void SetDrillShape( PAD_DRILL_SHAPE_T aShape ) { m_drillShape = aShape; m_shapesDirty = true; }
|
||||
PAD_DRILL_SHAPE_T GetDrillShape() const { return m_drillShape; }
|
||||
|
@ -487,12 +489,22 @@ public:
|
|||
int GetLocalSpokeWidthOverride( wxString* aSource = nullptr ) const;
|
||||
|
||||
/**
|
||||
* The orientation of the thermal spokes (in decidegrees). 450 will produce an X (the
|
||||
* default for circular pads and circular-anchored custom shaped pads), while 900 will
|
||||
* produce a + (the default for all other shapes).
|
||||
* The orientation of the thermal spokes. 45° will produce an X (the default for circular
|
||||
* pads and circular-anchored custom shaped pads), while 90° will produce a + (the default
|
||||
* for all other shapes).
|
||||
*/
|
||||
void SetThermalSpokeAngle( double aAngle ) { m_thermalSpokeAngle = aAngle; }
|
||||
double GetThermalSpokeAngle() const { return m_thermalSpokeAngle; }
|
||||
void SetThermalSpokeAngle( const EDA_ANGLE& aAngle ) { m_thermalSpokeAngle = aAngle; }
|
||||
EDA_ANGLE GetThermalSpokeAngle() const { return m_thermalSpokeAngle; }
|
||||
|
||||
// For property system
|
||||
void SetThermalSpokeAngleDegrees( double aAngle )
|
||||
{
|
||||
m_thermalSpokeAngle = EDA_ANGLE( aAngle, DEGREES_T );
|
||||
}
|
||||
double GetThermalSpokeAngleDegrees() const
|
||||
{
|
||||
return m_thermalSpokeAngle.AsDegrees();
|
||||
}
|
||||
|
||||
void SetThermalGap( int aGap ) { m_thermalGap = aGap; }
|
||||
int GetThermalGap() const { return m_thermalGap; }
|
||||
|
@ -737,14 +749,14 @@ private:
|
|||
// one end and half expands the other. It is only valid
|
||||
// to have a single axis be non-0.
|
||||
|
||||
VECTOR2I m_pos0; // Initial Pad position (i.e. pad position relative to the
|
||||
VECTOR2I m_pos0; // Initial Pad position (i.e. pad position relative to the
|
||||
// footprint anchor, orientation 0)
|
||||
|
||||
PAD_ATTRIB m_attribute; // PAD_ATTRIB_NORMAL, PAD_ATTRIB::SMD, PAD_ATTRIB::CONN,
|
||||
// PAD_ATTRIB::NPTH
|
||||
PAD_PROP m_property; // Property in fab files (BGA, FIDUCIAL, TESTPOINT, etc.)
|
||||
|
||||
double m_orient; // in 1/10 degrees
|
||||
EDA_ANGLE m_orient;
|
||||
|
||||
int m_lengthPadToDie; // Length net from pad to die, inside the package
|
||||
|
||||
|
@ -772,8 +784,8 @@ private:
|
|||
|
||||
ZONE_CONNECTION m_zoneConnection; // No connection, thermal relief, etc.
|
||||
int m_thermalSpokeWidth; // Thermal spoke width.
|
||||
double m_thermalSpokeAngle; // Rotation of the spokes, in deci-degrees. 450
|
||||
// will produce an X, while 900 will produce a +.
|
||||
EDA_ANGLE m_thermalSpokeAngle; // Rotation of the spokes. 45° will produce an X,
|
||||
// while 90° will produce a +.
|
||||
int m_thermalGap;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -418,7 +418,7 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||
// and orientation 0. The actual pos and rotation will be taken in account
|
||||
// later by the plot function
|
||||
dummy.SetPosition( VECTOR2I( 0, 0 ) );
|
||||
dummy.SetOrientation( 0 );
|
||||
dummy.SetOrientation( ANGLE_0 );
|
||||
SHAPE_POLY_SET outline;
|
||||
int maxError = aBoard->GetDesignSettings().m_MaxError;
|
||||
int numSegs = GetArcToSegmentCount( mask_clearance, maxError, 360.0 );
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -224,18 +224,21 @@ void BRDITEMS_PLOTTER::PlotPad( const PAD* aPad, const COLOR4D& aColor, OUTLINE_
|
|||
break;
|
||||
|
||||
case PAD_SHAPE::OVAL:
|
||||
m_plotter->FlashPadOval( shape_pos, aPad->GetSize(), aPad->GetOrientation(), aPlotMode,
|
||||
m_plotter->FlashPadOval( shape_pos, aPad->GetSize(),
|
||||
aPad->GetOrientation().AsTenthsOfADegree(), aPlotMode,
|
||||
&gbr_metadata );
|
||||
break;
|
||||
|
||||
case PAD_SHAPE::RECT:
|
||||
m_plotter->FlashPadRect( shape_pos, aPad->GetSize(), aPad->GetOrientation(), aPlotMode,
|
||||
m_plotter->FlashPadRect( shape_pos, aPad->GetSize(),
|
||||
aPad->GetOrientation().AsTenthsOfADegree(), aPlotMode,
|
||||
&gbr_metadata );
|
||||
break;
|
||||
|
||||
case PAD_SHAPE::ROUNDRECT:
|
||||
m_plotter->FlashPadRoundRect( shape_pos, aPad->GetSize(), aPad->GetRoundRectCornerRadius(),
|
||||
aPad->GetOrientation(), aPlotMode, &gbr_metadata );
|
||||
aPad->GetOrientation().AsTenthsOfADegree(), aPlotMode,
|
||||
&gbr_metadata );
|
||||
break;
|
||||
|
||||
case PAD_SHAPE::TRAPEZOID:
|
||||
|
@ -254,8 +257,8 @@ void BRDITEMS_PLOTTER::PlotPad( const PAD* aPad, const COLOR4D& aColor, OUTLINE_
|
|||
coord[2] = VECTOR2I( half_size.x - trap_delta.y, -half_size.y + trap_delta.x );
|
||||
coord[3] = VECTOR2I( -half_size.x + trap_delta.y, -half_size.y - trap_delta.x );
|
||||
|
||||
m_plotter->FlashPadTrapez( shape_pos, coord, aPad->GetOrientation(), aPlotMode,
|
||||
&gbr_metadata );
|
||||
m_plotter->FlashPadTrapez( shape_pos, coord, aPad->GetOrientation().AsTenthsOfADegree(),
|
||||
aPlotMode, &gbr_metadata );
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -263,11 +266,14 @@ void BRDITEMS_PLOTTER::PlotPad( const PAD* aPad, const COLOR4D& aColor, OUTLINE_
|
|||
if( m_plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
|
||||
{
|
||||
static_cast<GERBER_PLOTTER*>( m_plotter )->FlashPadChamferRoundRect(
|
||||
shape_pos, aPad->GetSize(),
|
||||
aPad->GetRoundRectCornerRadius(),
|
||||
aPad->GetChamferRectRatio(),
|
||||
aPad->GetChamferPositions(),
|
||||
aPad->GetOrientation(), aPlotMode, &gbr_metadata );
|
||||
shape_pos,
|
||||
aPad->GetSize(),
|
||||
aPad->GetRoundRectCornerRadius(),
|
||||
aPad->GetChamferRectRatio(),
|
||||
aPad->GetChamferPositions(),
|
||||
aPad->GetOrientation().AsTenthsOfADegree(),
|
||||
aPlotMode,
|
||||
&gbr_metadata );
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -280,8 +286,9 @@ void BRDITEMS_PLOTTER::PlotPad( const PAD* aPad, const COLOR4D& aColor, OUTLINE_
|
|||
|
||||
if( polygons->OutlineCount() )
|
||||
{
|
||||
m_plotter->FlashPadCustom( shape_pos, aPad->GetSize(), aPad->GetOrientation(),
|
||||
polygons.get(), aPlotMode, &gbr_metadata );
|
||||
m_plotter->FlashPadCustom( shape_pos, aPad->GetSize(),
|
||||
aPad->GetOrientation().AsTenthsOfADegree(), polygons.get(),
|
||||
aPlotMode, &gbr_metadata );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1125,7 +1132,8 @@ void BRDITEMS_PLOTTER::PlotDrillMarks()
|
|||
continue;
|
||||
|
||||
plotOneDrillMark( pad->GetDrillShape(), pad->GetPosition(), pad->GetDrillSize(),
|
||||
pad->GetSize(), pad->GetOrientation(), smallDrill );
|
||||
pad->GetSize(), pad->GetOrientation().AsTenthsOfADegree(),
|
||||
smallDrill );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020-2021 Roberto Fernandez Bautista <roberto.fer.bau@gmail.com>
|
||||
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
|
@ -1181,7 +1181,7 @@ PAD* CADSTAR_PCB_ARCHIVE_LOADER::getKiCadPad( const COMPONENT_PAD& aCadstarPad,
|
|||
padShape->SetPolyShape( padOutline );
|
||||
padShape->SetStroke( STROKE_PARAMS( 0 ) );
|
||||
padShape->Move( padOffset - drillOffset );
|
||||
padShape->Rotate( wxPoint( 0, 0 ),
|
||||
padShape->Rotate( VECTOR2I( 0, 0 ),
|
||||
1800.0 - getAngleTenthDegree( csPadcode.SlotOrientation ) );
|
||||
|
||||
SHAPE_POLY_SET editedPadOutline = padShape->GetPolyShape();
|
||||
|
@ -1221,14 +1221,14 @@ PAD* CADSTAR_PCB_ARCHIVE_LOADER::getKiCadPad( const COMPONENT_PAD& aCadstarPad,
|
|||
pad->SetOffset( drillOffset );
|
||||
}
|
||||
|
||||
double padOrientation = getAngleTenthDegree( aCadstarPad.OrientAngle )
|
||||
+ getAngleTenthDegree( csPadcode.Shape.OrientAngle );
|
||||
EDA_ANGLE padOrientation = getAngle( aCadstarPad.OrientAngle )
|
||||
+ getAngle( csPadcode.Shape.OrientAngle );
|
||||
|
||||
RotatePoint( padOffset, padOrientation );
|
||||
RotatePoint( drillOffset, padOrientation );
|
||||
pad->SetPos0( getKiCadPoint( aCadstarPad.Position ) - aParent->GetPosition() - padOffset
|
||||
- drillOffset );
|
||||
pad->SetOrientation( padOrientation + getAngleTenthDegree( csPadcode.SlotOrientation ) );
|
||||
pad->SetOrientation( padOrientation + getAngle( csPadcode.SlotOrientation ) );
|
||||
|
||||
//TODO handle csPadcode.Reassigns when KiCad supports full padstacks
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020-2021 Roberto Fernandez Bautista <roberto.fer.bau@gmail.com>
|
||||
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
|
@ -459,6 +459,26 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @param aCadstarAngle
|
||||
* @return
|
||||
*/
|
||||
EDA_ANGLE getAngle( const long long& aCadstarAngle )
|
||||
{
|
||||
// CADSTAR v6 (which outputted Format Version 8) and earlier versions used 1/10 degree
|
||||
// as the unit for angles/orientations. It is assumed that CADSTAR version 7 (i.e. Format
|
||||
// Version 9 and later) is the version that introduced 1/1000 degree for angles.
|
||||
if( Header.Format.Version > 8 )
|
||||
{
|
||||
return EDA_ANGLE( aCadstarAngle / 1000.0, DEGREES_T );
|
||||
}
|
||||
else
|
||||
{
|
||||
return EDA_ANGLE( (int) aCadstarAngle, TENTHS_OF_A_DEGREE_T );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @param aCadstarAngle
|
||||
|
|
|
@ -1907,9 +1907,7 @@ void EAGLE_PLUGIN::packagePad( FOOTPRINT* aFootprint, wxXmlNode* aTree )
|
|||
}
|
||||
|
||||
if( e.rot )
|
||||
{
|
||||
pad->SetOrientation( e.rot->degrees * 10 );
|
||||
}
|
||||
pad->SetOrientation( EDA_ANGLE( e.rot->degrees, DEGREES_T ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -2378,7 +2376,7 @@ void EAGLE_PLUGIN::packageSMD( FOOTPRINT* aFootprint, wxXmlNode* aTree ) const
|
|||
}
|
||||
|
||||
if( e.rot )
|
||||
pad->SetOrientation( e.rot->degrees * 10 );
|
||||
pad->SetOrientation( EDA_ANGLE( e.rot->degrees, DEGREES_T ) );
|
||||
|
||||
pad->SetLocalSolderPasteMargin( -eagleClamp( m_rules->mlMinCreamFrame,
|
||||
(int) ( m_rules->mvCreamFrame * minPadSize ),
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020 BeagleBoard Foundation
|
||||
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Author: Seth Hillbrand <hillbrand@kipro-pcb.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -2407,9 +2407,9 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
|
|||
newpad->SetLocalCoord();
|
||||
|
||||
if( src->mirror )
|
||||
newpad->SetOrientation( ( -src->rotate + pin->rotation ) * 10.0 );
|
||||
newpad->SetOrientation( EDA_ANGLE( -src->rotate + pin->rotation, DEGREES_T ) );
|
||||
else
|
||||
newpad->SetOrientation( ( src->rotate - pin->rotation ) * 10.0 );
|
||||
newpad->SetOrientation( EDA_ANGLE( src->rotate - pin->rotation, DEGREES_T ) );
|
||||
|
||||
fp->Add( newpad, ADD_MODE::APPEND );
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -585,9 +585,9 @@ FOOTPRINT* GPCB_FPL_CACHE::parseFOOTPRINT( LINE_READER* aLineReader )
|
|||
pad->SetLocalSolderMaskMargin( maskMargin );
|
||||
}
|
||||
|
||||
// Negate angle (due to Y reversed axis) and convert it to internal units
|
||||
angle = - RAD2DECIDEG( angle );
|
||||
pad->SetOrientation( KiROUND( angle ) );
|
||||
// Negate angle (due to Y reversed axis)
|
||||
EDA_ANGLE orient( -angle, RADIANS_T );
|
||||
pad->SetOrientation( orient );
|
||||
|
||||
VECTOR2I padPos( ( x1 + x2 ) / 2, ( y1 + y2 ) / 2 );
|
||||
|
||||
|
|
|
@ -4237,11 +4237,11 @@ PAD* PCB_PARSER::parsePAD( FOOTPRINT* aParent )
|
|||
}
|
||||
|
||||
if( pad->GetShape() == PAD_SHAPE::CIRCLE )
|
||||
pad->SetThermalSpokeAngle( 450 );
|
||||
pad->SetThermalSpokeAngle( ANGLE_45 );
|
||||
else if( pad->GetShape() == PAD_SHAPE::CUSTOM && pad->GetAnchorPadShape() == PAD_SHAPE::CIRCLE )
|
||||
pad->SetThermalSpokeAngle( 450 );
|
||||
pad->SetThermalSpokeAngle( ANGLE_45 );
|
||||
else
|
||||
pad->SetThermalSpokeAngle( 900 );
|
||||
pad->SetThermalSpokeAngle( ANGLE_90 );
|
||||
|
||||
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||
{
|
||||
|
@ -4273,7 +4273,7 @@ PAD* PCB_PARSER::parsePAD( FOOTPRINT* aParent )
|
|||
|
||||
if( token == T_NUMBER )
|
||||
{
|
||||
pad->SetOrientation( parseAngle() );
|
||||
pad->SetOrientation( EDA_ANGLE( parseAngle(), TENTHS_OF_A_DEGREE_T ) );
|
||||
NeedRIGHT();
|
||||
}
|
||||
else if( token != T_RIGHT )
|
||||
|
@ -4437,7 +4437,7 @@ PAD* PCB_PARSER::parsePAD( FOOTPRINT* aParent )
|
|||
break;
|
||||
|
||||
case T_thermal_bridge_angle:
|
||||
pad->SetThermalSpokeAngle( parseAngle( "thermal spoke angle value" ) );
|
||||
pad->SetThermalSpokeAngle( EDA_ANGLE( parseAngle( "thermal spoke angle value" ), TENTHS_OF_A_DEGREE_T ) );
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
|
|
|
@ -1441,8 +1441,8 @@ void PCB_PLUGIN::format( const PAD* aPad, int aNestLevel ) const
|
|||
|
||||
m_out->Print( 0, " (at %s", FormatInternalUnits( aPad->GetPos0() ).c_str() );
|
||||
|
||||
if( aPad->GetOrientation() != 0.0 )
|
||||
m_out->Print( 0, " %s", FormatAngle( aPad->GetOrientation() ).c_str() );
|
||||
if( !aPad->GetOrientation().IsZero() )
|
||||
m_out->Print( 0, " %s", FormatAngle( aPad->GetOrientation().AsTenthsOfADegree() ).c_str() );
|
||||
|
||||
m_out->Print( 0, ")" );
|
||||
|
||||
|
@ -1591,11 +1591,11 @@ void PCB_PLUGIN::format( const PAD* aPad, int aNestLevel ) const
|
|||
FormatInternalUnits( aPad->GetThermalSpokeWidth() ).c_str() );
|
||||
}
|
||||
|
||||
if( ( aPad->GetShape() == PAD_SHAPE::CIRCLE && aPad->GetThermalSpokeAngle() != 450.0 )
|
||||
|| ( aPad->GetShape() != PAD_SHAPE::CIRCLE && aPad->GetThermalSpokeAngle() != 900.0 ) )
|
||||
if( ( aPad->GetShape() == PAD_SHAPE::CIRCLE && aPad->GetThermalSpokeAngle() != ANGLE_45 )
|
||||
|| ( aPad->GetShape() != PAD_SHAPE::CIRCLE && aPad->GetThermalSpokeAngle() != ANGLE_90 ) )
|
||||
{
|
||||
StrPrintf( &output, " (thermal_bridge_angle %s)",
|
||||
FormatAngle( aPad->GetThermalSpokeAngle() ).c_str() );
|
||||
FormatAngle( aPad->GetThermalSpokeAngle().AsTenthsOfADegree() ).c_str() );
|
||||
}
|
||||
|
||||
if( aPad->GetThermalGap() != 0 )
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2007-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2019 Jean-Pierre Charras, jp.charras@wanadoo.fr
|
||||
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -1376,7 +1376,7 @@ void LEGACY_PLUGIN::loadPAD( FOOTPRINT* aFootprint )
|
|||
pad->SetShape( static_cast<PAD_SHAPE>( padshape ) );
|
||||
pad->SetSize( wxSize( size_x, size_y ) );
|
||||
pad->SetDelta( wxSize( delta_x, delta_y ) );
|
||||
pad->SetOrientation( orient );
|
||||
pad->SetOrientation( EDA_ANGLE( orient, TENTHS_OF_A_DEGREE_T ) );
|
||||
}
|
||||
else if( TESTLINE( "Dr" ) ) // (Dr)ill
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2007, 2008 Lubo Racko <developer@lura.sk>
|
||||
* Copyright (C) 2007, 2008, 2012-2013 Alexander Lunev <al.lunev@yahoo.com>
|
||||
* Copyright (C) 2012-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2012-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -288,7 +288,7 @@ void PCB_PAD::AddToFootprint( FOOTPRINT* aFootprint, int aRotation, bool aEncaps
|
|||
|
||||
pad->SetSize( VECTOR2I( width, height ) );
|
||||
pad->SetDelta( VECTOR2I( 0, 0 ) );
|
||||
pad->SetOrientation( m_rotation + aRotation );
|
||||
pad->SetOrientation( EDA_ANGLE( m_rotation + aRotation, TENTHS_OF_A_DEGREE_T ) );
|
||||
|
||||
pad->SetDrillShape( PAD_DRILL_SHAPE_CIRCLE );
|
||||
pad->SetOffset( VECTOR2I( 0, 0 ) );
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* KiRouter - a push-and-(sometimes-)shove PCB router
|
||||
*
|
||||
* Copyright (C) 2013-2016 CERN
|
||||
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2016-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
|
@ -930,7 +930,7 @@ std::unique_ptr<PNS::SOLID> PNS_KICAD_IFACE_BASE::syncPad( PAD* aPad )
|
|||
solid->SetNet( aPad->GetNetCode() );
|
||||
solid->SetParent( aPad );
|
||||
solid->SetPadToDie( aPad->GetPadToDieLength() );
|
||||
solid->SetOrientation( aPad->GetOrientation() );
|
||||
solid->SetOrientation( aPad->GetOrientation().AsTenthsOfADegree() );
|
||||
|
||||
VECTOR2I wx_c = aPad->ShapePos();
|
||||
VECTOR2I offset = aPad->GetOffset();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2017-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -178,7 +178,8 @@ static void doPushPadProperties( BOARD& board, const PAD& aSrcPad, BOARD_COMMIT&
|
|||
{
|
||||
const FOOTPRINT* refFootprint = aSrcPad.GetParent();
|
||||
|
||||
double pad_orient = aSrcPad.GetOrientation() - refFootprint->GetOrientation();
|
||||
EDA_ANGLE srcPadAngle = aSrcPad.GetOrientation()
|
||||
- EDA_ANGLE( refFootprint->GetOrientation(), TENTHS_OF_A_DEGREE_T );
|
||||
|
||||
for( FOOTPRINT* footprint : board.Footprints() )
|
||||
{
|
||||
|
@ -188,14 +189,15 @@ static void doPushPadProperties( BOARD& board, const PAD& aSrcPad, BOARD_COMMIT&
|
|||
if( footprint->GetFPID() != refFootprint->GetFPID() )
|
||||
continue;
|
||||
|
||||
for( auto pad : footprint->Pads() )
|
||||
for( PAD* pad : footprint->Pads() )
|
||||
{
|
||||
if( aPadShapeFilter && ( pad->GetShape() != aSrcPad.GetShape() ) )
|
||||
continue;
|
||||
|
||||
double currpad_orient = pad->GetOrientation() - footprint->GetOrientation();
|
||||
EDA_ANGLE padAngle = pad->GetOrientation()
|
||||
- EDA_ANGLE( footprint->GetOrientation(), TENTHS_OF_A_DEGREE_T );
|
||||
|
||||
if( aPadOrientFilter && ( currpad_orient != pad_orient ) )
|
||||
if( aPadOrientFilter && ( padAngle != srcPadAngle ) )
|
||||
continue;
|
||||
|
||||
if( aPadLayerFilter && ( pad->GetLayerSet() != aSrcPad.GetLayerSet() ) )
|
||||
|
@ -665,7 +667,7 @@ PCB_LAYER_ID PAD_TOOL::explodePad( PAD* aPad )
|
|||
|
||||
shape->SetLocalCoord();
|
||||
shape->Move( aPad->GetPosition() );
|
||||
shape->Rotate( aPad->GetPosition(), aPad->GetOrientation() );
|
||||
shape->Rotate( aPad->GetPosition(), aPad->GetOrientation().AsTenthsOfADegree() );
|
||||
shape->SetLayer( layer );
|
||||
|
||||
commit.Add( shape );
|
||||
|
@ -755,7 +757,7 @@ void PAD_TOOL::recombinePad( PAD* aPad )
|
|||
shape->SetStroke( STROKE_PARAMS( 0, PLOT_DASH_TYPE::SOLID ) );
|
||||
shape->SetPolyShape( existingOutline );
|
||||
shape->Move( - aPad->GetPosition() );
|
||||
shape->Rotate( wxPoint( 0, 0 ), - aPad->GetOrientation() );
|
||||
shape->Rotate( wxPoint( 0, 0 ), - aPad->GetOrientation().AsTenthsOfADegree() );
|
||||
|
||||
aPad->AddPrimitive( shape );
|
||||
}
|
||||
|
@ -802,7 +804,7 @@ void PAD_TOOL::recombinePad( PAD* aPad )
|
|||
}
|
||||
|
||||
pcbShape->Move( - aPad->GetPosition() );
|
||||
pcbShape->Rotate( wxPoint( 0, 0 ), - aPad->GetOrientation() );
|
||||
pcbShape->Rotate( wxPoint( 0, 0 ), - aPad->GetOrientation().AsTenthsOfADegree() );
|
||||
aPad->AddPrimitive( pcbShape );
|
||||
|
||||
fpShape->SetFlags( STRUCT_DELETED );
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013-2021 CERN
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -270,10 +270,10 @@ std::shared_ptr<EDIT_POINTS> PCB_POINT_EDITOR::makePoints( EDA_ITEM* aItem )
|
|||
case PAD_SHAPE::ROUNDRECT:
|
||||
case PAD_SHAPE::CHAMFERED_RECT:
|
||||
{
|
||||
if( (int) pad->GetOrientation() % 900 != 0 )
|
||||
if( !pad->GetOrientation().IsCardinal() )
|
||||
break;
|
||||
|
||||
if( pad->GetOrientation() == 900 || pad->GetOrientation() == 2700 )
|
||||
if( pad->GetOrientation() == ANGLE_90 || pad->GetOrientation() == ANGLE_270 )
|
||||
std::swap( halfSize.x, halfSize.y );
|
||||
|
||||
points->AddPoint( shapePos - halfSize );
|
||||
|
@ -1268,7 +1268,7 @@ void PCB_POINT_EDITOR::updateItem() const
|
|||
wxSize padSize( dist[0] + dist[2], dist[1] + dist[3] );
|
||||
VECTOR2I deltaOffset( padSize.x / 2 - dist[2], padSize.y / 2 - dist[3] );
|
||||
|
||||
if( pad->GetOrientation() == 900 || pad->GetOrientation() == 2700 )
|
||||
if( pad->GetOrientation() == ANGLE_90 || pad->GetOrientation() == ANGLE_270 )
|
||||
std::swap( padSize.x, padSize.y );
|
||||
|
||||
RotatePoint( deltaOffset, -pad->GetOrientation() );
|
||||
|
@ -1300,7 +1300,7 @@ void PCB_POINT_EDITOR::updateItem() const
|
|||
|
||||
wxSize padSize( abs( right - left ), abs( bottom - top ) );
|
||||
|
||||
if( pad->GetOrientation() == 900 || pad->GetOrientation() == 2700 )
|
||||
if( pad->GetOrientation() == ANGLE_90 || pad->GetOrientation() == ANGLE_270 )
|
||||
std::swap( padSize.x, padSize.y );
|
||||
|
||||
pad->SetSize( padSize );
|
||||
|
@ -1729,7 +1729,7 @@ void PCB_POINT_EDITOR::updatePoints()
|
|||
case PAD_SHAPE::CHAMFERED_RECT:
|
||||
{
|
||||
// Careful; pad shape and orientation are mutable...
|
||||
int target = locked || (int) pad->GetOrientation() % 900 > 0 ? 0 : 4;
|
||||
int target = locked || !pad->GetOrientation().IsCardinal() ? 0 : 4;
|
||||
|
||||
if( int( m_editPoints->PointsSize() ) != target )
|
||||
{
|
||||
|
@ -1743,7 +1743,7 @@ void PCB_POINT_EDITOR::updatePoints()
|
|||
}
|
||||
else if( target == 4 )
|
||||
{
|
||||
if( pad->GetOrientation() == 900 || pad->GetOrientation() == 2700 )
|
||||
if( pad->GetOrientation() == ANGLE_90 || pad->GetOrientation() == ANGLE_270 )
|
||||
std::swap( halfSize.x, halfSize.y );
|
||||
|
||||
m_editPoints->Point( RECT_TOP_LEFT ).SetPosition( shapePos - halfSize );
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2014-2017 CERN
|
||||
* Copyright (C) 2014-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2014-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @author Tomasz Włostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
|
@ -1350,8 +1350,8 @@ void ZONE_FILLER::buildThermalSpokes( const ZONE* aZone, PCB_LAYER_ID aLayer,
|
|||
|
||||
// Thermal spokes consist of segments from the pad center to points just outside
|
||||
// the thermal relief.
|
||||
VECTOR2I shapePos = pad->ShapePos();
|
||||
double spokesAngle = pad->GetThermalSpokeAngle();
|
||||
VECTOR2I shapePos = pad->ShapePos();
|
||||
EDA_ANGLE spokesAngle = pad->GetThermalSpokeAngle();
|
||||
|
||||
// We use the bounding-box to lay out the spokes, but for this to work the
|
||||
// bounding box has to be built at the same rotation as the spokes.
|
||||
|
@ -1403,8 +1403,8 @@ void ZONE_FILLER::buildThermalSpokes( const ZONE* aZone, PCB_LAYER_ID aLayer,
|
|||
break;
|
||||
}
|
||||
|
||||
// Rottae and move the spokes tho the right position
|
||||
spoke.Rotate( -DECIDEG2RAD( pad->GetOrientation() + spokesAngle ) );
|
||||
// Rotate and move the spokes tho the right position
|
||||
spoke.Rotate( - ( pad->GetOrientation() + spokesAngle ).AsRadians() );
|
||||
spoke.Move( shapePos );
|
||||
|
||||
spoke.SetClosed( true );
|
||||
|
|
Loading…
Reference in New Issue