KiCad PCB EDA Suite
ruler_item.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2017 Kicad Developers, see change_log.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
25 
29 #include <view/view.h>
30 #include <pcb_painter.h>
31 
32 #include <base_units.h>
33 #include <common.h>
34 
35 using namespace KIGFX::PREVIEW;
36 
37 static const double maxTickDensity = 10.0; // min pixels between tick marks
38 static const double midTickLengthFactor = 1.5;
39 static const double majorTickLengthFactor = 2.5;
40 
41 
42 static void drawCursorStrings( KIGFX::VIEW* aView, const VECTOR2D& aCursor,
43  const VECTOR2D& aRulerVec, EDA_UNITS_T aUnits )
44 {
45  // draw the cursor labels
46  std::vector<wxString> cursorStrings;
47 
48  cursorStrings.push_back( DimensionLabel( "x", aRulerVec.x, aUnits ) );
49  cursorStrings.push_back( DimensionLabel( "y", aRulerVec.y, aUnits ) );
50 
51  cursorStrings.push_back( DimensionLabel( "r", aRulerVec.EuclideanNorm(), aUnits ) );
52 
53  double degs = RAD2DECIDEG( -aRulerVec.Angle() );
54  cursorStrings.push_back( DimensionLabel( wxString::FromUTF8( "θ" ), degs, DEGREES ) );
55 
56  for( auto& str: cursorStrings )
57  {
58  // FIXME: remove spaces that choke OpenGL lp:1668455
59  str.erase( std::remove( str.begin(), str.end(), ' ' ), str.end() );
60  }
61 
62  auto temp = aRulerVec;
63  DrawTextNextToCursor( aView, aCursor, -temp, cursorStrings );
64 }
65 
66 
72 {
73  double divisionBase;
74  int majorStep;
75  int midStep;
76 };
77 
78 
79 static TICK_FORMAT getTickFormatForScale( double aScale, double& aTickSpace, EDA_UNITS_T aUnits )
80 {
81  // simple 1/2/5 scales per decade
82  static std::vector<TICK_FORMAT> tickFormats =
83  {
84  { 2, 10, 5 }, // |....:....|
85  { 2, 5, 0 }, // |....|
86  { 2.5, 2, 0 }, // |.|.|
87  };
88 
89  // could start at a set number of MM, but that's not available in common
90  aTickSpace = 1;
91 
92  // convert to a round (mod-10) number of mils
93  if( aUnits == INCHES )
94  {
95  aTickSpace *= 2.54;
96  }
97 
98  int tickFormat = 0;
99 
100  while( true )
101  {
102  const auto pixelSpace = aTickSpace * aScale;
103 
104  if( pixelSpace >= maxTickDensity )
105  break;
106 
107  tickFormat = ( tickFormat + 1 ) % tickFormats.size();
108  aTickSpace *= tickFormats[tickFormat].divisionBase;
109  }
110 
111  return tickFormats[tickFormat];
112 }
113 
114 
124 void drawTicksAlongLine( KIGFX::VIEW *aView, const VECTOR2D& aOrigin,
125  const VECTOR2D& aLine, double aMinorTickLen, EDA_UNITS_T aUnits )
126 {
127  VECTOR2D tickLine = aLine.Rotate( -M_PI_2 );
128  auto gal = aView->GetGAL();
129  double tickSpace;
130  TICK_FORMAT tickF = getTickFormatForScale( gal->GetWorldScale(), tickSpace, aUnits );
131  auto rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( aView->GetPainter()->GetSettings() );
132 
133  // number of ticks in whole ruler
134  int numTicks = (int) std::ceil( aLine.EuclideanNorm() / tickSpace );
135 
136  // work out which way up the tick labels go
137  double labelAngle = -tickLine.Angle();
138 
139  if( aLine.Angle() > 0 )
140  {
141  gal->SetHorizontalJustify( GR_TEXT_HJUSTIFY_LEFT );
142  }
143  else
144  {
145  gal->SetHorizontalJustify( GR_TEXT_HJUSTIFY_RIGHT );
146  labelAngle += M_PI;
147  }
148 
149  // text and ticks are dimmed
150  gal->SetStrokeColor( rs->GetLayerColor( LAYER_AUX_ITEMS ).WithAlpha( PreviewOverlayDeemphAlpha( true ) ) );
151 
152  const auto labelOffset = tickLine.Resize( aMinorTickLen * ( majorTickLengthFactor + 1 ) );
153 
154  for( int i = 0; i < numTicks; ++i )
155  {
156  const auto tickPos = aOrigin + aLine.Resize( tickSpace * i );
157 
158  double length = aMinorTickLen;
159  bool drawLabel = false;
160 
161  if( i % tickF.majorStep == 0)
162  {
163  drawLabel = true;
164  length *= majorTickLengthFactor;
165  }
166  else if( tickF.midStep && i % tickF.midStep == 0 )
167  {
168  drawLabel = true;
169  length *= midTickLengthFactor;
170  }
171 
172  gal->DrawLine( tickPos, tickPos + tickLine.Resize( length ) );
173 
174  if( drawLabel )
175  {
176  wxString label = DimensionLabel( "", tickSpace * i, aUnits );
177 
178  // FIXME: spaces choke OpenGL lp:1668455
179  label.erase( std::remove( label.begin(), label.end(), ' ' ), label.end() );
180 
181  gal->BitmapText( label, tickPos + labelOffset, labelAngle );
182  }
183  }
184 }
185 
186 
197 void drawBacksideTicks( KIGFX::GAL& aGal, const VECTOR2D& aOrigin,
198  const VECTOR2D& aLine, double aTickLen, int aNumDivisions )
199 {
200  const double backTickSpace = aLine.EuclideanNorm() / aNumDivisions;
201  const auto backTickVec = aLine.Rotate( M_PI_2 ).Resize( aTickLen );
202 
203  for( int i = 0; i < aNumDivisions + 1; ++i )
204  {
205  const auto backTickPos = aOrigin + aLine.Resize( backTickSpace * i );
206  aGal.DrawLine( backTickPos, backTickPos + backTickVec );
207  }
208 }
209 
210 
212  EDA_ITEM( NOT_USED ), // Never added to anything - just a preview
213  m_geomMgr( aGeomMgr ),
214  m_userUnits( userUnits )
215 {}
216 
217 
219 {
220  BOX2I tmp;
221 
222  tmp.SetOrigin( m_geomMgr.GetOrigin() );
223  tmp.SetEnd( m_geomMgr.GetEnd() );
224  tmp.Normalize();
225  return tmp;
226 }
227 
228 
229 void RULER_ITEM::ViewGetLayers( int aLayers[], int& aCount ) const
230 {
231  aLayers[0] = LAYER_GP_OVERLAY;
232  aCount = 1;
233 }
234 
235 
236 void RULER_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
237 {
238  auto& gal = *aView->GetGAL();
239  auto rs = static_cast<KIGFX::RENDER_SETTINGS*>( aView->GetPainter()->GetSettings() );
240 
241  const auto origin = m_geomMgr.GetOrigin();
242  const auto end = m_geomMgr.GetEnd();
243 
244  gal.SetLineWidth( 1.0 );
245  gal.SetIsStroke( true );
246  gal.SetIsFill( false );
247 
248  gal.SetTextMirrored( false );
249  gal.SetStrokeColor( rs->GetLayerColor( LAYER_AUX_ITEMS ) );
250 
251  gal.ResetTextAttributes();
252 
253  // draw the main line from the origin to cursor
254  gal.DrawLine( origin, end );
255 
256  VECTOR2D rulerVec( end - origin );
257 
258  // constant text size on screen
259  SetConstantGlyphHeight( gal, 14.0 );
260 
261  drawCursorStrings( aView, end, rulerVec, m_userUnits );
262 
263  // tick label size
264  SetConstantGlyphHeight( gal, 12.0 );
265 
266  // basic tick size
267  const double minorTickLen = 5.0 / gal.GetWorldScale();
268 
269  drawTicksAlongLine( aView, origin, rulerVec, minorTickLen, m_userUnits );
270 
271  gal.SetStrokeColor( rs->GetLayerColor( LAYER_AUX_ITEMS ).WithAlpha( PreviewOverlayDeemphAlpha( true ) ) );
272  drawBacksideTicks( gal, origin, rulerVec, minorTickLen * majorTickLengthFactor, 2 );
273 
274  // draw the back of the origin "crosshair"
275  gal.DrawLine( origin, origin + rulerVec.Resize( -minorTickLen * midTickLengthFactor ) );
276 }
const BOX2I ViewBBox() const override
>
Definition: ruler_item.cpp:218
void drawTicksAlongLine(KIGFX::VIEW *aView, const VECTOR2D &aOrigin, const VECTOR2D &aLine, double aMinorTickLen, EDA_UNITS_T aUnits)
Draw labelled ticks on a line.
Definition: ruler_item.cpp:124
Class RENDER_SETTINGS Contains all the knowledge about how graphical objects are drawn on any output ...
Definition: painter.h:56
Implementation of conversion functions that require both schematic and board internal units...
VECTOR2< T > Resize(T aNewLength) const
Function Resize returns a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:385
Class TWO_POINT_GEOMETRY_MANAGER.
the 3d code uses this value
Definition: typeinfo.h:80
VECTOR2< T > Rotate(double aAngle) const
Function Rotate rotates the vector by a given angle.
Definition: vector2d.h:370
double RAD2DECIDEG(double rad)
Definition: trigo.h:204
int midStep
ticks between major ticks
Definition: ruler_item.cpp:75
double divisionBase
Definition: ruler_item.cpp:73
virtual void DrawLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a line.
const string & str
Definition: json11.cpp:596
void drawBacksideTicks(KIGFX::GAL &aGal, const VECTOR2D &aOrigin, const VECTOR2D &aLine, double aTickLen, int aNumDivisions)
Draw simple ticks on the back of a line such that the line is divided into n parts.
Definition: ruler_item.cpp:197
const TWO_POINT_GEOMETRY_MANAGER & m_geomMgr
Definition: ruler_item.h:83
static const double majorTickLengthFactor
Definition: ruler_item.cpp:39
Class PCB_RENDER_SETTINGS Stores PCB specific render settings.
Definition: pcb_painter.h:62
double Angle() const
Function Angle computes the angle of the vector.
Definition: vector2d.h:306
Auxiliary items (guides, rule, etc)
T EuclideanNorm() const
Destructor.
Definition: vector2d.h:292
static TICK_FORMAT getTickFormatForScale(double aScale, double &aTickSpace, EDA_UNITS_T aUnits)
Definition: ruler_item.cpp:79
GAL * GetGAL() const
Function GetGAL() Returns the GAL this view is using to draw graphical primitives.
Definition: view.h:180
Definition: common.h:160
BOX2< Vec > & Normalize()
Function Normalize ensures that the height ant width are positive.
Definition: box2.h:127
static const double midTickLengthFactor
Definition: ruler_item.cpp:38
void DrawTextNextToCursor(KIGFX::VIEW *aView, const VECTOR2D &aCursorPos, const VECTOR2D &aTextQuadrant, const std::vector< wxString > &aStrings)
Draw strings next to the cursor.
general purpose overlay
RULER_ITEM(const TWO_POINT_GEOMETRY_MANAGER &m_geomMgr, EDA_UNITS_T userUnits)
Definition: ruler_item.cpp:211
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:199
double PreviewOverlayDeemphAlpha(bool aDeemph=true)
Default alpha of "de-emphasised" features (like previously locked-in lines.
void SetEnd(coord_type x, coord_type y)
Definition: box2.h:223
virtual RENDER_SETTINGS * GetSettings()=0
Function GetSettings Returns pointer to current settings that are going to be used when drawing items...
void ViewDraw(int aLayer, KIGFX::VIEW *aView) const overridefinal
>
Definition: ruler_item.cpp:236
void ViewGetLayers(int aLayers[], int &aCount) const override
>
Definition: ruler_item.cpp:229
Board layer functions and definitions.
void SetConstantGlyphHeight(KIGFX::GAL &aGal, double aHeight)
Set the GAL glyph height to a constant scaled value, so that it always looks the same on screen...
size_t i
Definition: json11.cpp:597
void SetOrigin(const Vec &pos)
Definition: box2.h:208
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:154
The common library.
Description of a "tick format" for a scale factor - how many ticks there are between medium/major tic...
Definition: ruler_item.cpp:71
wxString DimensionLabel(const wxString &prefix, double aVal, EDA_UNITS_T aUnits)
Get a formatted string showing a dimension to a sane precision with an optional prefix and unit suffi...
Class VIEW.
Definition: view.h:61
static const double maxTickDensity
Definition: ruler_item.cpp:37
static void drawCursorStrings(KIGFX::VIEW *aView, const VECTOR2D &aCursor, const VECTOR2D &aRulerVec, EDA_UNITS_T aUnits)
Definition: ruler_item.cpp:42
int majorStep
multiple from the last scale
Definition: ruler_item.cpp:74
EDA_UNITS_T
Definition: common.h:159
Class GAL is the abstract interface for drawing on a 2D-surface.