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 
31 #include <base_units.h>
32 #include <common.h>
33 
34 using namespace KIGFX::PREVIEW;
35 
36 static const double maxTickDensity = 10.0; // min pixels between tick marks
37 static const double midTickLengthFactor = 1.5;
38 static const double majorTickLengthFactor = 2.5;
39 
40 
41 static void drawCursorStrings( KIGFX::GAL& aGal, const VECTOR2D& aCursor,
42  const VECTOR2D& aRulerVec )
43 {
44  // draw the cursor labels
45  std::vector<wxString> cursorStrings;
46 
47  cursorStrings.push_back( DimensionLabel( "r", aRulerVec.EuclideanNorm(), g_UserUnit ) );
48 
49  double degs = RAD2DECIDEG( -aRulerVec.Angle() );
50  cursorStrings.push_back( DimensionLabel( "θ", degs, DEGREES ) );
51 
52  for( auto& str: cursorStrings )
53  {
54  // FIXME: remove spaces that choke OpenGL lp:1668455
55  str.erase( std::remove( str.begin(), str.end(), ' ' ), str.end() );
56  }
57 
58  auto temp = aRulerVec;
59  DrawTextNextToCursor( aGal, aCursor, -temp, cursorStrings );
60 }
61 
62 
68 {
69  double divisionBase;
70  int majorStep;
71  int midStep;
72 };
73 
74 
75 static TICK_FORMAT getTickFormatForScale( double aScale, double& aTickSpace )
76 {
77  // simple 1/2/5 scales per decade
78  static std::vector<TICK_FORMAT> tickFormats =
79  {
80  { 2, 10, 5 }, // |....:....|
81  { 2, 5, 0 }, // |....|
82  { 2.5, 2, 0 }, // |.|.|
83  };
84 
85  // could start at a set number of MM, but that's not available in common
86  aTickSpace = 1;
87 
88  // convert to a round (mod-10) number of mils
89  if( g_UserUnit == INCHES )
90  {
91  aTickSpace *= 2.54;
92  }
93 
94  int tickFormat = 0;
95 
96  while( true )
97  {
98  const auto pixelSpace = aTickSpace * aScale;
99 
100  if( pixelSpace >= maxTickDensity )
101  break;
102 
103  tickFormat = ( tickFormat + 1 ) % tickFormats.size();
104  aTickSpace *= tickFormats[tickFormat].divisionBase;
105  }
106 
107  return tickFormats[tickFormat];
108 }
109 
110 
120 void drawTicksAlongLine( KIGFX::GAL& aGal, const VECTOR2D& aOrigin,
121  const VECTOR2D& aLine, double aMinorTickLen )
122 {
123  VECTOR2D tickLine = aLine.Rotate( -M_PI_2 );
124 
125  double tickSpace;
126  TICK_FORMAT tickF = getTickFormatForScale( aGal.GetWorldScale(), tickSpace );
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  {
137  }
138  else
139  {
141  labelAngle += M_PI;
142  }
143 
144  // text and ticks are dimmed
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  aGal.DrawLine( tickPos, tickPos + tickLine.Resize( length ) );
168 
169  if( drawLabel )
170  {
171  wxString label = DimensionLabel( "", tickSpace * i, g_UserUnit );
172 
173  // FIXME: spaces choke OpenGL lp:1668455
174  label.erase( std::remove( label.begin(), label.end(), ' ' ), label.end() );
175 
176  aGal.BitmapText( label, tickPos + labelOffset, labelAngle );
177  }
178  }
179 }
180 
181 
192 void drawBacksideTicks( KIGFX::GAL& aGal, const VECTOR2D& aOrigin,
193  const VECTOR2D& aLine, double aTickLen, int aNumDivisions )
194 {
195  const double backTickSpace = aLine.EuclideanNorm() / aNumDivisions;
196  const auto backTickVec = aLine.Rotate( M_PI_2 ).Resize( aTickLen );
197 
198  for( int i = 0; i < aNumDivisions + 1; ++i )
199  {
200  const auto backTickPos = aOrigin + aLine.Resize( backTickSpace * i );
201  aGal.DrawLine( backTickPos, backTickPos + backTickVec );
202  }
203 }
204 
205 
207  EDA_ITEM( NOT_USED ), // Never added to anything - just a preview
208  m_geomMgr( aGeomMgr )
209 {}
210 
211 
213 {
214  BOX2I tmp;
215 
216  tmp.SetOrigin( m_geomMgr.GetOrigin() );
217  tmp.SetEnd( m_geomMgr.GetEnd() );
218  tmp.Normalize();
219  return tmp;
220 }
221 
222 
223 void RULER_ITEM::ViewGetLayers( int aLayers[], int& aCount ) const
224 {
225  aLayers[0] = ITEM_GAL_LAYER( GP_OVERLAY );
226  aCount = 1;
227 }
228 
229 
230 void RULER_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
231 {
232  auto& gal = *aView->GetGAL();
233 
234  const auto origin = m_geomMgr.GetOrigin();
235  const auto end = m_geomMgr.GetEnd();
236 
237  gal.SetLineWidth( 1.0 );
238  gal.SetIsStroke( true );
239  gal.SetIsFill( false );
240  gal.SetStrokeColor( PreviewOverlayDefaultColor() );
241 
242  // draw the main line from the origin to cursor
243  gal.DrawLine( origin, end );
244 
245  VECTOR2D rulerVec( end - origin );
246 
247  // constant text size on screen
248  SetConstantGlyphHeight( gal, 12.0 );
249 
250  drawCursorStrings( gal, end, rulerVec );
251 
252  // tick label size
253  SetConstantGlyphHeight( gal, 10.0 );
254 
255  // basic tick size
256  const double minorTickLen = 5.0 / gal.GetWorldScale();
257 
258  drawTicksAlongLine( gal, origin, rulerVec, minorTickLen );
259 
260  gal.SetStrokeColor( PreviewOverlayDefaultColor().WithAlpha( PreviewOverlayDeemphAlpha( true ) ) );
261  drawBacksideTicks( gal, origin, rulerVec, minorTickLen * majorTickLengthFactor, 2 );
262 
263  // draw the back of the origin "crosshair"
264  gal.DrawLine( origin, origin + rulerVec.Resize( -minorTickLen * midTickLengthFactor ) );
265 }
const BOX2I ViewBBox() const override
>
Definition: ruler_item.cpp:212
RULER_ITEM(const TWO_POINT_GEOMETRY_MANAGER &m_geomMgr)
Definition: ruler_item.cpp:206
virtual void BitmapText(const wxString &aText, const VECTOR2D &aPosition, double aRotationAngle)
Draws a text using a bitmap font.
Implementation of conversion functions that require both schematic and board internal units...
double GetWorldScale() const
Get the world scale.
VECTOR2< T > Resize(T aNewLength) const
Function Resize returns a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:388
COLOR4D PreviewOverlayDefaultColor()
The default fill/stroke color of preview overlay items.
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:71
double divisionBase
Definition: ruler_item.cpp:69
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:192
const TWO_POINT_GEOMETRY_MANAGER & m_geomMgr
Definition: ruler_item.h:76
static const double majorTickLengthFactor
Definition: ruler_item.cpp:38
double Angle() const
Function Angle computes the angle of the vector.
Definition: vector2d.h:309
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:37
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:75
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 void SetStrokeColor(const COLOR4D &aColor)
Set the stroke color.
#define ITEM_GAL_LAYER(layer)
macro for obtaining layer number for specific item (eg. pad or text)
void ViewDraw(int aLayer, KIGFX::VIEW *aView) const overridefinal
>
Definition: ruler_item.cpp:230
void ViewGetLayers(int aLayers[], int &aCount) const override
>
Definition: ruler_item.cpp:223
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
void drawTicksAlongLine(KIGFX::GAL &aGal, const VECTOR2D &aOrigin, const VECTOR2D &aLine, double aMinorTickLen)
Draw labelled ticks on a line.
Definition: ruler_item.cpp:120
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:151
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:67
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...
void DrawTextNextToCursor(KIGFX::GAL &aGal, const VECTOR2D &aCursorPos, const VECTOR2D &aTextQuadrant, const std::vector< wxString > &aStrings)
Draw strings next to the cursor.
general purpose overlay
void SetHorizontalJustify(const EDA_TEXT_HJUSTIFY_T aHorizontalJustify)
Set the horizontal justify for text drawing.
Class VIEW.
Definition: view.h:58
static const double maxTickDensity
Definition: ruler_item.cpp:36
int majorStep
multiple from the last scale
Definition: ruler_item.cpp:70
static void drawCursorStrings(KIGFX::GAL &aGal, const VECTOR2D &aCursor, const VECTOR2D &aRulerVec)
Definition: ruler_item.cpp:41
Class GAL is the abstract interface for drawing on a 2D-surface.