KiCad PCB EDA Suite
Loading...
Searching...
No Matches
stroke_params.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 modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * 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, see <https://www.gnu.org/licenses/>.
18 */
19
20#include "stroke_params.h"
22
23#include <base_units.h>
24#include <bitmaps.h>
25#include <charconv>
26#include <string_utils.h>
27#include <render_settings.h>
29#include <geometry/shape.h>
30#include <geometry/shape_rect.h>
35#include <macros.h>
36#include <trigo.h>
37#include <widgets/msgpanel.h>
38
39using namespace STROKEPARAMS_T;
40
41
42const std::map<LINE_STYLE, struct LINE_STYLE_DESC> lineTypeNames = {
43 { LINE_STYLE::SOLID, { _( "Solid" ), BITMAPS::stroke_solid } },
44 { LINE_STYLE::DASH, { _( "Dashed" ), BITMAPS::stroke_dash } },
45 { LINE_STYLE::DOT, { _( "Dotted" ), BITMAPS::stroke_dot } },
46 { LINE_STYLE::DASHDOT, { _( "Dash-Dot" ), BITMAPS::stroke_dashdot } },
47 { LINE_STYLE::DASHDOTDOT, { _( "Dash-Dot-Dot" ), BITMAPS::stroke_dashdotdot } }
48};
49
50
51void STROKE_PARAMS::Stroke( const SHAPE* aShape, LINE_STYLE aLineStyle, int aWidth,
52 const KIGFX::RENDER_SETTINGS* aRenderSettings,
53 const std::function<void( const VECTOR2I& a, const VECTOR2I& b )>& aStroker )
54{
55 double strokes[6] = { aWidth * 1.0, aWidth * 1.0, aWidth * 1.0, aWidth * 1.0, aWidth * 1.0, aWidth * 1.0 };
56 int wrapAround = 6;
57
58 switch( aLineStyle )
59 {
61 strokes[0] = aRenderSettings->GetDashLength( aWidth );
62 strokes[1] = aRenderSettings->GetGapLength( aWidth );
63 wrapAround = 2;
64 break;
65 case LINE_STYLE::DOT:
66 strokes[0] = aRenderSettings->GetDotLength( aWidth );
67 strokes[1] = aRenderSettings->GetGapLength( aWidth );
68 wrapAround = 2;
69 break;
71 strokes[0] = aRenderSettings->GetDashLength( aWidth );
72 strokes[1] = aRenderSettings->GetGapLength( aWidth );
73 strokes[2] = aRenderSettings->GetDotLength( aWidth );
74 strokes[3] = aRenderSettings->GetGapLength( aWidth );
75 wrapAround = 4;
76 break;
78 strokes[0] = aRenderSettings->GetDashLength( aWidth );
79 strokes[1] = aRenderSettings->GetGapLength( aWidth );
80 strokes[2] = aRenderSettings->GetDotLength( aWidth );
81 strokes[3] = aRenderSettings->GetGapLength( aWidth );
82 strokes[4] = aRenderSettings->GetDotLength( aWidth );
83 strokes[5] = aRenderSettings->GetGapLength( aWidth );
84 wrapAround = 6;
85 break;
86 default:
87 UNIMPLEMENTED_FOR( lineTypeNames.at( aLineStyle ).name );
88 }
89
90 switch( aShape->Type() )
91 {
92 case SH_RECT:
93 {
94 SHAPE_LINE_CHAIN outline = static_cast<const SHAPE_RECT*>( aShape )->Outline();
95 std::set<size_t> arcsHandled;
96
97 for( int ii = 0; ii < outline.SegmentCount(); ++ii )
98 {
99 if( outline.IsArcSegment( ii ) )
100 {
101 size_t arcIndex = outline.ArcIndex( ii );
102
103 if( !arcsHandled.contains( arcIndex ) )
104 {
105 arcsHandled.insert( arcIndex );
106 const SHAPE_ARC& arc( outline.Arc( arcIndex ) );
107 STROKE_PARAMS::Stroke( &arc, aLineStyle, aWidth, aRenderSettings, aStroker );
108 }
109 }
110 else
111 {
112 const SEG& seg = outline.GetSegment( ii );
113 SHAPE_SEGMENT line( seg.A, seg.B );
114 STROKE_PARAMS::Stroke( &line, aLineStyle, aWidth, aRenderSettings, aStroker );
115 }
116 }
117
118 for( int jj = 0; jj < (int) outline.ArcCount(); ++jj )
119 {
120 const SHAPE_ARC& arc( outline.Arc( jj ) );
121 STROKE_PARAMS::Stroke( &arc, aLineStyle, aWidth, aRenderSettings, aStroker );
122 }
123
124 break;
125 }
126
127 case SH_SIMPLE:
128 {
129 const SHAPE_SIMPLE* poly = static_cast<const SHAPE_SIMPLE*>( aShape );
130
131 for( size_t ii = 0; ii < poly->GetSegmentCount(); ++ii )
132 {
133 SEG seg = poly->GetSegment( (int) ii );
134 SHAPE_SEGMENT line( seg.A, seg.B );
135 STROKE_PARAMS::Stroke( &line, aLineStyle, aWidth, aRenderSettings, aStroker );
136 }
137
138 break;
139 }
140
141 case SH_LINE_CHAIN:
142 {
143 const SHAPE_LINE_CHAIN* chain = static_cast<const SHAPE_LINE_CHAIN*>( aShape );
144
145 double patternLength = 0.0;
146
147 for( int ii = 0; ii < wrapAround; ++ii )
148 patternLength += strokes[ii];
149
150 // A zero-width shape makes every element zero long, and the walk would never advance.
151 if( patternLength <= 0.0 )
152 break;
153
154 int element = 0;
155 double remaining = strokes[0];
156
157 for( int ii = 0; ii < chain->SegmentCount(); ++ii )
158 {
159 SEG seg = chain->CSegment( ii );
160 VECTOR2D segVec( seg.B - seg.A );
161 double segLength = segVec.EuclideanNorm();
162
163 if( segLength == 0.0 )
164 continue;
165
166 // The pattern carries across the vertices, so calculations MUST be done in
167 // doubles to keep from accumulating rounding errors along the chain.
168 VECTOR2D step = segVec / segLength;
169 VECTOR2D start( seg.A );
170 double walked = 0.0;
171
172 while( walked < segLength )
173 {
174 double length = std::min( remaining, segLength - walked );
175 VECTOR2D next = start + step * length;
176
177 if( element % 2 == 0 )
178 aStroker( KiROUND( start ), KiROUND( next ) );
179
180 walked += length;
181 remaining -= length;
182 start = next;
183
184 if( remaining <= 0.0 )
185 {
186 element++;
187 remaining = strokes[element % wrapAround];
188 }
189 }
190 }
191
192 break;
193 }
194
195 case SH_SEGMENT:
196 {
197 const SHAPE_SEGMENT* line = static_cast<const SHAPE_SEGMENT*>( aShape );
198
199 VECTOR2D start = line->GetSeg().A;
200 VECTOR2D end = line->GetSeg().B;
201 BOX2I clip( start, KiROUND( end.x - start.x, end.y - start.y ) );
202 clip.Normalize();
203
204 double theta = atan2( end.y - start.y, end.x - start.x );
205
206 for( size_t i = 0; i < 10000; ++i )
207 {
208 // Calculations MUST be done in doubles to keep from accumulating rounding
209 // errors as we go.
210 VECTOR2D next( start.x + strokes[ i % wrapAround ] * cos( theta ),
211 start.y + strokes[ i % wrapAround ] * sin( theta ) );
212
213 // Drawing each segment can be done rounded to ints.
214 VECTOR2I a = KiROUND( start );
215 VECTOR2I b = KiROUND( next );
216
217 if( ClipLine( &clip, a.x, a.y, b.x, b.y ) )
218 break;
219 else if( i % 2 == 0 )
220 aStroker( a, b );
221
222 start = next;
223 }
224
225 break;
226 }
227
228 case SH_ARC:
229 {
230 const SHAPE_ARC* arc = static_cast<const SHAPE_ARC*>( aShape );
231
232 double r = arc->GetRadius();
233 double C = 2.0 * M_PI * r;
234 VECTOR2I center = arc->GetCenter();
235 VECTOR2D startRadial( arc->GetP0() - center );
236 EDA_ANGLE startAngle( startRadial );
237 VECTOR2D endRadial( arc->GetP1() - center );
238 EDA_ANGLE arcEndAngle( endRadial );
239
240 if( arcEndAngle == startAngle )
241 arcEndAngle = startAngle + ANGLE_360; // ring, not null
242
243 if( startAngle > arcEndAngle )
244 {
245 if( arcEndAngle < ANGLE_0 )
246 arcEndAngle = arcEndAngle.Normalize();
247 else
248 startAngle = startAngle.Normalize() - ANGLE_360;
249 }
250
251 wxASSERT( startAngle < arcEndAngle );
252
253 EDA_ANGLE angleIncrement = EDA_ANGLE( 0.5, DEGREES_T );
254
255 for( size_t i = 0; i < 10000 && startAngle < arcEndAngle; ++i )
256 {
257 EDA_ANGLE theta = ANGLE_360 * strokes[ i % wrapAround ] / C;
258 EDA_ANGLE endAngle = std::min( startAngle + theta, arcEndAngle );
259
260 if( i % 2 == 0 )
261 {
262 if( ( ( aLineStyle == LINE_STYLE::DASHDOT || aLineStyle == LINE_STYLE::DASHDOTDOT )
263 && i % wrapAround == 0 )
264 || aLineStyle == LINE_STYLE::DASH )
265 {
266 for( EDA_ANGLE currentAngle = startAngle; currentAngle < endAngle;
267 currentAngle += angleIncrement )
268 {
269 VECTOR2I a( center.x + KiROUND( r * currentAngle.Cos() ),
270 center.y + KiROUND( r * currentAngle.Sin() ) );
271
272 // Calculate the next angle step, ensuring it doesn't exceed the endAngle
273 EDA_ANGLE nextAngle = currentAngle + angleIncrement;
274
275 if( nextAngle > endAngle )
276 {
277 nextAngle = endAngle; // Set nextAngle to endAngle if it exceeds
278 }
279
280 VECTOR2I b( center.x + KiROUND( r * nextAngle.Cos() ),
281 center.y + KiROUND( r * nextAngle.Sin() ) );
282
283 aStroker( a, b ); // Draw the segment as an arc
284 }
285 }
286 else
287 {
288 VECTOR2I a( center.x + KiROUND( r * startAngle.Cos() ),
289 center.y + KiROUND( r * startAngle.Sin() ) );
290 VECTOR2I b( center.x + KiROUND( r * endAngle.Cos() ),
291 center.y + KiROUND( r * endAngle.Sin() ) );
292
293 aStroker( a, b );
294 }
295 }
296
297 startAngle = endAngle;
298 }
299
300 break;
301 }
302
303 case SH_ELLIPSE:
304 {
305 const SHAPE_ELLIPSE* ellipse = static_cast<const SHAPE_ELLIPSE*>( aShape );
306
307 VECTOR2I center = ellipse->GetCenter();
308 double a = ellipse->GetMajorRadius();
309 double b = ellipse->GetMinorRadius();
310 EDA_ANGLE rotation = ellipse->GetRotation();
311 double cosRot = rotation.Cos();
312 double sinRot = rotation.Sin();
313
314 EDA_ANGLE startAngle = ellipse->IsArc() ? ellipse->GetStartAngle() : ANGLE_0;
315 EDA_ANGLE endAngle = ellipse->IsArc() ? ellipse->GetEndAngle() : ANGLE_360;
316
317 if( endAngle == startAngle )
318 endAngle = startAngle + ANGLE_360;
319
320 if( startAngle > endAngle )
321 {
322 if( endAngle < ANGLE_0 )
323 endAngle = endAngle.Normalize();
324 else
325 startAngle = startAngle.Normalize() - ANGLE_360;
326 }
327
328 auto evalRad = [&]( double thetaRad ) -> VECTOR2D
329 {
330 double x = a * std::cos( thetaRad );
331 double y = b * std::sin( thetaRad );
332 return VECTOR2D( center.x + x * cosRot - y * sinRot, center.y + x * sinRot + y * cosRot );
333 };
334
335 auto evalAngle = [&]( const EDA_ANGLE& theta ) -> VECTOR2I
336 {
337 double x = a * theta.Cos();
338 double y = b * theta.Sin();
339 return VECTOR2I( center.x + KiROUND( x * cosRot - y * sinRot ),
340 center.y + KiROUND( x * sinRot + y * cosRot ) );
341 };
342
343 // Place strokes by arclength rather than angle so the pattern stays
344 // visually uniform on highly curved ellipses.
345 const double startRad = startAngle.AsRadians();
346 const double endRad = endAngle.AsRadians();
347 const int LUT_SIZE = 1024;
348 std::vector<double> arcLens( LUT_SIZE + 1 );
349
350 arcLens[0] = 0.0;
351 VECTOR2D prev = evalRad( startRad );
352
353 for( int j = 1; j <= LUT_SIZE; ++j )
354 {
355 double t = startRad + ( endRad - startRad ) * j / LUT_SIZE;
356 VECTOR2D curr = evalRad( t );
357 arcLens[j] = arcLens[j - 1] + ( curr - prev ).EuclideanNorm();
358 prev = curr;
359 }
360
361 const double totalLen = arcLens[LUT_SIZE];
362
363 auto angleAtLen = [&]( double s ) -> double
364 {
365 if( s >= totalLen )
366 return endRad;
367
368 if( s <= 0.0 )
369 return startRad;
370
371 auto it = std::upper_bound( arcLens.begin(), arcLens.end(), s );
372 int idx = std::distance( arcLens.begin(), it ) - 1;
373
374 double seg = arcLens[idx + 1] - arcLens[idx];
375 double frac = ( seg > 0 ) ? ( s - arcLens[idx] ) / seg : 0.0;
376
377 double t0 = startRad + ( endRad - startRad ) * idx / LUT_SIZE;
378 double t1 = startRad + ( endRad - startRad ) * ( idx + 1 ) / LUT_SIZE;
379
380 return t0 + frac * ( t1 - t0 );
381 };
382
383 EDA_ANGLE angleIncrement( 0.5, DEGREES_T );
384 double currentLen = 0.0;
385
386 for( size_t i = 0; i < 10000 && currentLen < totalLen; ++i )
387 {
388 double targetLen = std::min( currentLen + strokes[i % wrapAround], totalLen );
389
390 if( i % 2 == 0 )
391 {
392 EDA_ANGLE elemStart( angleAtLen( currentLen ), RADIANS_T );
393 EDA_ANGLE elemEnd( angleAtLen( targetLen ), RADIANS_T );
394
395 for( EDA_ANGLE c = elemStart; c < elemEnd; c += angleIncrement )
396 {
397 EDA_ANGLE n = std::min( c + angleIncrement, elemEnd );
398 aStroker( evalAngle( c ), evalAngle( n ) );
399 }
400 }
401
402 currentLen = targetLen;
403 }
404
405 break;
406 }
407
408 case SH_CIRCLE:
409 // A circle is always filled. A ring is represented by a 360° arc.
411
412 default:
414 }
415}
416
417
419{
420 wxString token;
421
422 switch( aStyle )
423 {
424 case LINE_STYLE::DASH: token = wxT( "dash" ); break;
425 case LINE_STYLE::DOT: token = wxT( "dot" ); break;
426 case LINE_STYLE::DASHDOT: token = wxT( "dash_dot" ); break;
427 case LINE_STYLE::DASHDOTDOT: token = wxT( "dash_dot_dot" ); break;
428 case LINE_STYLE::SOLID: token = wxT( "solid" ); break;
429 case LINE_STYLE::DEFAULT: token = wxT( "default" ); break;
430 }
431
432 return token;
433}
434
435
437 std::vector<MSG_PANEL_ITEM>& aList,
438 bool aIncludeStyle, bool aIncludeWidth )
439{
440 if( aIncludeStyle )
441 {
442 wxString msg = _( "Default" );
443
444 for( const auto& [ lineStyle, lineStyleDesc ] : lineTypeNames )
445 {
446 if( lineStyle == GetLineStyle() )
447 {
448 msg = lineStyleDesc.name;
449 break;
450 }
451 }
452
453 aList.emplace_back( _( "Line Style" ), msg );
454 }
455
456 if( aIncludeWidth )
457 aList.emplace_back( _( "Line Width" ), aUnitsProvider->MessageTextFromValue( GetWidth() ) );
458}
459
460
462{
463 if( m_width != aOther.m_width )
464 return m_width < aOther.m_width;
465
466 if( m_lineStyle != aOther.m_lineStyle )
467 return m_lineStyle < aOther.m_lineStyle;
468
469 return m_color < aOther.m_color;
470}
471
472
473void STROKE_PARAMS::Format( OUTPUTFORMATTER* aFormatter, const EDA_IU_SCALE& aIuScale ) const
474{
475 wxASSERT( aFormatter != nullptr );
476
478 {
479 aFormatter->Print( "(stroke (width %s) (type %s))",
480 EDA_UNIT_UTILS::FormatInternalUnits( aIuScale, GetWidth() ).c_str(),
482 }
483 else
484 {
485 aFormatter->Print( "(stroke (width %s) (type %s) (color %d %d %d %s))",
486 EDA_UNIT_UTILS::FormatInternalUnits( aIuScale, GetWidth() ).c_str(),
488 KiROUND( GetColor().r * 255.0 ),
489 KiROUND( GetColor().g * 255.0 ),
490 KiROUND( GetColor().b * 255.0 ),
491 FormatDouble2Str( GetColor().a ).c_str() );
492 }
493}
494
495
497{
498 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
499 {
500 if( token != T_LEFT )
501 Expecting( T_LEFT );
502
503 token = NextTok();
504
505 switch( token )
506 {
507 case T_width:
508 aStroke.SetWidth( KiROUND( parseDouble( "stroke width" ) * m_iuPerMM ) );
509 NeedRIGHT();
510 break;
511
512 case T_type:
513 {
514 token = NextTok();
515
516 switch( token )
517 {
518 case T_dash: aStroke.SetLineStyle( LINE_STYLE::DASH ); break;
519 case T_dot: aStroke.SetLineStyle( LINE_STYLE::DOT ); break;
520 case T_dash_dot: aStroke.SetLineStyle( LINE_STYLE::DASHDOT ); break;
521 case T_dash_dot_dot: aStroke.SetLineStyle( LINE_STYLE::DASHDOTDOT ); break;
522 case T_solid: aStroke.SetLineStyle( LINE_STYLE::SOLID ); break;
523 case T_default: aStroke.SetLineStyle( LINE_STYLE::DEFAULT ); break;
524 default:
525 Expecting( "solid, dash, dash_dot, dash_dot_dot, dot or default" );
526 }
527
528 NeedRIGHT();
529 break;
530 }
531
532 case T_color:
533 {
534 KIGFX::COLOR4D color;
535
536 color.r = parseInt( "red" ) / 255.0;
537 color.g = parseInt( "green" ) / 255.0;
538 color.b = parseInt( "blue" ) / 255.0;
539 color.a = std::clamp( parseDouble( "alpha" ), 0.0, 1.0 );
540
541 aStroke.SetColor( color );
542 NeedRIGHT();
543 break;
544 }
545
546 default:
547 Expecting( "width, type, or color" );
548 }
549 }
550}
551
552
553int STROKE_PARAMS_PARSER::parseInt( const char* aText )
554{
555 T token = NextTok();
556
557 if( token != T_NUMBER )
558 Expecting( aText );
559
560 return atoi( CurText() );
561}
562
563
564double STROKE_PARAMS_PARSER::parseDouble( const char* aText )
565{
566 T token = NextTok();
567
568 if( token != T_NUMBER )
569 Expecting( aText );
570
571 return DSNLEXER::parseDouble();
572}
@ stroke_dashdotdot
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:982
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition box2.h:143
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
Definition dsnlexer.cpp:867
EDA_ANGLE Normalize()
Definition eda_angle.h:228
double Sin() const
Definition eda_angle.h:177
double AsRadians() const
Definition eda_angle.h:119
double Cos() const
Definition eda_angle.h:196
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
double r
Red component.
Definition color4d.h:391
double g
Green component.
Definition color4d.h:392
double a
Alpha component.
Definition color4d.h:394
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:400
double b
Blue component.
Definition color4d.h:393
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
double GetGapLength(int aLineWidth) const
double GetDotLength(int aLineWidth) const
double GetDashLength(int aLineWidth) 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
Definition seg.h:38
VECTOR2I A
Definition seg.h:45
VECTOR2I B
Definition seg.h:46
const VECTOR2I & GetP1() const
Definition shape_arc.h:115
double GetRadius() const
const VECTOR2I & GetP0() const
Definition shape_arc.h:114
const VECTOR2I & GetCenter() const
SHAPE_TYPE Type() const
Return the type of the shape.
Definition shape.h:96
int GetMajorRadius() const
const VECTOR2I & GetCenter() const
const EDA_ANGLE & GetStartAngle() const
const EDA_ANGLE & GetEndAngle() const
const EDA_ANGLE & GetRotation() const
bool IsArc() const
int GetMinorRadius() const
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SHAPE_ARC & Arc(size_t aArc) const
ssize_t ArcIndex(size_t aSegment) const
Return the arc index for the given segment index.
virtual const SEG GetSegment(int aIndex) const override
int SegmentCount() const
Return the number of segments in this line chain.
size_t ArcCount() const
bool IsArcSegment(size_t aSegment) const
const SEG & GetSeg() const
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
virtual const SEG GetSegment(int aIndex) const override
virtual size_t GetSegmentCount() const override
An abstract shape on 2D plane.
Definition shape.h:124
int parseInt(const char *aText)
void ParseStroke(STROKE_PARAMS &aStroke)
double parseDouble(const char *aText)
Simple container to manage line stroke parameters.
int GetWidth() const
void SetLineStyle(LINE_STYLE aLineStyle)
LINE_STYLE m_lineStyle
void SetWidth(int aWidth)
void SetColor(const KIGFX::COLOR4D &aColor)
void GetMsgPanelInfo(UNITS_PROVIDER *aUnitsProvider, std::vector< MSG_PANEL_ITEM > &aList, bool aIncludeStyle=true, bool aIncludeWidth=true)
STROKE_PARAMS(int aWidth=0, LINE_STYLE aLineStyle=LINE_STYLE::DEFAULT, const KIGFX::COLOR4D &aColor=KIGFX::COLOR4D::UNSPECIFIED)
LINE_STYLE GetLineStyle() const
bool operator<(const STROKE_PARAMS &aOther) const
void Format(OUTPUTFORMATTER *out, const EDA_IU_SCALE &aIuScale) const
KIGFX::COLOR4D GetColor() const
KIGFX::COLOR4D m_color
static void Stroke(const SHAPE *aShape, LINE_STYLE aLineStyle, int aWidth, const KIGFX::RENDER_SETTINGS *aRenderSettings, const std::function< void(const VECTOR2I &a, const VECTOR2I &b)> &aStroker)
static wxString GetLineStyleToken(LINE_STYLE aStyle)
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition vector2d.h:281
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:448
@ RADIANS_T
Definition eda_angle.h:31
@ DEGREES_T
Definition eda_angle.h:30
static constexpr EDA_ANGLE ANGLE_360
Definition eda_angle.h:454
a few functions useful in geometry calculations.
bool ClipLine(const BOX2I *aClipBox, int &x1, int &y1, int &x2, int &y2)
Test if any part of a line falls within the bounds of a rectangle.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition idf_helpers.h:37
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition macros.h:79
#define UNIMPLEMENTED_FOR(type)
Definition macros.h:92
Message panel definition file.
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.
CITER next(CITER it)
Definition ptree.cpp:120
@ SH_RECT
axis-aligned rectangle
Definition shape.h:43
@ SH_CIRCLE
circle
Definition shape.h:46
@ SH_SIMPLE
simple polygon
Definition shape.h:47
@ SH_ELLIPSE
ellipse or elliptical arc
Definition shape.h:53
@ SH_SEGMENT
line segment
Definition shape.h:44
@ SH_ARC
circular arc
Definition shape.h:50
@ SH_LINE_CHAIN
line chain (polyline)
Definition shape.h:45
static wxString SHAPE_TYPE_asString(SHAPE_TYPE a)
Definition shape.h:56
std::string FormatDouble2Str(double aValue)
Print a float number without using scientific notation and no trailing 0 This function is intended in...
const std::map< LINE_STYLE, struct LINE_STYLE_DESC > lineTypeNames
Conversion map between LINE_STYLE values and style names displayed.
const std::map< LINE_STYLE, struct LINE_STYLE_DESC > lineTypeNames
Conversion map between LINE_STYLE values and style names displayed.
LINE_STYLE
Dashed line types.
VECTOR2I center
const SHAPE_LINE_CHAIN chain
VECTOR2I end
#define M_PI
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
VECTOR2< double > VECTOR2D
Definition vector2d.h:707