KiCad PCB EDA Suite
Loading...
Searching...
No Matches
line_ending.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 The KiCad Developers, see AUTHORS.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
24#include <line_ending.h>
25#include <stroke_params.h>
26#include <eda_units.h>
27#include <macros.h>
28#include <string_utils.h>
29#include <trigo.h>
30#include <richio.h>
32#include <plotters/plotter.h>
33
34#include <cmath>
35#include <iterator>
36
37
39{
45};
46
48 static_cast<int>( std::size( LINE_ENDING::s_defaultChoiceOrder ) );
49
50
52{
53 for( int i = 0; i < s_defaultChoiceCount; ++i )
54 {
55 if( s_defaultChoiceOrder[i] == aStyle )
56 return i;
57 }
58
59 return 0;
60}
61
62
64{
65 int autoLen = KiROUND( aLineWidth * DEFAULT_RATIO_LENGTH );
66 int autoWid = KiROUND( aLineWidth * DEFAULT_RATIO_WIDTH );
67
68 int len, wid;
69
70 if( m_length > 0 )
71 len = m_length;
72 else if( m_width > 0 )
73 len = m_width;
74 else
75 len = autoLen;
76
77 if( m_width > 0 )
78 wid = m_width;
79 else if( m_length > 0 )
80 wid = m_length;
81 else
82 wid = autoWid;
83
84 return VECTOR2I( len, wid );
85}
86
87
88int LINE_ENDING::GetShortenDepth( int aLineWidth ) const
89{
91 return 0;
92
93 VECTOR2I sz = GetEffectiveSize( aLineWidth );
94
95 int raw;
96
98 raw = sz.x;
100 raw = 0;
101 else
102 raw = sz.x / 2;
103
104 if( m_stroke.GetWidth() > 0 )
105 raw = std::max( 0, raw - m_stroke.GetWidth() / 2 );
106
107 return raw;
108}
109
110
111int LINE_ENDING::GetCurveOrientationDepth( int aLineWidth ) const
112{
114 return GetEffectiveSize( aLineWidth ).x;
115
116 return GetShortenDepth( aLineWidth );
117}
118
119
120void LINE_ENDING::GetShapes( const VECTOR2I& aPoint, const EDA_ANGLE& aTangent,
121 int aLineWidth, std::vector<VECTOR2I>& aPolygon ) const
122{
124 return;
125
126 VECTOR2I size = GetEffectiveSize( aLineWidth );
127 int sizeX = size.x;
128 int sizeY = size.y;
129
130 aPolygon.clear();
131
132 switch( m_style )
133 {
135 {
136 int halfWidth = sizeY / 2;
137
138 aPolygon.emplace_back( 0, 0 );
139 aPolygon.emplace_back( -sizeX, halfWidth );
140 aPolygon.emplace_back( -sizeX, -halfWidth );
141 aPolygon.emplace_back( 0, 0 );
142 break;
143 }
144
146 {
147 int halfWidth = sizeY / 2;
148
149 aPolygon.emplace_back( -sizeX, -halfWidth );
150 aPolygon.emplace_back( 0, 0 );
151 aPolygon.emplace_back( -sizeX, halfWidth );
152 break;
153 }
154
156 {
157 int halfX = sizeX / 2;
158 int halfY = sizeY / 2;
159 int nSeg = 32;
160
161 for( int i = 0; i <= nSeg; i++ )
162 {
163 double angle = 2.0 * M_PI * i / nSeg;
164 int px = KiROUND( halfX * std::cos( angle ) );
165 int py = KiROUND( halfY * std::sin( angle ) );
166 aPolygon.emplace_back( px, py );
167 }
168
169 break;
170 }
171
173 {
174 int halfX = sizeX / 2;
175 int halfY = sizeY / 2;
176
177 aPolygon.emplace_back( halfX, halfY );
178 aPolygon.emplace_back( halfX, -halfY );
179 aPolygon.emplace_back( -halfX, -halfY );
180 aPolygon.emplace_back( -halfX, halfY );
181 aPolygon.emplace_back( halfX, halfY );
182 break;
183 }
184
186 return;
187 }
188
189 for( VECTOR2I& pt : aPolygon )
190 {
191 RotatePoint( pt, -aTangent );
192 pt += aPoint;
193 }
194}
195
196
197void LINE_ENDING::Draw( KIGFX::GAL& aGal, const VECTOR2I& aPoint, const EDA_ANGLE& aTangent,
198 double aLineWidth, const KIGFX::COLOR4D& aColor ) const
199{
201 return;
202
203 std::vector<VECTOR2I> polygon;
204 GetShapes( aPoint, aTangent, KiROUND( aLineWidth ), polygon );
205
206 if( polygon.empty() )
207 return;
208
210
212 {
213 aGal.SetIsFill( false );
214 aGal.SetIsStroke( true );
215 aGal.SetStrokeColor( aColor );
216 aGal.SetLineWidth( m_stroke.GetWidth() > 0 ? m_stroke.GetWidth() : aLineWidth );
217 aGal.DrawPolyline( polygon );
218 }
219 else if( m_stroke.GetWidth() > 0 )
220 {
221 aGal.SetIsFill( true );
222 aGal.SetFillColor( aColor );
223 aGal.SetIsStroke( true );
224 aGal.SetStrokeColor( aColor );
225 aGal.SetLineWidth( m_stroke.GetWidth() );
226 aGal.DrawPolygon( polygon );
227 }
228 else
229 {
230 aGal.SetIsFill( true );
231 aGal.SetFillColor( aColor );
232 aGal.SetIsStroke( false );
233 aGal.DrawPolygon( polygon );
234 }
235}
236
237
238void LINE_ENDING::Plot( PLOTTER* aPlotter, const VECTOR2I& aPoint, const EDA_ANGLE& aTangent,
239 int aLineWidth, void* aData ) const
240{
242 return;
243
244 std::vector<VECTOR2I> polygon;
245 GetShapes( aPoint, aTangent, aLineWidth, polygon );
246
247 if( polygon.empty() )
248 return;
249
251 {
252 int plotWidth = m_stroke.GetWidth() > 0 ? m_stroke.GetWidth() : aLineWidth;
253 aPlotter->PlotPoly( polygon, FILL_T::NO_FILL, plotWidth, aData );
254 }
255 else if( m_stroke.GetWidth() > 0 )
256 {
257 aPlotter->PlotPoly( polygon, FILL_T::FILLED_SHAPE, m_stroke.GetWidth(), aData );
258 }
259 else
260 {
261 aPlotter->PlotPoly( polygon, FILL_T::FILLED_SHAPE, 0, aData );
262 }
263}
264
265
266bool LINE_ENDING::operator==( const LINE_ENDING& aOther ) const
267{
268 return m_style == aOther.m_style
269 && m_length == aOther.m_length
270 && m_width == aOther.m_width
271 && m_stroke == aOther.m_stroke;
272}
273
274
276{
277 switch( aStyle )
278 {
279 case LINE_ENDING_STYLE::NONE: return wxT( "none" );
280 case LINE_ENDING_STYLE::ARROW: return wxT( "arrow" );
281 case LINE_ENDING_STYLE::CIRCLE: return wxT( "circle" );
282 case LINE_ENDING_STYLE::SQUARE: return wxT( "square" );
283 case LINE_ENDING_STYLE::ARROW_OPEN: return wxT( "arrow_open" );
284 default: return wxT( "none" );
285 }
286}
287
288
290{
291 if( aToken == wxT( "arrow" ) ) return LINE_ENDING_STYLE::ARROW;
292 if( aToken == wxT( "circle" ) ) return LINE_ENDING_STYLE::CIRCLE;
293 if( aToken == wxT( "square" ) ) return LINE_ENDING_STYLE::SQUARE;
294 if( aToken == wxT( "arrow_open" ) ) return LINE_ENDING_STYLE::ARROW_OPEN;
296}
297
298
300 const char* aToken ) const
301{
303 return;
304
305 std::string result = "(" + std::string( aToken ) + " "
307
308 if( m_length > 0 )
309 {
310 result += " (length "
312 + ")";
313 }
314
315 if( m_width > 0 )
316 {
317 result += " (width "
319 + ")";
320 }
321
322 if( m_stroke.GetWidth() > 0 )
323 {
324 result += " (stroke (width "
325 + EDA_UNIT_UTILS::FormatInternalUnits( aIuScale, m_stroke.GetWidth() )
326 + ") (type "
328 + "))";
329 }
330
331 result += ")";
332
333 aOut->Print( "%s", result.c_str() );
334}
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:995
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
Attribute save/restore for GAL attributes.
Abstract interface for drawing on a 2D-surface.
virtual void DrawPolygon(const std::deque< VECTOR2D > &aPointList)
Draw a polygon.
virtual void SetIsFill(bool aIsFillEnabled)
Enable/disable fill.
virtual void SetFillColor(const COLOR4D &aColor)
Set the fill color.
virtual void SetLineWidth(float aLineWidth)
Set the line width.
virtual void DrawPolyline(const std::deque< VECTOR2D > &aPointList)
Draw a polyline.
virtual void SetStrokeColor(const COLOR4D &aColor)
Set the stroke color.
virtual void SetIsStroke(bool aIsStrokeEnabled)
Enable/disable stroked outlines.
static constexpr double DEFAULT_RATIO_LENGTH
int GetShortenDepth(int aLineWidth) const
Return how far the line should be shortened at this ending.
bool operator==(const LINE_ENDING &aOther) const
void Draw(KIGFX::GAL &aGal, const VECTOR2I &aPoint, const EDA_ANGLE &aTangent, double aLineWidth, const KIGFX::COLOR4D &aColor) const
static wxString StyleToToken(LINE_ENDING_STYLE aStyle)
int GetCurveOrientationDepth(int aLineWidth) const
Return how far along a curved body to look when orienting this ending.
LINE_ENDING_STYLE m_style
static const int s_defaultChoiceCount
VECTOR2I GetEffectiveSize(int aLineWidth) const
Return the rendered size per axis, applying auto-sizing when length or width is 0.
static constexpr double DEFAULT_RATIO_WIDTH
static LINE_ENDING_STYLE TokenToStyle(const wxString &aToken)
int m_length
Along-line axis. 0 = auto (ratio * line width).
void GetShapes(const VECTOR2I &aPoint, const EDA_ANGLE &aTangent, int aLineWidth, std::vector< VECTOR2I > &aPolygon) const
Generate ending geometry as polygon vertices at the given point and direction.
static const LINE_ENDING_STYLE s_defaultChoiceOrder[]
Dropdown display order for line ending style choosers.
Definition line_ending.h:38
STROKE_PARAMS m_stroke
static int StyleToChoiceIndex(LINE_ENDING_STYLE aStyle)
Return the dropdown index for the given style, or 0 (NONE) if not found.
void Plot(PLOTTER *aPlotter, const VECTOR2I &aPoint, const EDA_ANGLE &aTangent, int aLineWidth, void *aData=nullptr) const
int m_width
Perpendicular axis. 0 = auto.
void Format(OUTPUTFORMATTER *aOut, const EDA_IU_SCALE &aIuScale, const char *aToken) const
An interface used to output 8 bit text in a convenient way.
Definition richio.h:294
int PRINTF_FUNC_N Print(int nestLevel, const char *fmt,...)
Format and write text to the output stream.
Definition richio.cpp:432
Base plotter engine class.
Definition plotter.h:136
virtual void PlotPoly(const std::vector< VECTOR2I > &aCornerList, FILL_T aFill, int aWidth, void *aData)=0
Draw a polygon ( filled or not ).
static wxString GetLineStyleToken(LINE_STYLE aStyle)
@ NO_FILL
Definition eda_fill.h:30
@ FILLED_SHAPE
Fill with object color.
Definition eda_fill.h:31
LINE_ENDING_STYLE
Line ending styles for graphic lines, arcs, and beziers.
Definition line_ending.h:44
This file contains miscellaneous commonly used macros and functions.
KICOMMON_API std::string FormatInternalUnits(const EDA_IU_SCALE &aIuScale, int aValue, EDA_DATA_TYPE aDataType=EDA_DATA_TYPE::DISTANCE)
Converts aValue from internal units to a string appropriate for writing to file.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
wxString result
Test unit parsing edge cases and error handling.
#define M_PI
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:225
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683