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.

559 lines
18 KiB

14 years ago
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) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
  5. * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. /**
  25. * @file class_dimension.h
  26. * @brief DIMENSION class definition.
  27. */
  28. #ifndef DIMENSION_H_
  29. #define DIMENSION_H_
  30. #include <class_board_item.h>
  31. #include <class_pcb_text.h>
  32. #include <geometry/shape.h>
  33. class LINE_READER;
  34. class TEXTE_PCB;
  35. class MSG_PANEL_ITEM;
  36. /// How to display the units in a dimension's text
  37. enum class DIM_UNITS_FORMAT
  38. {
  39. NO_SUFFIX, // 1234.0
  40. BARE_SUFFIX, // 1234.0 mm
  41. PAREN_SUFFIX // 1234.0 (mm)
  42. };
  43. /// Where to place the text on a dimension
  44. enum class DIM_TEXT_POSITION
  45. {
  46. OUTSIDE, ///< Text appears outside the dimension line (default)
  47. INLINE, ///< Text appears in line with the dimension line
  48. MANUAL ///< Text placement is manually set by the user
  49. };
  50. /**
  51. * Used for storing the units selection in the file because EDA_UNITS alone doesn't cut it
  52. */
  53. enum class DIM_UNITS_MODE
  54. {
  55. INCHES,
  56. MILS,
  57. MILLIMETRES,
  58. AUTOMATIC
  59. };
  60. /**
  61. * Frame to show around dimension text
  62. */
  63. enum class DIM_TEXT_FRAME
  64. {
  65. NONE,
  66. RECTANGLE,
  67. CIRCLE,
  68. ROUNDRECT
  69. };
  70. /**
  71. * Abstract dimension API
  72. *
  73. * Some notes about dimension nomenclature:
  74. *
  75. * - "feature points" are the points being measured by the dimension. For an example, the start
  76. * and end points of a line to be measured. These are the first points picked when drawing a
  77. * new dimension. Dimensions can have one or more feature points: linear dimensions (the only
  78. * type supported in KiCad 5 and earlier) have two feature points; leader dimensions have one;
  79. * and ordinate dimensions can have in theory an unlimited number of feature points.
  80. *
  81. * - "feature lines" are lines that coincide with feature points. Not all dimension types have
  82. * feature lines. The actual start and end of feature lines is calculated from dimension style
  83. * properties (offset from feature point to start of feature line, height of crossbar, and height
  84. * of feature line past crossbar, for example in linear dimensions)
  85. *
  86. * - "crossbar" refers to the perpendicular line (usually with arrows at each end) between feature
  87. * lines on linear dimensions
  88. */
  89. class DIMENSION : public BOARD_ITEM
  90. {
  91. public:
  92. DIMENSION( BOARD_ITEM* aParent, KICAD_T aType = PCB_DIMENSION_T );
  93. bool IsType( const KICAD_T aScanTypes[] ) const override
  94. {
  95. if( BOARD_ITEM::IsType( aScanTypes ) )
  96. return true;
  97. for( const KICAD_T* p = aScanTypes; *p != EOT; ++p )
  98. {
  99. if( *p == PCB_LOCATE_GRAPHIC_T )
  100. return true;
  101. }
  102. return false;
  103. }
  104. void SetParent( EDA_ITEM* aParent ) override;
  105. /**
  106. * The dimension's origin is the first feature point for the dimension. Every dimension has
  107. * one or more feature points, so every dimension has at least an origin.
  108. * @return the origin point of this dimension
  109. */
  110. virtual const wxPoint& GetStart() const { return m_start; }
  111. virtual void SetStart( const wxPoint& aPoint );
  112. virtual const wxPoint& GetEnd() const { return m_end; }
  113. virtual void SetEnd( const wxPoint& aPoint );
  114. // These deal with the text position
  115. wxPoint GetPosition() const override;
  116. void SetPosition( const wxPoint& aPos ) override;
  117. bool GetOverrideTextEnabled() const { return m_overrideTextEnabled; }
  118. void SetOverrideTextEnabled( bool aOverride ) { m_overrideTextEnabled = aOverride; }
  119. wxString GetOverrideText() const { return m_valueString; }
  120. void SetOverrideText( const wxString& aValue ) { m_valueString = aValue; }
  121. int GetMeasuredValue() const { return m_measuredValue; }
  122. /**
  123. * @return the dimension value, rendered with precision / zero suppression but no units, etc
  124. */
  125. wxString GetValueText() const;
  126. /**
  127. * Updates the dimension's cached text and geometry
  128. */
  129. void Update()
  130. {
  131. updateGeometry();
  132. updateText();
  133. }
  134. wxString GetPrefix() const { return m_prefix; }
  135. void SetPrefix( const wxString& aPrefix );
  136. wxString GetSuffix() const { return m_suffix; }
  137. void SetSuffix( const wxString& aSuffix );
  138. void GetUnits( EDA_UNITS& aUnits, bool& aUseMils ) const
  139. {
  140. aUnits = m_units;
  141. aUseMils = m_useMils;
  142. }
  143. void SetUnits( EDA_UNITS aUnits, bool aUseMils );
  144. DIM_UNITS_MODE GetUnitsMode() const;
  145. void SetUnitsMode( DIM_UNITS_MODE aMode );
  146. void SetAutoUnits( bool aAuto = true ) { m_autoUnits = aAuto; }
  147. DIM_UNITS_FORMAT GetUnitsFormat() const { return m_unitsFormat; }
  148. void SetUnitsFormat( const DIM_UNITS_FORMAT aFormat ) { m_unitsFormat = aFormat; }
  149. int GetPrecision() const { return m_precision; }
  150. void SetPrecision( int aPrecision ) { m_precision = aPrecision; }
  151. bool GetSuppressZeroes() const { return m_suppressZeroes; }
  152. void SetSuppressZeroes( bool aSuppress ) { m_suppressZeroes = aSuppress; }
  153. bool GetKeepTextAligned() const { return m_keepTextAligned; }
  154. void SetKeepTextAligned( bool aKeepAligned ) { m_keepTextAligned = aKeepAligned; }
  155. void SetTextPositionMode( DIM_TEXT_POSITION aMode ) { m_textPosition = aMode; }
  156. DIM_TEXT_POSITION GetTextPositionMode() const { return m_textPosition; }
  157. int GetArrowLength() const { return m_arrowLength; }
  158. void SetArrowLength( int aLength ) { m_arrowLength = aLength; }
  159. void SetExtensionOffset( int aOffset ) { m_extensionOffset = aOffset; }
  160. int GetExtensionOffset() const { return m_extensionOffset; }
  161. int GetLineThickness() const { return m_lineThickness; }
  162. void SetLineThickness( int aWidth ) { m_lineThickness = aWidth; }
  163. void SetLayer( PCB_LAYER_ID aLayer ) override;
  164. void SetTextSize( const wxSize& aTextSize )
  165. {
  166. m_text.SetTextSize( aTextSize );
  167. }
  168. /**
  169. * Sets the override text - has no effect if m_overrideValue == false
  170. * @param aNewText is the text to use as the value
  171. */
  172. void SetText( const wxString& aNewText );
  173. /**
  174. * Retrieves the value text or override text, not including prefix or suffix
  175. * @return the value portion of the dimension text (either overridden or not)
  176. */
  177. const wxString GetText() const;
  178. TEXTE_PCB& Text() { return m_text; }
  179. TEXTE_PCB& Text() const { return *( const_cast<TEXTE_PCB*> ( &m_text ) ); }
  180. /**
  181. * @return a list of line segments that make up this dimension (for drawing, plotting, etc)
  182. */
  183. const std::vector<std::shared_ptr<SHAPE>>& GetShapes() const { return m_shapes; }
  184. /**
  185. * @return create a caller-owned list of *all* shapes (including any text).
  186. * Used for collision calculations (DRC, PNS, etc.).
  187. */
  188. std::vector<SHAPE*> MakeEffectiveShapes() const;
  189. // BOARD_ITEM overrides
  190. void Move( const wxPoint& offset ) override;
  191. void Rotate( const wxPoint& aRotCentre, double aAngle ) override;
  192. void Flip( const wxPoint& aCentre, bool aFlipLeftRight ) override;
  193. /**
  194. * Mirror the Dimension , relative to a given horizontal axis
  195. * the text is not mirrored. only its position (and angle) is mirrored
  196. * the layer is not changed
  197. * @param axis_pos : vertical axis position
  198. */
  199. void Mirror( const wxPoint& axis_pos, bool aMirrorLeftRight = false );
  200. void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
  201. bool HitTest( const wxPoint& aPosition, int aAccuracy ) const override;
  202. bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
  203. const EDA_RECT GetBoundingBox() const override;
  204. std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer ) const override;
  205. wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
  206. const BOX2I ViewBBox() const override;
  207. #if defined(DEBUG)
  208. virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
  209. #endif
  210. protected:
  211. /**
  212. * Updates the cached geometry of the dimension after changing any of its properties
  213. */
  214. virtual void updateGeometry() = 0;
  215. /**
  216. * Updates the text field value from the current geometry (called by updateGeometry normally)
  217. */
  218. virtual void updateText();
  219. template<typename ShapeType>
  220. void addShape( ShapeType* aShape );
  221. /**
  222. * Finds the intersection between a given segment and polygon outline
  223. * @param aPoly is the polygon to collide
  224. * @param aSeg is the segment to collide
  225. * @param aStart if true will start from aSeg.A, otherwise aSeg.B
  226. * @return a point on aSeg that collides with aPoly closest to the start, if one exists
  227. */
  228. static OPT_VECTOR2I segPolyIntersection( SHAPE_POLY_SET& aPoly, SEG& aSeg, bool aStart = true );
  229. // Value format
  230. bool m_overrideTextEnabled; ///< Manually specify the displayed measurement value
  231. wxString m_valueString; ///< Displayed value when m_overrideValue = true
  232. wxString m_prefix; ///< String prepended to the value
  233. wxString m_suffix; ///< String appended to the value
  234. EDA_UNITS m_units; ///< 0 = inches, 1 = mm
  235. bool m_useMils; ///< If inches, use mils.
  236. bool m_autoUnits; ///< If true, follow the currently selected UI units
  237. DIM_UNITS_FORMAT m_unitsFormat; ///< How to render the units suffix
  238. int m_precision; ///< Number of digits to display after decimal
  239. bool m_suppressZeroes; ///< Suppress trailing zeroes
  240. // Geometry
  241. int m_lineThickness; ///< Thickness used for all graphics in the dimension
  242. int m_arrowLength; ///< Length of arrow shapes
  243. int m_extensionOffset; ///< Distance from feature points to extension line start
  244. DIM_TEXT_POSITION m_textPosition; ///< How to position the text
  245. bool m_keepTextAligned; ///< Calculate text orientation to match dimension
  246. // Internal
  247. TEXTE_PCB m_text; ///< The actual text object
  248. int m_measuredValue; ///< value of PCB dimensions
  249. wxPoint m_start;
  250. wxPoint m_end;
  251. ///< Internal cache of drawn shapes
  252. std::vector<std::shared_ptr<SHAPE>> m_shapes;
  253. static constexpr float s_arrowAngle = 27.5;
  254. };
  255. /**
  256. * For better understanding of the points that make a dimension:
  257. *
  258. * Note: historically KiCad called extension lines "feature lines", and also note that what we
  259. * call the "crossbar line" here is more commonly called the "dimension line"
  260. *
  261. * Start (feature point 1) End (feature point 2)
  262. * | |
  263. * | <-- extension lines --> |
  264. * | |
  265. * | m_arrowG2F m_arrowD2F |
  266. * | / \ |
  267. * Crossbar start |/_______crossbar line________\| Crossbar end
  268. * |\ m_text /|
  269. * | \ / |
  270. * | m_arrowG1F m_arrowD1F |
  271. * | |
  272. * m_featureLineGF m_featureLineDF
  273. */
  274. /**
  275. * An aligned dimension measures the distance between two feature points. It has a crossbar
  276. * (dimension line) that stays parallel with the vector between the feature points.
  277. *
  278. * The height (distance from features to crossbar) can be set directly, or set by manipulating the
  279. * crossbar start or end point (with the point editor).
  280. */
  281. class ALIGNED_DIMENSION : public DIMENSION
  282. {
  283. protected:
  284. // Geometry
  285. int m_height; ///< Perpendicular distance from features to crossbar
  286. int m_extensionHeight; ///< Length of extension lines past the crossbar
  287. wxPoint m_crossBarStart; ///< Crossbar start control point
  288. wxPoint m_crossBarEnd; ///< Crossbar end control point
  289. public:
  290. ALIGNED_DIMENSION( BOARD_ITEM* aParent, KICAD_T aType = PCB_DIM_ALIGNED_T );
  291. // Do not create a copy constructor & operator=.
  292. // The ones generated by the compiler are adequate.
  293. ~ALIGNED_DIMENSION() = default;
  294. static inline bool ClassOf( const EDA_ITEM* aItem )
  295. {
  296. return aItem && PCB_DIM_ALIGNED_T == aItem->Type();
  297. }
  298. EDA_ITEM* Clone() const override;
  299. virtual void SwapData( BOARD_ITEM* aImage ) override;
  300. BITMAP_DEF GetMenuImage() const override;
  301. const wxPoint& GetCrossbarStart() const { return m_crossBarStart; }
  302. const wxPoint& GetCrossbarEnd() const { return m_crossBarEnd; }
  303. /**
  304. * Sets the distance from the feature points to the crossbar line
  305. * @param aHeight is the new height.
  306. */
  307. void SetHeight( int aHeight );
  308. int GetHeight() const { return m_height; }
  309. /**
  310. * Updates stored height basing on points coordinates.
  311. * @param aCrossbarStart is the start point of the crossbar
  312. */
  313. void UpdateHeight( const wxPoint& aCrossbarStart, const wxPoint& aCrossbarEnd );
  314. void SetExtensionHeight( int aHeight ) { m_extensionHeight = aHeight; }
  315. int GetExtensionHeight() const { return m_extensionHeight; }
  316. /**
  317. * Function GetAngle
  318. * Returns angle of the crossbar.
  319. * @return Angle of the crossbar line expressed in radians.
  320. */
  321. double GetAngle() const
  322. {
  323. wxPoint delta( m_end - m_start );
  324. return atan2( (double)delta.y, (double)delta.x );
  325. }
  326. wxString GetClass() const override
  327. {
  328. return wxT( "ALIGNED_DIMENSION" );
  329. }
  330. protected:
  331. void updateGeometry() override;
  332. void updateText() override;
  333. };
  334. /**
  335. * An orthogonal dimension is like an aligned dimension, but the extension lines are locked to the
  336. * X or Y axes, and the measurement is only taken in the X or Y direction.
  337. */
  338. class ORTHOGONAL_DIMENSION : public ALIGNED_DIMENSION
  339. {
  340. public:
  341. enum class DIR
  342. {
  343. HORIZONTAL, // Aligned with x-axis
  344. VERTICAL // Aligned with y-axis
  345. };
  346. private:
  347. // Geometry
  348. DIR m_orientation; ///< What axis to lock the dimension line to
  349. public:
  350. ORTHOGONAL_DIMENSION( BOARD_ITEM* aParent );
  351. ~ORTHOGONAL_DIMENSION() = default;
  352. static inline bool ClassOf( const EDA_ITEM* aItem )
  353. {
  354. return aItem && PCB_DIM_ORTHOGONAL_T == aItem->Type();
  355. }
  356. EDA_ITEM* Clone() const override;
  357. void SwapData( BOARD_ITEM* aImage ) override;
  358. BITMAP_DEF GetMenuImage() const override;
  359. /**
  360. * Sets the orientation of the dimension line (so, perpendicular to the feature lines)
  361. * @param aOrientation is the orientation the dimension should take
  362. */
  363. void SetOrientation( DIR aOrientation ) { m_orientation = aOrientation; }
  364. DIR GetOrientation() const { return m_orientation; }
  365. wxString GetClass() const override
  366. {
  367. return wxT( "ORTHOGONAL_DIMENSION" );
  368. }
  369. protected:
  370. void updateGeometry() override;
  371. void updateText() override;
  372. };
  373. /**
  374. * A leader is a dimension-like object pointing to a specific point.
  375. *
  376. * A guide to the geometry of a leader:
  377. *
  378. * a
  379. * _
  380. * |\
  381. * \
  382. * b---c TEXT
  383. *
  384. * Point (a) is m_start, point (b) is m_end, point (c) is the end of the "text line"
  385. * The b-c line is drawn from b to the text center, and clipped on the text bounding box.
  386. */
  387. class LEADER : public DIMENSION
  388. {
  389. DIM_TEXT_FRAME m_textFrame;
  390. public:
  391. LEADER( BOARD_ITEM* aParent );
  392. static inline bool ClassOf( const EDA_ITEM* aItem )
  393. {
  394. return aItem && PCB_DIM_LEADER_T == aItem->Type();
  395. }
  396. EDA_ITEM* Clone() const override;
  397. virtual void SwapData( BOARD_ITEM* aImage ) override;
  398. BITMAP_DEF GetMenuImage() const override;
  399. wxString GetClass() const override
  400. {
  401. return wxT( "LEADER" );
  402. }
  403. void SetTextFrame( DIM_TEXT_FRAME aFrame ) { m_textFrame = aFrame; }
  404. DIM_TEXT_FRAME GetTextFrame() const { return m_textFrame; }
  405. void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
  406. protected:
  407. void updateGeometry() override;
  408. };
  409. /**
  410. * Marks the center of a circle or arc with a cross shape
  411. * The size and orientation of the cross is adjustable.
  412. * m_start always marks the center being measured; m_end marks the end of one leg of the cross.
  413. */
  414. class CENTER_DIMENSION : public DIMENSION
  415. {
  416. public:
  417. CENTER_DIMENSION( BOARD_ITEM* aParent );
  418. static inline bool ClassOf( const EDA_ITEM* aItem )
  419. {
  420. return aItem && PCB_DIM_CENTER_T == aItem->Type();
  421. }
  422. EDA_ITEM* Clone() const override;
  423. virtual void SwapData( BOARD_ITEM* aImage ) override;
  424. BITMAP_DEF GetMenuImage() const override;
  425. wxString GetClass() const override
  426. {
  427. return wxT( "CENTER_DIMENSION" );
  428. }
  429. const EDA_RECT GetBoundingBox() const override;
  430. const BOX2I ViewBBox() const override;
  431. protected:
  432. void updateGeometry() override;
  433. };
  434. #endif // DIMENSION_H_