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 <painter.h>
30 #include <view/view.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(
43  KIGFX::VIEW* aView, const VECTOR2D& aCursor, const VECTOR2D& aRulerVec, EDA_UNITS 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(
55  DimensionLabel( wxString::FromUTF8( "θ" ), degs, EDA_UNITS::DEGREES ) );
56 
57  auto temp = aRulerVec;
58  DrawTextNextToCursor( aView, aCursor, -temp, cursorStrings );
59 }
60 
61 
67 {
68  double divisionBase;
69  int majorStep;
70  int midStep;
71 };
72 
73 
74 static TICK_FORMAT getTickFormatForScale( double aScale, double& aTickSpace, EDA_UNITS aUnits )
75 {
76  // simple 1/2/5 scales per decade
77  static std::vector<TICK_FORMAT> tickFormats =
78  {
79  { 2, 10, 5 }, // |....:....|
80  { 2, 5, 0 }, // |....|
81  { 2.5, 2, 0 }, // |.|.|
82  };
83 
84  // could start at a set number of MM, but that's not available in common
85  aTickSpace = 1;
86 
87  // convert to a round (mod-10) number of mils
88  if( aUnits == EDA_UNITS::INCHES )
89  {
90  aTickSpace *= 2.54;
91  }
92 
93  int tickFormat = 0;
94 
95  while( true )
96  {
97  const auto pixelSpace = aTickSpace * aScale;
98 
99  if( pixelSpace >= maxTickDensity )
100  break;
101 
102  tickFormat = ( tickFormat + 1 ) % tickFormats.size();
103  aTickSpace *= tickFormats[tickFormat].divisionBase;
104  }
105 
106  return tickFormats[tickFormat];
107 }
108 
109 
119 void drawTicksAlongLine( KIGFX::VIEW* aView, const VECTOR2D& aOrigin, const VECTOR2D& aLine,
120  double aMinorTickLen, EDA_UNITS aUnits )
121 {
122  VECTOR2D tickLine = aLine.Rotate( -M_PI_2 );
123  auto gal = aView->GetGAL();
124  double tickSpace;
125  TICK_FORMAT tickF = getTickFormatForScale( gal->GetWorldScale(), tickSpace, aUnits );
126  auto rs = aView->GetPainter()->GetSettings();
127 
128  // number of ticks in whole ruler
129  int numTicks = (int) std::ceil( aLine.EuclideanNorm() / tickSpace );
130 
131  // work out which way up the tick labels go
132  double labelAngle = -tickLine.Angle();
133 
134  if( aLine.Angle() > 0 )
135  {
136  gal->SetHorizontalJustify( GR_TEXT_HJUSTIFY_LEFT );
137  }
138  else
139  {
140  gal->SetHorizontalJustify( GR_TEXT_HJUSTIFY_RIGHT );
141  labelAngle += M_PI;
142  }
143 
144  // text and ticks are dimmed
145  gal->SetStrokeColor( rs->GetLayerColor( LAYER_AUX_ITEMS ).WithAlpha( PreviewOverlayDeemphAlpha( true ) ) );
146 
147  const auto labelOffset = tickLine.Resize( aMinorTickLen * ( majorTickLengthFactor + 1 ) );
148 
149  for( int i = 0; i < numTicks; ++i )
150  {
151  const auto tickPos = aOrigin + aLine.Resize( tickSpace * i );
152 
153  double length = aMinorTickLen;
154  bool drawLabel = false;
155 
156  if( i % tickF.majorStep == 0)
157  {
158  drawLabel = true;
159  length *= majorTickLengthFactor;
160  }
161  else if( tickF.midStep && i % tickF.midStep == 0 )
162  {
163  drawLabel = true;
164  length *= midTickLengthFactor;
165  }
166 
167  gal->DrawLine( tickPos, tickPos + tickLine.Resize( length ) );
168 
169  if( drawLabel )
170  {
171  wxString label = DimensionLabel( "", tickSpace * i, aUnits );
172  gal->BitmapText( label, tickPos + labelOffset, labelAngle );
173  }
174  }
175 }
176 
177 
188 void drawBacksideTicks( KIGFX::GAL& aGal, const VECTOR2D& aOrigin,
189  const VECTOR2D& aLine, double aTickLen, int aNumDivisions )
190 {
191  const double backTickSpace = aLine.EuclideanNorm() / aNumDivisions;
192  const auto backTickVec = aLine.Rotate( M_PI_2 ).Resize( aTickLen );
193 
194  for( int i = 0; i < aNumDivisions + 1; ++i )
195  {
196  const auto backTickPos = aOrigin + aLine.Resize( backTickSpace * i );
197  aGal.DrawLine( backTickPos, backTickPos + backTickVec );
198  }
199 }
200 
201 
203  : EDA_ITEM( NOT_USED ), // Never added to anything - just a preview
204  m_geomMgr( aGeomMgr ),
205  m_userUnits( userUnits )
206 {
207 }
208 
209 
211 {
212  BOX2I tmp;
213 
214  tmp.SetOrigin( m_geomMgr.GetOrigin() );
215  tmp.SetEnd( m_geomMgr.GetEnd() );
216  tmp.Normalize();
217  return tmp;
218 }
219 
220 
221 void RULER_ITEM::ViewGetLayers( int aLayers[], int& aCount ) const
222 {
223  aLayers[0] = LAYER_GP_OVERLAY;
224  aCount = 1;
225 }
226 
227 
228 void RULER_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
229 {
230  auto& gal = *aView->GetGAL();
231  auto rs = aView->GetPainter()->GetSettings();
232 
233  VECTOR2D origin = m_geomMgr.GetOrigin();
234  VECTOR2D end = m_geomMgr.GetEnd();
235 
236  gal.SetLineWidth( 1.0 );
237  gal.SetIsStroke( true );
238  gal.SetIsFill( false );
239 
240  gal.SetTextMirrored( false );
241  gal.SetStrokeColor( rs->GetLayerColor( LAYER_AUX_ITEMS ) );
242 
243  gal.ResetTextAttributes();
244 
245  // draw the main line from the origin to cursor
246  gal.DrawLine( origin, end );
247 
248  VECTOR2D rulerVec( end - origin );
249 
250  // constant text size on screen
251  SetConstantGlyphHeight( gal, 14.0 );
252 
253  drawCursorStrings( aView, end, rulerVec, m_userUnits );
254 
255  // tick label size
256  SetConstantGlyphHeight( gal, 12.0 );
257 
258  // basic tick size
259  const double minorTickLen = 5.0 / gal.GetWorldScale();
260 
261  drawTicksAlongLine( aView, origin, rulerVec, minorTickLen, m_userUnits );
262 
263  gal.SetStrokeColor( rs->GetLayerColor( LAYER_AUX_ITEMS ).WithAlpha( PreviewOverlayDeemphAlpha( true ) ) );
264  drawBacksideTicks( gal, origin, rulerVec, minorTickLen * majorTickLengthFactor, 2 );
265 
266  // draw the back of the origin "crosshair"
267  gal.DrawLine( origin, origin + rulerVec.Resize( -minorTickLen * midTickLengthFactor ) );
268 }
EDA_UNITS
Definition: common.h:198
const BOX2I ViewBBox() const override
Definition: ruler_item.cpp:210
wxString DimensionLabel(const wxString &prefix, double aVal, EDA_UNITS aUnits)
Get a formatted string showing a dimension to a sane precision with an optional prefix and unit suffi...
Implementation of conversion functions that require both schematic and board internal units.
the 3d code uses this value
Definition: typeinfo.h:80
#define M_PI_2
Definition: transline.cpp:36
double RAD2DECIDEG(double rad)
Definition: trigo.h:219
GAL * GetGAL() const
Function GetGAL() Returns the GAL this view is using to draw graphical primitives.
Definition: view.h:180
int midStep
ticks between major ticks
Definition: ruler_item.cpp:70
double divisionBase
Definition: ruler_item.cpp:68
virtual void DrawLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a line.
RULER_ITEM(const TWO_POINT_GEOMETRY_MANAGER &m_geomMgr, EDA_UNITS userUnits)
Definition: ruler_item.cpp:202
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:188
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:199
const TWO_POINT_GEOMETRY_MANAGER & m_geomMgr
Definition: ruler_item.h:82
static const double majorTickLengthFactor
Definition: ruler_item.cpp:39
Auxiliary items (guides, rule, etc)
BOX2< Vec > & Normalize()
Function Normalize ensures that the height ant width are positive.
Definition: box2.h:128
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.
double Angle() const
Function Angle computes the angle of the vector.
Definition: vector2d.h:313
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:224
VECTOR2< T > Resize(T aNewLength) const
Function Resize returns a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:392
virtual RENDER_SETTINGS * GetSettings()=0
Function GetAdapter Returns pointer to current settings that are going to be used when drawing items.
VECTOR2< T > Rotate(double aAngle) const
Function Rotate rotates the vector by a given angle.
Definition: vector2d.h:377
void ViewGetLayers(int aLayers[], int &aCount) const override
Definition: ruler_item.cpp:221
Board layer functions and definitions.
static void drawCursorStrings(KIGFX::VIEW *aView, const VECTOR2D &aCursor, const VECTOR2D &aRulerVec, EDA_UNITS aUnits)
Definition: ruler_item.cpp:42
void drawTicksAlongLine(KIGFX::VIEW *aView, const VECTOR2D &aOrigin, const VECTOR2D &aLine, double aMinorTickLen, EDA_UNITS aUnits)
Draw labelled ticks on a line.
Definition: ruler_item.cpp:119
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:209
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:159
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:66
static TICK_FORMAT getTickFormatForScale(double aScale, double &aTickSpace, EDA_UNITS aUnits)
Definition: ruler_item.cpp:74
T EuclideanNorm() const
Destructor.
Definition: vector2d.h:299
VIEW.
Definition: view.h:61
static const double maxTickDensity
Definition: ruler_item.cpp:37
int majorStep
multiple from the last scale
Definition: ruler_item.cpp:69
void ViewDraw(int aLayer, KIGFX::VIEW *aView) const override final
Definition: ruler_item.cpp:228
Class GAL is the abstract interface for drawing on a 2D-surface.