You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

412 lines
11 KiB

14 years ago
14 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  6. * Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
  7. * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 2
  12. * of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, you may find one here:
  21. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  22. * or you may search the http://www.gnu.org website for the version 2 license,
  23. * or you may write to the Free Software Foundation, Inc.,
  24. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  25. */
  26. #include <bitmaps.h>
  27. #include <core/mirror.h>
  28. #include <macros.h>
  29. #include <pcb_edit_frame.h>
  30. #include <board_design_settings.h>
  31. #include <footprint.h>
  32. #include <base_units.h>
  33. #include <geometry/shape_compound.h>
  34. #include <pcb_shape.h>
  35. #include <pcb_painter.h>
  36. PCB_SHAPE::PCB_SHAPE( BOARD_ITEM* aParent, KICAD_T aItemType, SHAPE_T aShapeType ) :
  37. BOARD_ITEM( aParent, aItemType ),
  38. EDA_SHAPE( aShapeType, pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ), FILL_T::NO_FILL )
  39. {
  40. }
  41. PCB_SHAPE::PCB_SHAPE( BOARD_ITEM* aParent, SHAPE_T shapetype ) :
  42. BOARD_ITEM( aParent, PCB_SHAPE_T ),
  43. EDA_SHAPE( shapetype, pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ), FILL_T::NO_FILL )
  44. {
  45. }
  46. PCB_SHAPE::~PCB_SHAPE()
  47. {
  48. }
  49. bool PCB_SHAPE::IsType( const std::vector<KICAD_T>& aScanTypes ) const
  50. {
  51. if( BOARD_ITEM::IsType( aScanTypes ) )
  52. return true;
  53. bool sametype = false;
  54. for( KICAD_T scanType : aScanTypes )
  55. {
  56. if( scanType == PCB_LOCATE_GRAPHIC_T )
  57. return true;
  58. else if( scanType == PCB_LOCATE_BOARD_EDGE_T )
  59. sametype = m_layer == Edge_Cuts;
  60. else if( scanType == PCB_SHAPE_LOCATE_ARC_T )
  61. sametype = m_shape == SHAPE_T::ARC;
  62. else if( scanType == PCB_SHAPE_LOCATE_CIRCLE_T )
  63. sametype = m_shape == SHAPE_T::CIRCLE;
  64. else if( scanType == PCB_SHAPE_LOCATE_RECT_T )
  65. sametype = m_shape == SHAPE_T::RECT;
  66. else if( scanType == PCB_SHAPE_LOCATE_SEGMENT_T )
  67. sametype = m_shape == SHAPE_T::SEGMENT;
  68. else if( scanType == PCB_SHAPE_LOCATE_POLY_T )
  69. sametype = m_shape == SHAPE_T::POLY;
  70. else if( scanType == PCB_SHAPE_LOCATE_BEZIER_T )
  71. sametype = m_shape == SHAPE_T::BEZIER;
  72. if( sametype )
  73. return true;
  74. }
  75. return false;
  76. }
  77. const VECTOR2I PCB_SHAPE::GetFocusPosition() const
  78. {
  79. // For some shapes return the visual center, but for not filled polygonal shapes,
  80. // the center is usually far from the shape: a point on the outline is better
  81. switch( m_shape )
  82. {
  83. case SHAPE_T::CIRCLE:
  84. if( !IsFilled() )
  85. return VECTOR2I( GetCenter().x + GetRadius(), GetCenter().y );
  86. else
  87. return GetCenter();
  88. case SHAPE_T::RECT:
  89. if( !IsFilled() )
  90. return GetStart();
  91. else
  92. return GetCenter();
  93. case SHAPE_T::POLY:
  94. if( !IsFilled() )
  95. {
  96. VECTOR2I pos = GetPolyShape().Outline(0).CPoint(0);
  97. return VECTOR2I( pos.x, pos.y );
  98. }
  99. else
  100. {
  101. return GetCenter();
  102. }
  103. case SHAPE_T::ARC:
  104. return GetArcMid();
  105. case SHAPE_T::BEZIER:
  106. return GetStart();
  107. default:
  108. return GetCenter();
  109. }
  110. }
  111. std::vector<VECTOR2I> PCB_SHAPE::GetCorners() const
  112. {
  113. std::vector<VECTOR2I> pts;
  114. if( GetShape() == SHAPE_T::RECT )
  115. {
  116. pts = GetRectCorners();
  117. }
  118. else if( GetShape() == SHAPE_T::POLY )
  119. {
  120. VECTOR2I offset = getParentPosition();
  121. for( int ii = 0; ii < GetPolyShape().OutlineCount(); ++ii )
  122. {
  123. for( const VECTOR2I& pt : GetPolyShape().Outline( ii ).CPoints() )
  124. pts.emplace_back( pt + offset );
  125. }
  126. }
  127. else
  128. {
  129. UNIMPLEMENTED_FOR( SHAPE_T_asString() );
  130. }
  131. while( pts.size() < 4 )
  132. pts.emplace_back( pts.back() + VECTOR2I( 10, 10 ) );
  133. return pts;
  134. }
  135. void PCB_SHAPE::Move( const VECTOR2I& aMoveVector )
  136. {
  137. move( aMoveVector );
  138. }
  139. void PCB_SHAPE::Scale( double aScale )
  140. {
  141. scale( aScale );
  142. }
  143. void PCB_SHAPE::NormalizeRect()
  144. {
  145. if( m_shape == SHAPE_T::RECT )
  146. {
  147. VECTOR2I start = GetStart();
  148. VECTOR2I end = GetEnd();
  149. BOX2I rect( start, end - start );
  150. rect.Normalize();
  151. SetStart( rect.GetPosition() );
  152. SetEnd( rect.GetEnd() );
  153. }
  154. }
  155. void PCB_SHAPE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
  156. {
  157. rotate( aRotCentre, aAngle );
  158. }
  159. void PCB_SHAPE::Flip( const VECTOR2I& aCentre, bool aFlipLeftRight )
  160. {
  161. flip( aCentre, aFlipLeftRight );
  162. SetLayer( FlipLayer( GetLayer(), GetBoard()->GetCopperLayerCount() ) );
  163. }
  164. void PCB_SHAPE::Mirror( const VECTOR2I& aCentre, bool aMirrorAroundXAxis )
  165. {
  166. // Mirror an edge of the footprint. the layer is not modified
  167. // This is a footprint shape modification.
  168. switch( GetShape() )
  169. {
  170. case SHAPE_T::ARC:
  171. case SHAPE_T::SEGMENT:
  172. case SHAPE_T::RECT:
  173. case SHAPE_T::CIRCLE:
  174. case SHAPE_T::BEZIER:
  175. if( aMirrorAroundXAxis )
  176. {
  177. MIRROR( m_start.y, aCentre.y );
  178. MIRROR( m_end.y, aCentre.y );
  179. MIRROR( m_arcCenter.y, aCentre.y );
  180. MIRROR( m_bezierC1.y, aCentre.y );
  181. MIRROR( m_bezierC2.y, aCentre.y );
  182. }
  183. else
  184. {
  185. MIRROR( m_start.x, aCentre.x );
  186. MIRROR( m_end.x, aCentre.x );
  187. MIRROR( m_arcCenter.x, aCentre.x );
  188. MIRROR( m_bezierC1.x, aCentre.x );
  189. MIRROR( m_bezierC2.x, aCentre.x );
  190. }
  191. if( GetShape() == SHAPE_T::ARC )
  192. std::swap( m_start, m_end );
  193. if( GetShape() == SHAPE_T::BEZIER )
  194. RebuildBezierToSegmentsPointsList( GetWidth() );
  195. break;
  196. case SHAPE_T::POLY:
  197. m_poly.Mirror( !aMirrorAroundXAxis, aMirrorAroundXAxis, aCentre );
  198. break;
  199. default:
  200. UNIMPLEMENTED_FOR( SHAPE_T_asString() );
  201. }
  202. }
  203. FOOTPRINT* PCB_SHAPE::GetParentFootprint() const
  204. {
  205. return dynamic_cast<FOOTPRINT*>( BOARD_ITEM::GetParentFootprint() );
  206. }
  207. EDA_ANGLE PCB_SHAPE::getParentOrientation() const
  208. {
  209. if( GetParentFootprint() )
  210. return GetParentFootprint()->GetOrientation();
  211. else
  212. return ANGLE_0;
  213. }
  214. VECTOR2I PCB_SHAPE::getParentPosition() const
  215. {
  216. if( GetParentFootprint() )
  217. return GetParentFootprint()->GetPosition();
  218. else
  219. return VECTOR2I( 0, 0 );
  220. }
  221. double PCB_SHAPE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
  222. {
  223. constexpr double HIDE = std::numeric_limits<double>::max();
  224. constexpr double SHOW = 0.0;
  225. KIGFX::PCB_PAINTER* painter = static_cast<KIGFX::PCB_PAINTER*>( aView->GetPainter() );
  226. KIGFX::PCB_RENDER_SETTINGS* renderSettings = painter->GetSettings();
  227. if( aLayer == LAYER_LOCKED_ITEM_SHADOW )
  228. {
  229. // Hide shadow if the main layer is not shown
  230. if( !aView->IsLayerVisible( m_layer ) )
  231. return HIDE;
  232. // Hide shadow on dimmed tracks
  233. if( renderSettings->GetHighContrast() )
  234. {
  235. if( m_layer != renderSettings->GetPrimaryHighContrastLayer() )
  236. return HIDE;
  237. }
  238. }
  239. return SHOW;
  240. }
  241. void PCB_SHAPE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
  242. {
  243. aList.emplace_back( _( "Type" ), _( "Drawing" ) );
  244. if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
  245. aList.emplace_back( _( "Status" ), _( "Locked" ) );
  246. ShapeGetMsgPanelInfo( aFrame, aList );
  247. aList.emplace_back( _( "Layer" ), GetLayerName() );
  248. }
  249. wxString PCB_SHAPE::GetSelectMenuText( UNITS_PROVIDER* aUnitsProvider ) const
  250. {
  251. return wxString::Format( _( "%s on %s" ), ShowShape(), GetLayerName() );
  252. }
  253. BITMAPS PCB_SHAPE::GetMenuImage() const
  254. {
  255. return BITMAPS::add_dashed_line;
  256. }
  257. EDA_ITEM* PCB_SHAPE::Clone() const
  258. {
  259. return new PCB_SHAPE( *this );
  260. }
  261. const BOX2I PCB_SHAPE::ViewBBox() const
  262. {
  263. BOX2I return_box = EDA_ITEM::ViewBBox();
  264. // Inflate the bounding box by just a bit more for safety.
  265. return_box.Inflate( GetWidth() );
  266. return return_box;
  267. }
  268. std::shared_ptr<SHAPE> PCB_SHAPE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
  269. {
  270. return std::make_shared<SHAPE_COMPOUND>( MakeEffectiveShapes() );
  271. }
  272. void PCB_SHAPE::swapData( BOARD_ITEM* aImage )
  273. {
  274. PCB_SHAPE* image = dynamic_cast<PCB_SHAPE*>( aImage );
  275. assert( image );
  276. SwapShape( image );
  277. std::swap( m_layer, image->m_layer );
  278. std::swap( m_fill, image->m_fill );
  279. std::swap( m_flags, image->m_flags );
  280. std::swap( m_status, image->m_status );
  281. std::swap( m_parent, image->m_parent );
  282. std::swap( m_forceVisible, image->m_forceVisible );
  283. }
  284. bool PCB_SHAPE::cmp_drawings::operator()( const BOARD_ITEM* aFirst,
  285. const BOARD_ITEM* aSecond ) const
  286. {
  287. if( aFirst->Type() != aSecond->Type() )
  288. return aFirst->Type() < aSecond->Type();
  289. if( aFirst->GetLayer() != aSecond->GetLayer() )
  290. return aFirst->GetLayer() < aSecond->GetLayer();
  291. if( aFirst->Type() == PCB_SHAPE_T )
  292. {
  293. const PCB_SHAPE* dwgA = static_cast<const PCB_SHAPE*>( aFirst );
  294. const PCB_SHAPE* dwgB = static_cast<const PCB_SHAPE*>( aSecond );
  295. if( dwgA->GetShape() != dwgB->GetShape() )
  296. return dwgA->GetShape() < dwgB->GetShape();
  297. }
  298. return aFirst->m_Uuid < aSecond->m_Uuid;
  299. }
  300. void PCB_SHAPE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
  301. int aClearance, int aError, ERROR_LOC aErrorLoc,
  302. bool ignoreLineWidth ) const
  303. {
  304. EDA_SHAPE::TransformShapeToPolygon( aBuffer, aClearance, aError, aErrorLoc, ignoreLineWidth );
  305. }
  306. static struct PCB_SHAPE_DESC
  307. {
  308. PCB_SHAPE_DESC()
  309. {
  310. PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
  311. REGISTER_TYPE( PCB_SHAPE );
  312. propMgr.AddTypeCast( new TYPE_CAST<PCB_SHAPE, BOARD_ITEM> );
  313. propMgr.AddTypeCast( new TYPE_CAST<PCB_SHAPE, EDA_SHAPE> );
  314. propMgr.InheritsAfter( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( BOARD_ITEM ) );
  315. propMgr.InheritsAfter( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( EDA_SHAPE ) );
  316. auto layerProperty = new PROPERTY_ENUM<PCB_SHAPE, PCB_LAYER_ID, BOARD_ITEM>(
  317. _HKI( "Layer" ), &PCB_SHAPE::SetLayer, &PCB_SHAPE::GetLayer );
  318. propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Layer" ), layerProperty );
  319. }
  320. } _PCB_SHAPE_DESC;