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 <charconv>
25#include <string_utils.h>
26#include <render_settings.h>
28#include <geometry/shape.h>
29#include <geometry/shape_rect.h>
34#include <macros.h>
35#include <trigo.h>
36#include <widgets/msgpanel.h>
37
38using namespace STROKEPARAMS_T;
39
40
41const std::map<LINE_STYLE, struct LINE_STYLE_DESC> lineTypeNames = {
42 { LINE_STYLE::SOLID, { _( "Solid" ), BITMAPS::stroke_solid } },
43 { LINE_STYLE::DASH, { _( "Dashed" ), BITMAPS::stroke_dash } },
44 { LINE_STYLE::DOT, { _( "Dotted" ), BITMAPS::stroke_dot } },
45 { LINE_STYLE::DASHDOT, { _( "Dash-Dot" ), BITMAPS::stroke_dashdot } },
46 { LINE_STYLE::DASHDOTDOT, { _( "Dash-Dot-Dot" ), BITMAPS::stroke_dashdotdot } }
47};
48
49
50void STROKE_PARAMS::Stroke( const SHAPE* aShape, LINE_STYLE aLineStyle, int aWidth,
51 const KIGFX::RENDER_SETTINGS* aRenderSettings,
52 const std::function<void( const VECTOR2I& a, const VECTOR2I& b )>& aStroker )
53{
54 double strokes[6] = { aWidth * 1.0, aWidth * 1.0, aWidth * 1.0, aWidth * 1.0, aWidth * 1.0, aWidth * 1.0 };
55 int wrapAround = 6;
56
57 switch( aLineStyle )
58 {
60 strokes[0] = aRenderSettings->GetDashLength( aWidth );
61 strokes[1] = aRenderSettings->GetGapLength( aWidth );
62 wrapAround = 2;
63 break;
64 case LINE_STYLE::DOT:
65 strokes[0] = aRenderSettings->GetDotLength( aWidth );
66 strokes[1] = aRenderSettings->GetGapLength( aWidth );
67 wrapAround = 2;
68 break;
70 strokes[0] = aRenderSettings->GetDashLength( aWidth );
71 strokes[1] = aRenderSettings->GetGapLength( aWidth );
72 strokes[2] = aRenderSettings->GetDotLength( aWidth );
73 strokes[3] = aRenderSettings->GetGapLength( aWidth );
74 wrapAround = 4;
75 break;
77 strokes[0] = aRenderSettings->GetDashLength( aWidth );
78 strokes[1] = aRenderSettings->GetGapLength( aWidth );
79 strokes[2] = aRenderSettings->GetDotLength( aWidth );
80 strokes[3] = aRenderSettings->GetGapLength( aWidth );
81 strokes[4] = aRenderSettings->GetDotLength( aWidth );
82 strokes[5] = aRenderSettings->GetGapLength( aWidth );
83 wrapAround = 6;
84 break;
85 default:
86 UNIMPLEMENTED_FOR( lineTypeNames.at( aLineStyle ).name );
87 }
88
89 switch( aShape->Type() )
90 {
91 case SH_RECT:
92 {
93 SHAPE_LINE_CHAIN outline = static_cast<const SHAPE_RECT*>( aShape )->Outline();
94 std::set<size_t> arcsHandled;
95
96 for( int ii = 0; ii < outline.SegmentCount(); ++ii )
97 {
98 if( outline.IsArcSegment( ii ) )
99 {
100 size_t arcIndex = outline.ArcIndex( ii );
101
102 if( !arcsHandled.contains( arcIndex ) )
103 {
104 arcsHandled.insert( arcIndex );
105 const SHAPE_ARC& arc( outline.Arc( arcIndex ) );
106 STROKE_PARAMS::Stroke( &arc, aLineStyle, aWidth, aRenderSettings, aStroker );
107 }
108 }
109 else
110 {
111 const SEG& seg = outline.GetSegment( ii );
112 SHAPE_SEGMENT line( seg.A, seg.B );
113 STROKE_PARAMS::Stroke( &line, aLineStyle, aWidth, aRenderSettings, aStroker );
114 }
115 }
116
117 for( int jj = 0; jj < (int) outline.ArcCount(); ++jj )
118 {
119 const SHAPE_ARC& arc( outline.Arc( jj ) );
120 STROKE_PARAMS::Stroke( &arc, aLineStyle, aWidth, aRenderSettings, aStroker );
121 }
122
123 break;
124 }
125
126 case SH_SIMPLE:
127 {
128 const SHAPE_SIMPLE* poly = static_cast<const SHAPE_SIMPLE*>( aShape );
129
130 for( size_t ii = 0; ii < poly->GetSegmentCount(); ++ii )
131 {
132 SEG seg = poly->GetSegment( (int) ii );
133 SHAPE_SEGMENT line( seg.A, seg.B );
134 STROKE_PARAMS::Stroke( &line, aLineStyle, aWidth, aRenderSettings, aStroker );
135 }
136
137 break;
138 }
139
140 case SH_LINE_CHAIN:
141 {
142 const SHAPE_LINE_CHAIN* chain = static_cast<const SHAPE_LINE_CHAIN*>( aShape );
143
144 double patternLength = 0.0;
145
146 for( int ii = 0; ii < wrapAround; ++ii )
147 patternLength += strokes[ii];
148
149 // A zero-width shape makes every element zero long, and the walk would never advance.
150 if( patternLength <= 0.0 )
151 break;
152
153 int element = 0;
154 double remaining = strokes[0];
155
156 for( int ii = 0; ii < chain->SegmentCount(); ++ii )
157 {
158 SEG seg = chain->CSegment( ii );
159 VECTOR2D segVec( seg.B - seg.A );
160 double segLength = segVec.EuclideanNorm();
161
162 if( segLength == 0.0 )
163 continue;
164
165 // The pattern carries across the vertices, so calculations MUST be done in
166 // doubles to keep from accumulating rounding errors along the chain.
167 VECTOR2D step = segVec / segLength;
168 VECTOR2D start( seg.A );
169 double walked = 0.0;
170
171 while( walked < segLength )
172 {
173 double length = std::min( remaining, segLength - walked );
174 VECTOR2D next = start + step * length;
175
176 if( element % 2 == 0 )
177 aStroker( KiROUND( start ), KiROUND( next ) );
178
179 walked += length;
180 remaining -= length;
181 start = next;
182
183 if( remaining <= 0.0 )
184 {
185 element++;
186 remaining = strokes[element % wrapAround];
187 }
188 }
189 }
190
191 break;
192 }
193
194 case SH_SEGMENT:
195 {
196 const SHAPE_SEGMENT* line = static_cast<const SHAPE_SEGMENT*>( aShape );
197
198 VECTOR2D start = line->GetSeg().A;
199 VECTOR2D end = line->GetSeg().B;
200 BOX2I clip( start, KiROUND( end.x - start.x, end.y - start.y ) );
201 clip.Normalize();
202
203 double theta = atan2( end.y - start.y, end.x - start.x );
204
205 for( size_t i = 0; i < 10000; ++i )
206 {
207 // Calculations MUST be done in doubles to keep from accumulating rounding
208 // errors as we go.
209 VECTOR2D next( start.x + strokes[ i % wrapAround ] * cos( theta ),
210 start.y + strokes[ i % wrapAround ] * sin( theta ) );
211
212 // Drawing each segment can be done rounded to ints.
213 VECTOR2I a = KiROUND( start );
214 VECTOR2I b = KiROUND( next );
215
216 if( ClipLine( &clip, a.x, a.y, b.x, b.y ) )
217 break;
218 else if( i % 2 == 0 )
219 aStroker( a, b );
220
221 start = next;
222 }
223
224 break;
225 }
226
227 case SH_ARC:
228 {
229 const SHAPE_ARC* arc = static_cast<const SHAPE_ARC*>( aShape );
230
231 double r = arc->GetRadius();
232 double C = 2.0 * M_PI * r;
233 VECTOR2I center = arc->GetCenter();
234 VECTOR2D startRadial( arc->GetP0() - center );
235 EDA_ANGLE startAngle( startRadial );
236 VECTOR2D endRadial( arc->GetP1() - center );
237 EDA_ANGLE arcEndAngle( endRadial );
238
239 if( arcEndAngle == startAngle )
240 arcEndAngle = startAngle + ANGLE_360; // ring, not null
241
242 if( startAngle > arcEndAngle )
243 {
244 if( arcEndAngle < ANGLE_0 )
245 arcEndAngle = arcEndAngle.Normalize();
246 else
247 startAngle = startAngle.Normalize() - ANGLE_360;
248 }
249
250 wxASSERT( startAngle < arcEndAngle );
251
252 EDA_ANGLE angleIncrement = EDA_ANGLE( 0.5, DEGREES_T );
253
254 for( size_t i = 0; i < 10000 && startAngle < arcEndAngle; ++i )
255 {
256 EDA_ANGLE theta = ANGLE_360 * strokes[ i % wrapAround ] / C;
257 EDA_ANGLE endAngle = std::min( startAngle + theta, arcEndAngle );
258
259 if( i % 2 == 0 )
260 {
261 if( ( ( aLineStyle == LINE_STYLE::DASHDOT || aLineStyle == LINE_STYLE::DASHDOTDOT )
262 && i % wrapAround == 0 )
263 || aLineStyle == LINE_STYLE::DASH )
264 {
265 for( EDA_ANGLE currentAngle = startAngle; currentAngle < endAngle;
266 currentAngle += angleIncrement )
267 {
268 VECTOR2I a( center.x + KiROUND( r * currentAngle.Cos() ),
269 center.y + KiROUND( r * currentAngle.Sin() ) );
270
271 // Calculate the next angle step, ensuring it doesn't exceed the endAngle
272 EDA_ANGLE nextAngle = currentAngle + angleIncrement;
273
274 if( nextAngle > endAngle )
275 {
276 nextAngle = endAngle; // Set nextAngle to endAngle if it exceeds
277 }
278
279 VECTOR2I b( center.x + KiROUND( r * nextAngle.Cos() ),
280 center.y + KiROUND( r * nextAngle.Sin() ) );
281
282 aStroker( a, b ); // Draw the segment as an arc
283 }
284 }
285 else
286 {
287 VECTOR2I a( center.x + KiROUND( r * startAngle.Cos() ),
288 center.y + KiROUND( r * startAngle.Sin() ) );
289 VECTOR2I b( center.x + KiROUND( r * endAngle.Cos() ),
290 center.y + KiROUND( r * endAngle.Sin() ) );
291
292 aStroker( a, b );
293 }
294 }
295
296 startAngle = endAngle;
297 }
298
299 break;
300 }
301
302 case SH_ELLIPSE:
303 {
304 const SHAPE_ELLIPSE* ellipse = static_cast<const SHAPE_ELLIPSE*>( aShape );
305
306 VECTOR2I center = ellipse->GetCenter();
307 double a = ellipse->GetMajorRadius();
308 double b = ellipse->GetMinorRadius();
309 EDA_ANGLE rotation = ellipse->GetRotation();
310 double cosRot = rotation.Cos();
311 double sinRot = rotation.Sin();
312
313 EDA_ANGLE startAngle = ellipse->IsArc() ? ellipse->GetStartAngle() : ANGLE_0;
314 EDA_ANGLE endAngle = ellipse->IsArc() ? ellipse->GetEndAngle() : ANGLE_360;
315
316 if( endAngle == startAngle )
317 endAngle = startAngle + ANGLE_360;
318
319 if( startAngle > endAngle )
320 {
321 if( endAngle < ANGLE_0 )
322 endAngle = endAngle.Normalize();
323 else
324 startAngle = startAngle.Normalize() - ANGLE_360;
325 }
326
327 auto evalRad = [&]( double thetaRad ) -> VECTOR2D
328 {
329 double x = a * std::cos( thetaRad );
330 double y = b * std::sin( thetaRad );
331 return VECTOR2D( center.x + x * cosRot - y * sinRot, center.y + x * sinRot + y * cosRot );
332 };
333
334 auto evalAngle = [&]( const EDA_ANGLE& theta ) -> VECTOR2I
335 {
336 double x = a * theta.Cos();
337 double y = b * theta.Sin();
338 return VECTOR2I( center.x + KiROUND( x * cosRot - y * sinRot ),
339 center.y + KiROUND( x * sinRot + y * cosRot ) );
340 };
341
342 // Place strokes by arclength rather than angle so the pattern stays
343 // visually uniform on highly curved ellipses.
344 const double startRad = startAngle.AsRadians();
345 const double endRad = endAngle.AsRadians();
346 const int LUT_SIZE = 1024;
347 std::vector<double> arcLens( LUT_SIZE + 1 );
348
349 arcLens[0] = 0.0;
350 VECTOR2D prev = evalRad( startRad );
351
352 for( int j = 1; j <= LUT_SIZE; ++j )
353 {
354 double t = startRad + ( endRad - startRad ) * j / LUT_SIZE;
355 VECTOR2D curr = evalRad( t );
356 arcLens[j] = arcLens[j - 1] + ( curr - prev ).EuclideanNorm();
357 prev = curr;
358 }
359
360 const double totalLen = arcLens[LUT_SIZE];
361
362 auto angleAtLen = [&]( double s ) -> double
363 {
364 if( s >= totalLen )
365 return endRad;
366
367 if( s <= 0.0 )
368 return startRad;
369
370 auto it = std::upper_bound( arcLens.begin(), arcLens.end(), s );
371 int idx = std::distance( arcLens.begin(), it ) - 1;
372
373 double seg = arcLens[idx + 1] - arcLens[idx];
374 double frac = ( seg > 0 ) ? ( s - arcLens[idx] ) / seg : 0.0;
375
376 double t0 = startRad + ( endRad - startRad ) * idx / LUT_SIZE;
377 double t1 = startRad + ( endRad - startRad ) * ( idx + 1 ) / LUT_SIZE;
378
379 return t0 + frac * ( t1 - t0 );
380 };
381
382 EDA_ANGLE angleIncrement( 0.5, DEGREES_T );
383 double currentLen = 0.0;
384
385 for( size_t i = 0; i < 10000 && currentLen < totalLen; ++i )
386 {
387 double targetLen = std::min( currentLen + strokes[i % wrapAround], totalLen );
388
389 if( i % 2 == 0 )
390 {
391 EDA_ANGLE elemStart( angleAtLen( currentLen ), RADIANS_T );
392 EDA_ANGLE elemEnd( angleAtLen( targetLen ), RADIANS_T );
393
394 for( EDA_ANGLE c = elemStart; c < elemEnd; c += angleIncrement )
395 {
396 EDA_ANGLE n = std::min( c + angleIncrement, elemEnd );
397 aStroker( evalAngle( c ), evalAngle( n ) );
398 }
399 }
400
401 currentLen = targetLen;
402 }
403
404 break;
405 }
406
407 case SH_CIRCLE:
408 // A circle is always filled. A ring is represented by a 360° arc.
410
411 default:
413 }
414}
415
416
418{
419 wxString token;
420
421 switch( aStyle )
422 {
423 case LINE_STYLE::DASH: token = wxT( "dash" ); break;
424 case LINE_STYLE::DOT: token = wxT( "dot" ); break;
425 case LINE_STYLE::DASHDOT: token = wxT( "dash_dot" ); break;
426 case LINE_STYLE::DASHDOTDOT: token = wxT( "dash_dot_dot" ); break;
427 case LINE_STYLE::SOLID: token = wxT( "solid" ); break;
428 case LINE_STYLE::DEFAULT: token = wxT( "default" ); break;
429 }
430
431 return token;
432}
433
434
436 std::vector<MSG_PANEL_ITEM>& aList,
437 bool aIncludeStyle, bool aIncludeWidth )
438{
439 if( aIncludeStyle )
440 {
441 wxString msg = _( "Default" );
442
443 for( const auto& [ lineStyle, lineStyleDesc ] : lineTypeNames )
444 {
445 if( lineStyle == GetLineStyle() )
446 {
447 msg = lineStyleDesc.name;
448 break;
449 }
450 }
451
452 aList.emplace_back( _( "Line Style" ), msg );
453 }
454
455 if( aIncludeWidth )
456 aList.emplace_back( _( "Line Width" ), aUnitsProvider->MessageTextFromValue( GetWidth() ) );
457}
458
459
460void STROKE_PARAMS::Format( OUTPUTFORMATTER* aFormatter, const EDA_IU_SCALE& aIuScale ) const
461{
462 wxASSERT( aFormatter != nullptr );
463
465 {
466 aFormatter->Print( "(stroke (width %s) (type %s))",
467 EDA_UNIT_UTILS::FormatInternalUnits( aIuScale, GetWidth() ).c_str(),
469 }
470 else
471 {
472 aFormatter->Print( "(stroke (width %s) (type %s) (color %d %d %d %s))",
473 EDA_UNIT_UTILS::FormatInternalUnits( aIuScale, GetWidth() ).c_str(),
475 KiROUND( GetColor().r * 255.0 ),
476 KiROUND( GetColor().g * 255.0 ),
477 KiROUND( GetColor().b * 255.0 ),
478 FormatDouble2Str( GetColor().a ).c_str() );
479 }
480}
481
482
484{
485 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
486 {
487 if( token != T_LEFT )
488 Expecting( T_LEFT );
489
490 token = NextTok();
491
492 switch( token )
493 {
494 case T_width:
495 aStroke.SetWidth( KiROUND( parseDouble( "stroke width" ) * m_iuPerMM ) );
496 NeedRIGHT();
497 break;
498
499 case T_type:
500 {
501 token = NextTok();
502
503 switch( token )
504 {
505 case T_dash: aStroke.SetLineStyle( LINE_STYLE::DASH ); break;
506 case T_dot: aStroke.SetLineStyle( LINE_STYLE::DOT ); break;
507 case T_dash_dot: aStroke.SetLineStyle( LINE_STYLE::DASHDOT ); break;
508 case T_dash_dot_dot: aStroke.SetLineStyle( LINE_STYLE::DASHDOTDOT ); break;
509 case T_solid: aStroke.SetLineStyle( LINE_STYLE::SOLID ); break;
510 case T_default: aStroke.SetLineStyle( LINE_STYLE::DEFAULT ); break;
511 default:
512 Expecting( "solid, dash, dash_dot, dash_dot_dot, dot or default" );
513 }
514
515 NeedRIGHT();
516 break;
517 }
518
519 case T_color:
520 {
521 KIGFX::COLOR4D color;
522
523 color.r = parseInt( "red" ) / 255.0;
524 color.g = parseInt( "green" ) / 255.0;
525 color.b = parseInt( "blue" ) / 255.0;
526 color.a = std::clamp( parseDouble( "alpha" ), 0.0, 1.0 );
527
528 aStroke.SetColor( color );
529 NeedRIGHT();
530 break;
531 }
532
533 default:
534 Expecting( "width, type, or color" );
535 }
536 }
537}
538
539
540int STROKE_PARAMS_PARSER::parseInt( const char* aText )
541{
542 T token = NextTok();
543
544 if( token != T_NUMBER )
545 Expecting( aText );
546
547 return atoi( CurText() );
548}
549
550
551double STROKE_PARAMS_PARSER::parseDouble( const char* aText )
552{
553 T token = NextTok();
554
555 if( token != T_NUMBER )
556 Expecting( aText );
557
558 return DSNLEXER::parseDouble();
559}
560
561
@ stroke_dashdotdot
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:995
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:860
EDA_ANGLE Normalize()
Definition eda_angle.h:229
double Sin() const
Definition eda_angle.h:178
double AsRadians() const
Definition eda_angle.h:120
double Cos() const
Definition eda_angle.h:197
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
double r
Red component.
Definition color4d.h:390
double g
Green component.
Definition color4d.h:391
double a
Alpha component.
Definition color4d.h:393
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:399
double b
Blue component.
Definition color4d.h:392
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)
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)
LINE_STYLE GetLineStyle() const
void Format(OUTPUTFORMATTER *out, const EDA_IU_SCALE &aIuScale) const
KIGFX::COLOR4D GetColor() const
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:279
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:422
@ RADIANS_T
Definition eda_angle.h:32
@ DEGREES_T
Definition eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_360
Definition eda_angle.h:428
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.
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...
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
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:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682