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 )
44 {
45  // draw the cursor labels
46  std::vector<wxString> cursorStrings;
47 
48  cursorStrings.push_back( DimensionLabel( "r", aRulerVec.EuclideanNorm(), g_UserUnit ) );
49 
50  double degs = RAD2DECIDEG( -aRulerVec.Angle() );
51  cursorStrings.push_back( DimensionLabel( "θ", degs, DEGREES ) );
52 
53  for( auto& str: cursorStrings )
54  {
55  // FIXME: remove spaces that choke OpenGL lp:1668455
56  str.erase( std::remove( str.begin(), str.end(), ' ' ), str.end() );
57  }
58 
59  auto temp = aRulerVec;
60  DrawTextNextToCursor( aView, aCursor, -temp, cursorStrings );
61 }
62 
63 
69 {
70  double divisionBase;
71  int majorStep;
72  int midStep;
73 };
74 
75 
76 static TICK_FORMAT getTickFormatForScale( double aScale, double& aTickSpace )
77 {
78  // simple 1/2/5 scales per decade
79  static std::vector<TICK_FORMAT> tickFormats =
80  {
81  { 2, 10, 5 }, // |....:....|
82  { 2, 5, 0 }, // |....|
83  { 2.5, 2, 0 }, // |.|.|
84  };
85 
86  // could start at a set number of MM, but that's not available in common
87  aTickSpace = 1;
88 
89  // convert to a round (mod-10) number of mils
90  if( g_UserUnit == INCHES )
91  {
92  aTickSpace *= 2.54;
93  }
94 
95  int tickFormat = 0;
96 
97  while( true )
98  {
99  const auto pixelSpace = aTickSpace * aScale;
100 
101  if( pixelSpace >= maxTickDensity )
102  break;
103 
104  tickFormat = ( tickFormat + 1 ) % tickFormats.size();
105  aTickSpace *= tickFormats[tickFormat].divisionBase;
106  }
107 
108  return tickFormats[tickFormat];
109 }
110 
111 
121 void drawTicksAlongLine( KIGFX::VIEW *aView, const VECTOR2D& aOrigin,
122  const VECTOR2D& aLine, double aMinorTickLen )
123 {
124  VECTOR2D tickLine = aLine.Rotate( -M_PI_2 );
125  auto gal = aView->GetGAL();
126  double tickSpace;
127  TICK_FORMAT tickF = getTickFormatForScale( gal->GetWorldScale(), tickSpace );
128  auto rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( aView->GetPainter()->GetSettings() );
129 
130  // number of ticks in whole ruler
131  int numTicks = (int) std::ceil( aLine.EuclideanNorm() / tickSpace );
132 
133  // work out which way up the tick labels go
134  double labelAngle = -tickLine.Angle();
135 
136  if( aLine.Angle() > 0 )
137  {
138  gal->SetHorizontalJustify( GR_TEXT_HJUSTIFY_LEFT );
139  }
140  else
141  {
142  gal->SetHorizontalJustify( GR_TEXT_HJUSTIFY_RIGHT );
143  labelAngle += M_PI;
144  }
145 
146  // text and ticks are dimmed
147  gal->SetStrokeColor( rs->GetLayerColor( LAYER_AUX_ITEMS ).WithAlpha( PreviewOverlayDeemphAlpha( true ) ) );
148 
149  const auto labelOffset = tickLine.Resize( aMinorTickLen * ( majorTickLengthFactor + 1 ) );
150 
151  for( int i = 0; i < numTicks; ++i )
152  {
153  const auto tickPos = aOrigin + aLine.Resize( tickSpace * i );
154 
155  double length = aMinorTickLen;
156  bool drawLabel = false;
157 
158  if( i % tickF.majorStep == 0)
159  {
160  drawLabel = true;
161  length *= majorTickLengthFactor;
162  }
163  else if( tickF.midStep && i % tickF.midStep == 0 )
164  {
165  drawLabel = true;
166  length *= midTickLengthFactor;
167  }
168 
169  gal->DrawLine( tickPos, tickPos + tickLine.Resize( length ) );
170 
171  if( drawLabel )
172  {
173  wxString label = DimensionLabel( "", tickSpace * i, g_UserUnit );
174 
175  // FIXME: spaces choke OpenGL lp:1668455
176  label.erase( std::remove( label.begin(), label.end(), ' ' ), label.end() );
177 
178  gal->BitmapText( label, tickPos + labelOffset, labelAngle );
179  }
180  }
181 }
182 
183 
194 void drawBacksideTicks( KIGFX::GAL& aGal, const VECTOR2D& aOrigin,
195  const VECTOR2D& aLine, double aTickLen, int aNumDivisions )
196 {
197  const double backTickSpace = aLine.EuclideanNorm() / aNumDivisions;
198  const auto backTickVec = aLine.Rotate( M_PI_2 ).Resize( aTickLen );
199 
200  for( int i = 0; i < aNumDivisions + 1; ++i )
201  {
202  const auto backTickPos = aOrigin + aLine.Resize( backTickSpace * i );
203  aGal.DrawLine( backTickPos, backTickPos + backTickVec );
204  }
205 }
206 
207 
209  EDA_ITEM( NOT_USED ), // Never added to anything - just a preview
210  m_geomMgr( aGeomMgr )
211 {}
212 
213 
215 {
216  BOX2I tmp;
217 
218  tmp.SetOrigin( m_geomMgr.GetOrigin() );
219  tmp.SetEnd( m_geomMgr.GetEnd() );
220  tmp.Normalize();
221  return tmp;
222 }
223 
224 
225 void RULER_ITEM::ViewGetLayers( int aLayers[], int& aCount ) const
226 {
227  aLayers[0] = LAYER_GP_OVERLAY;
228  aCount = 1;
229 }
230 
231 
232 void RULER_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
233 {
234  auto& gal = *aView->GetGAL();
235  auto rs = static_cast<KIGFX::RENDER_SETTINGS*>( aView->GetPainter()->GetSettings() );
236 
237  const auto origin = m_geomMgr.GetOrigin();
238  const auto end = m_geomMgr.GetEnd();
239 
240  gal.SetLineWidth( 1.0 );
241  gal.SetIsStroke( true );
242  gal.SetIsFill( false );
243 
244  gal.SetTextMirrored( false );
245  gal.SetStrokeColor( rs->GetLayerColor( LAYER_AUX_ITEMS ) );
246 
247  gal.ResetTextAttributes();
248 
249  // draw the main line from the origin to cursor
250  gal.DrawLine( origin, end );
251 
252  VECTOR2D rulerVec( end - origin );
253 
254  // constant text size on screen
255  SetConstantGlyphHeight( gal, 12.0 );
256 
257  drawCursorStrings( aView, end, rulerVec );
258 
259  // tick label size
260  SetConstantGlyphHeight( gal, 10.0 );
261 
262  // basic tick size
263  const double minorTickLen = 5.0 / gal.GetWorldScale();
264 
265  drawTicksAlongLine( aView, origin, rulerVec, minorTickLen );
266 
267  gal.SetStrokeColor( rs->GetLayerColor( LAYER_AUX_ITEMS ).WithAlpha( PreviewOverlayDeemphAlpha( true ) ) );
268  drawBacksideTicks( gal, origin, rulerVec, minorTickLen * majorTickLengthFactor, 2 );
269 
270  // draw the back of the origin "crosshair"
271  gal.DrawLine( origin, origin + rulerVec.Resize( -minorTickLen * midTickLengthFactor ) );
272 }
const BOX2I ViewBBox() const override
>
Definition: ruler_item.cpp:214
RULER_ITEM(const TWO_POINT_GEOMETRY_MANAGER &m_geomMgr)
Definition: ruler_item.cpp:208
void drawTicksAlongLine(KIGFX::VIEW *aView, const VECTOR2D &aOrigin, const VECTOR2D &aLine, double aMinorTickLen)
Draw labelled ticks on a line.
Definition: ruler_item.cpp:121
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:388
Class TWO_POINT_GEOMETRY_MANAGER.
the 3d code uses this value
Definition: typeinfo.h:92
VECTOR2< T > Rotate(double aAngle) const
Function Rotate rotates the vector by a given angle.
Definition: vector2d.h:373
double RAD2DECIDEG(double rad)
Definition: trigo.h:196
int midStep
ticks between major ticks
Definition: ruler_item.cpp:72
double divisionBase
Definition: ruler_item.cpp:70
virtual void DrawLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a line.
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:194
const TWO_POINT_GEOMETRY_MANAGER & m_geomMgr
Definition: ruler_item.h:76
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:309
Auxillary items (guides, rule, etc)
T EuclideanNorm() const
Destructor.
Definition: vector2d.h:295
GAL * GetGAL() const
Function GetGAL() Returns the GAL this view is using to draw graphical primitives.
Definition: view.h:177
Definition: common.h:145
BOX2< Vec > & Normalize()
Function Normalize ensures that the height ant width are positive.
Definition: box2.h:117
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
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:196
double PreviewOverlayDeemphAlpha(bool aDeemph=true)
Default alpha of "de-emphasised" features (like previously locked-in lines.
static TICK_FORMAT getTickFormatForScale(double aScale, double &aTickSpace)
Definition: ruler_item.cpp:76
void SetEnd(coord_type x, coord_type y)
Definition: box2.h:213
EDA_UNITS_T g_UserUnit
Global variables definitions.
Definition: common.cpp:56
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:232
void ViewGetLayers(int aLayers[], int &aCount) const override
>
Definition: ruler_item.cpp:225
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...
void SetOrigin(const Vec &pos)
Definition: box2.h:198
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:165
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:68
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...
static void drawCursorStrings(KIGFX::VIEW *aView, const VECTOR2D &aCursor, const VECTOR2D &aRulerVec)
Definition: ruler_item.cpp:42
Class VIEW.
Definition: view.h:58
static const double maxTickDensity
Definition: ruler_item.cpp:37
int majorStep
multiple from the last scale
Definition: ruler_item.cpp:71
Class GAL is the abstract interface for drawing on a 2D-surface.