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
26#include <cmath>
27#include <iterator>
28
29#include <stroke_params.h>
30#include <eda_units.h>
31#include <macros.h>
32#include <string_utils.h>
33#include <trigo.h>
34#include <richio.h>
37#include <plotters/plotter.h>
38
39
41{
47};
48
50 static_cast<int>( std::size( LINE_ENDING::s_defaultChoiceOrder ) );
51
52
54{
55 for( int i = 0; i < s_defaultChoiceCount; ++i )
56 {
57 if( s_defaultChoiceOrder[i] == aStyle )
58 return i;
59 }
60
61 return 0;
62}
63
64
66{
67 int autoLen = KiROUND( aLineWidth * DEFAULT_RATIO_LENGTH );
68 int autoWid = KiROUND( aLineWidth * DEFAULT_RATIO_WIDTH );
69
70 int len, wid;
71
72 if( m_length > 0 )
73 len = m_length;
74 else if( m_width > 0 )
75 len = m_width;
76 else
77 len = autoLen;
78
79 if( m_width > 0 )
80 wid = m_width;
81 else if( m_length > 0 )
82 wid = m_length;
83 else
84 wid = autoWid;
85
86 return VECTOR2I( len, wid );
87}
88
89
90int LINE_ENDING::GetShortenDepth( int aLineWidth ) const
91{
93 return 0;
94
95 VECTOR2I sz = GetEffectiveSize( aLineWidth );
96
97 int raw;
98
100 raw = sz.x;
102 raw = 0;
103 else
104 raw = sz.x / 2;
105
106 if( m_stroke.GetWidth() > 0 )
107 raw = std::max( 0, raw - m_stroke.GetWidth() / 2 );
108
109 return raw;
110}
111
112
113int LINE_ENDING::GetCurveOrientationDepth( int aLineWidth ) const
114{
116 return GetEffectiveSize( aLineWidth ).x;
117
118 return GetShortenDepth( aLineWidth );
119}
120
121
122void LINE_ENDING::GetShapes( const VECTOR2I& aPoint, const EDA_ANGLE& aTangent,
123 int aLineWidth, std::vector<VECTOR2I>& aPolygon ) const
124{
126 return;
127
128 VECTOR2I size = GetEffectiveSize( aLineWidth );
129 int sizeX = size.x;
130 int sizeY = size.y;
131
132 aPolygon.clear();
133
134 switch( m_style )
135 {
137 {
138 int halfWidth = sizeY / 2;
139
140 aPolygon.emplace_back( 0, 0 );
141 aPolygon.emplace_back( -sizeX, halfWidth );
142 aPolygon.emplace_back( -sizeX, -halfWidth );
143 aPolygon.emplace_back( 0, 0 );
144 break;
145 }
146
148 {
149 int halfWidth = sizeY / 2;
150
151 aPolygon.emplace_back( -sizeX, -halfWidth );
152 aPolygon.emplace_back( 0, 0 );
153 aPolygon.emplace_back( -sizeX, halfWidth );
154 break;
155 }
156
158 {
159 int halfX = sizeX / 2;
160 int halfY = sizeY / 2;
161 int nSeg = 32;
162
163 for( int i = 0; i <= nSeg; i++ )
164 {
165 double angle = 2.0 * M_PI * i / nSeg;
166 int px = KiROUND( halfX * std::cos( angle ) );
167 int py = KiROUND( halfY * std::sin( angle ) );
168 aPolygon.emplace_back( px, py );
169 }
170
171 break;
172 }
173
175 {
176 int halfX = sizeX / 2;
177 int halfY = sizeY / 2;
178
179 aPolygon.emplace_back( halfX, halfY );
180 aPolygon.emplace_back( halfX, -halfY );
181 aPolygon.emplace_back( -halfX, -halfY );
182 aPolygon.emplace_back( -halfX, halfY );
183 aPolygon.emplace_back( halfX, halfY );
184 break;
185 }
186
188 return;
189 }
190
191 for( VECTOR2I& pt : aPolygon )
192 {
193 RotatePoint( pt, -aTangent );
194 pt += aPoint;
195 }
196}
197
198
199void LINE_ENDING::Draw( KIGFX::GAL& aGal, const VECTOR2I& aPoint, const EDA_ANGLE& aTangent,
200 double aLineWidth, const KIGFX::COLOR4D& aColor ) const
201{
203 return;
204
205 std::vector<VECTOR2I> polygon;
206 GetShapes( aPoint, aTangent, KiROUND( aLineWidth ), polygon );
207
208 if( polygon.empty() )
209 return;
210
212
214 {
215 aGal.SetIsFill( false );
216 aGal.SetIsStroke( true );
217 aGal.SetStrokeColor( aColor );
218 aGal.SetLineWidth( m_stroke.GetWidth() > 0 ? m_stroke.GetWidth() : aLineWidth );
219 aGal.DrawPolyline( polygon );
220 }
221 else if( m_stroke.GetWidth() > 0 )
222 {
223 aGal.SetIsFill( true );
224 aGal.SetFillColor( aColor );
225 aGal.SetIsStroke( true );
226 aGal.SetStrokeColor( aColor );
227 aGal.SetLineWidth( m_stroke.GetWidth() );
228 aGal.DrawPolygon( polygon );
229 }
230 else
231 {
232 aGal.SetIsFill( true );
233 aGal.SetFillColor( aColor );
234 aGal.SetIsStroke( false );
235 aGal.DrawPolygon( polygon );
236 }
237}
238
239
240void LINE_ENDING::Plot( PLOTTER* aPlotter, const VECTOR2I& aPoint, const EDA_ANGLE& aTangent,
241 int aLineWidth, void* aData ) const
242{
244 return;
245
246 std::vector<VECTOR2I> polygon;
247 GetShapes( aPoint, aTangent, aLineWidth, polygon );
248
249 if( polygon.empty() )
250 return;
251
253 {
254 int plotWidth = m_stroke.GetWidth() > 0 ? m_stroke.GetWidth() : aLineWidth;
255 aPlotter->PlotPoly( polygon, FILL_T::NO_FILL, plotWidth, aData );
256 }
257 else if( m_stroke.GetWidth() > 0 )
258 {
259 aPlotter->PlotPoly( polygon, FILL_T::FILLED_SHAPE, m_stroke.GetWidth(), aData );
260 }
261 else
262 {
263 aPlotter->PlotPoly( polygon, FILL_T::FILLED_SHAPE, 0, aData );
264 }
265}
266
267
268bool LINE_ENDING::operator==( const LINE_ENDING& aOther ) const
269{
270 return m_style == aOther.m_style
271 && m_length == aOther.m_length
272 && m_width == aOther.m_width
273 && m_stroke == aOther.m_stroke;
274}
275
276
278{
279 switch( aStyle )
280 {
281 case LINE_ENDING_STYLE::NONE: return wxT( "none" );
282 case LINE_ENDING_STYLE::ARROW: return wxT( "arrow" );
283 case LINE_ENDING_STYLE::CIRCLE: return wxT( "circle" );
284 case LINE_ENDING_STYLE::SQUARE: return wxT( "square" );
285 case LINE_ENDING_STYLE::ARROW_OPEN: return wxT( "arrow_open" );
286 default: return wxT( "none" );
287 }
288}
289
290
292{
293 if( aToken == wxT( "arrow" ) ) return LINE_ENDING_STYLE::ARROW;
294 if( aToken == wxT( "circle" ) ) return LINE_ENDING_STYLE::CIRCLE;
295 if( aToken == wxT( "square" ) ) return LINE_ENDING_STYLE::SQUARE;
296 if( aToken == wxT( "arrow_open" ) ) return LINE_ENDING_STYLE::ARROW_OPEN;
298}
299
300
302 const char* aToken ) const
303{
305 return;
306
307 std::string result = "(" + std::string( aToken ) + " "
309
310 if( m_length > 0 )
311 {
312 result += " (length "
314 + ")";
315 }
316
317 if( m_width > 0 )
318 {
319 result += " (width "
321 + ")";
322 }
323
324 if( m_stroke.GetWidth() > 0 )
325 {
326 result += " (stroke (width "
327 + EDA_UNIT_UTILS::FormatInternalUnits( aIuScale, m_stroke.GetWidth() )
328 + ") (type "
330 + "))";
331 }
332
333 result += ")";
334
335 aOut->Print( "%s", result.c_str() );
336}
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:982
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:40
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:138
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
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition idf_helpers.h:37
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.
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:227
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708