KiCad PCB EDA Suite
Loading...
Searching...
No Matches
DXF_plotter.cpp
Go to the documentation of this file.
1
5/*
6 * This program source code file is part of KiCad, a free EDA CAD application.
7 *
8 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, you may find one here:
22 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23 * or you may search the http://www.gnu.org website for the version 2 license,
24 * or you may write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 */
27
29#include <macros.h>
30#include <string_utils.h>
32#include <trigo.h>
33#include <fmt/core.h>
34
39static const double DXF_OBLIQUE_ANGLE = 15;
40
41// No support for linewidths in DXF
42#define DXF_LINE_WIDTH DO_NOT_SET_LINE_WIDTH
43
60static const struct
61{
62 const char *name;
63 int color;
65{
66 { "BLACK", 7 }, // In DXF, color 7 is *both* white and black!
67 { "GRAY1", 251 },
68 { "GRAY2", 8 },
69 { "GRAY3", 9 },
70 { "WHITE", 7 },
71 { "LYELLOW", 51 },
72 { "LORANGE", 41 },
73 { "BLUE1", 178 },
74 { "GREEN1", 98 },
75 { "CYAN1", 138 },
76 { "RED1", 18 },
77 { "MAGENTA1", 228 },
78 { "BROWN1", 58 },
79 { "ORANGE1", 34 },
80 { "BLUE2", 5 },
81 { "GREEN2", 3 },
82 { "CYAN2", 4 },
83 { "RED2", 1 },
84 { "MAGENTA2", 6 },
85 { "BROWN2", 54 },
86 { "ORANGE2", 42 },
87 { "BLUE3", 171 },
88 { "GREEN3", 91 },
89 { "CYAN3", 131 },
90 { "RED3", 11 },
91 { "MAGENTA3", 221 },
92 { "YELLOW3", 2 },
93 { "ORANGE3", 32 },
94 { "BLUE4", 5 },
95 { "GREEN4", 3 },
96 { "CYAN4", 4 },
97 { "RED4", 1 },
98 { "MAGENTA4", 6 },
99 { "YELLOW4", 2 },
100 { "ORANGE4", 40 }
102
103
104static const char* getDXFLineType( LINE_STYLE aType )
105{
106 switch( aType )
107 {
110 return "CONTINUOUS";
111 case LINE_STYLE::DASH:
112 return "DASHED";
113 case LINE_STYLE::DOT:
114 return "DOTTED";
116 return "DASHDOT";
117 default:
118 wxFAIL_MSG( "Unhandled LINE_STYLE" );
119 return "CONTINUOUS";
120 }
121}
122
123
124// A helper function to create a color name acceptable in DXF files
125// DXF files do not use a RGB definition
126static wxString getDXFColorName( const COLOR4D& aColor )
127{
128 EDA_COLOR_T color = COLOR4D::FindNearestLegacyColor( int( aColor.r * 255 ),
129 int( aColor.g * 255 ),
130 int( aColor.b * 255 ) );
131 wxString cname( dxf_layer[color].name );
132 return cname;
133}
134
135
137{
138 m_plotUnits = aUnit;
139
140 switch( aUnit )
141 {
142 case DXF_UNITS::MM:
143 m_unitScalingFactor = 0.00254;
145 break;
146
147 case DXF_UNITS::INCH:
148 default:
149 m_unitScalingFactor = 0.0001;
151 }
152}
153
154
155// convert aValue to a string, and remove trailing zeros
156// In DXF files coordinates need a high precision: at least 9 digits when given
157// in inches and 7 digits when in mm.
158// So we use 16 digits and remove trailing 0 (if any)
159static std::string formatCoord( double aValue )
160{
161 std::string buf;
162
163 buf = fmt::format( "{:.16f}", aValue );
164
165 // remove trailing zeros
166 while( !buf.empty() && buf[buf.size() - 1] == '0' )
167 {
168 buf.pop_back();
169 }
170
171 return buf;
172}
173
174
175void DXF_PLOTTER::SetViewport( const VECTOR2I& aOffset, double aIusPerDecimil,
176 double aScale, bool aMirror )
177{
178 m_plotOffset = aOffset;
179 m_plotScale = aScale;
180
181 /* DXF paper is 'virtual' so there is no need of a paper size.
182 Also this way we can handle the aux origin which can be useful
183 (for example when aligning to a mechanical drawing) */
184 m_paperSize.x = 0;
185 m_paperSize.y = 0;
186
187 /* Like paper size DXF units are abstract too. Anyway there is a
188 * system variable (MEASUREMENT) which will be set to 0 to indicate
189 * english units */
190 m_IUsPerDecimil = aIusPerDecimil;
191 m_iuPerDeviceUnit = 1.0 / aIusPerDecimil; // Gives a DXF in decimils
192 m_iuPerDeviceUnit *= GetUnitScaling(); // Get the scaling factor for the current units
193
194 m_plotMirror = false; // No mirroring on DXF
195 m_currentColor = COLOR4D::BLACK;
196}
197
198
199bool DXF_PLOTTER::StartPlot( const wxString& aPageNumber )
200{
201 wxASSERT( m_outputFile );
202
203 // DXF HEADER - Boilerplate
204 // Defines the minimum for drawing i.e. the angle system and the
205 // 4 linetypes (CONTINUOUS, DOTDASH, DASHED and DOTTED)
206 fmt::print( m_outputFile,
207 " 0\n"
208 "SECTION\n"
209 " 2\n"
210 "HEADER\n"
211 " 9\n"
212 "$ANGBASE\n"
213 " 50\n"
214 "0.0\n"
215 " 9\n"
216 "$ANGDIR\n"
217 " 70\n"
218 "1\n"
219 " 9\n"
220 "$MEASUREMENT\n"
221 " 70\n"
222 "{}\n"
223 " 0\n"
224 "ENDSEC\n"
225 " 0\n"
226 "SECTION\n"
227 " 2\n"
228 "TABLES\n"
229 " 0\n"
230 "TABLE\n"
231 " 2\n"
232 "LTYPE\n"
233 " 70\n"
234 "4\n"
235 " 0\n"
236 "LTYPE\n"
237 " 5\n"
238 "40F\n"
239 " 2\n"
240 "CONTINUOUS\n"
241 " 70\n"
242 "0\n"
243 " 3\n"
244 "Solid line\n"
245 " 72\n"
246 "65\n"
247 " 73\n"
248 "0\n"
249 " 40\n"
250 "0.0\n"
251 " 0\n"
252 "LTYPE\n"
253 " 5\n"
254 "410\n"
255 " 2\n"
256 "DASHDOT\n"
257 " 70\n"
258 "0\n"
259 " 3\n"
260 "Dash Dot ____ _ ____ _\n"
261 " 72\n"
262 "65\n"
263 " 73\n"
264 "4\n"
265 " 40\n"
266 "2.0\n"
267 " 49\n"
268 "1.25\n"
269 " 49\n"
270 "-0.25\n"
271 " 49\n"
272 "0.25\n"
273 " 49\n"
274 "-0.25\n"
275 " 0\n"
276 "LTYPE\n"
277 " 5\n"
278 "411\n"
279 " 2\n"
280 "DASHED\n"
281 " 70\n"
282 "0\n"
283 " 3\n"
284 "Dashed __ __ __ __ __\n"
285 " 72\n"
286 "65\n"
287 " 73\n"
288 "2\n"
289 " 40\n"
290 "0.75\n"
291 " 49\n"
292 "0.5\n"
293 " 49\n"
294 "-0.25\n"
295 " 0\n"
296 "LTYPE\n"
297 " 5\n"
298 "43B\n"
299 " 2\n"
300 "DOTTED\n"
301 " 70\n"
302 "0\n"
303 " 3\n"
304 "Dotted . . . .\n"
305 " 72\n"
306 "65\n"
307 " 73\n"
308 "2\n"
309 " 40\n"
310 "0.2\n"
311 " 49\n"
312 "0.0\n"
313 " 49\n"
314 "-0.2\n"
315 " 0\n"
316 "ENDTAB\n",
318
319 // Text styles table
320 // Defines 4 text styles, one for each bold/italic combination
321 fmt::print( m_outputFile,
322 " 0\n"
323 "TABLE\n"
324 " 2\n"
325 "STYLE\n"
326 " 70\n"
327 "4\n" );
328
329 static const char *style_name[4] = {"KICAD", "KICADB", "KICADI", "KICADBI"};
330
331 for(int i = 0; i < 4; i++ )
332 {
333 fmt::print( m_outputFile,
334 " 0\n"
335 "STYLE\n"
336 " 2\n"
337 "{}\n" // Style name
338 " 70\n"
339 "0\n" // Standard flags
340 " 40\n"
341 "0\n" // Non-fixed height text
342 " 41\n"
343 "1\n" // Width factor (base)
344 " 42\n"
345 "1\n" // Last height (mandatory)
346 " 50\n"
347 "{:g}\n" // Oblique angle
348 " 71\n"
349 "0\n" // Generation flags (default)
350 " 3\n"
351 // The standard ISO font (when kicad is build with it
352 // the dxf text in acad matches *perfectly*)
353 "isocp.shx\n", // Font name (when not bigfont)
354 // Apply a 15 degree angle to italic text
355 style_name[i], i < 2 ? 0 : DXF_OBLIQUE_ANGLE );
356 }
357
358 EDA_COLOR_T numLayers = NBCOLORS;
359
360 // If printing in monochrome, only output the black layer
361 if( !GetColorMode() )
362 numLayers = static_cast<EDA_COLOR_T>( 1 );
363
364 // Layer table - one layer per color
365 fmt::print( m_outputFile,
366 " 0\n"
367 "ENDTAB\n"
368 " 0\n"
369 "TABLE\n"
370 " 2\n"
371 "LAYER\n"
372 " 70\n"
373 "{}\n", (int)numLayers );
374
375 /* The layer/colors palette. The acad/DXF palette is divided in 3 zones:
376
377 - The primary colors (1 - 9)
378 - An HSV zone (10-250, 5 values x 2 saturations x 10 hues
379 - Greys (251 - 255)
380 */
381
382 wxASSERT( numLayers <= NBCOLORS );
383
384 for( EDA_COLOR_T i = BLACK; i < numLayers; i = static_cast<EDA_COLOR_T>( int( i ) + 1 ) )
385 {
386 fmt::print( m_outputFile,
387 " 0\n"
388 "LAYER\n"
389 " 2\n"
390 "{}\n" // Layer name
391 " 70\n"
392 "0\n" // Standard flags
393 " 62\n"
394 "{}\n" // Color number
395 " 6\n"
396 "CONTINUOUS\n",// Linetype name
397 dxf_layer[i].name, dxf_layer[i].color );
398 }
399
400 // End of layer table, begin entities
401 fmt::print( m_outputFile,
402 " 0\n"
403 "ENDTAB\n"
404 " 0\n"
405 "ENDSEC\n"
406 " 0\n"
407 "SECTION\n"
408 " 2\n"
409 "ENTITIES\n" );
410
411 return true;
412}
413
414
416{
417 wxASSERT( m_outputFile );
418
419 // DXF FOOTER
420 fmt::print( m_outputFile,
421 " 0\n"
422 "ENDSEC\n"
423 " 0\n"
424 "EOF\n" );
425 fclose( m_outputFile );
426 m_outputFile = nullptr;
427
428 return true;
429}
430
431
433{
434 if( ( m_colorMode )
435 || ( color == COLOR4D::BLACK )
436 || ( color == COLOR4D::WHITE ) )
437 {
439 }
440 else
441 {
442 m_currentColor = COLOR4D::BLACK;
443 }
444}
445
446
447void DXF_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int width )
448{
449 wxASSERT( m_outputFile );
450
451 if( p1 != p2 )
452 {
453 MoveTo( p1 );
454 LineTo( VECTOR2I( p1.x, p2.y ) );
455 LineTo( VECTOR2I( p2.x, p2.y ) );
456 LineTo( VECTOR2I( p2.x, p1.y ) );
457 FinishTo( VECTOR2I( p1.x, p1.y ) );
458 }
459 else
460 {
461 // Draw as a point
462 wxString cname = getDXFColorName( m_currentColor );
463 VECTOR2D point_dev = userToDeviceCoordinates( p1 );
464
465 fmt::print( m_outputFile, "0\nPOINT\n8\n{}\n10\n{}\n20\n{}\n",
466 TO_UTF8( cname ),
467 formatCoord( point_dev.x ),
468 formatCoord( point_dev.y ) );
469 }
470}
471
472
473void DXF_PLOTTER::Circle( const VECTOR2I& centre, int diameter, FILL_T fill, int width )
474{
475 wxASSERT( m_outputFile );
476 double radius = userToDeviceSize( diameter / 2 );
477 VECTOR2D centre_dev = userToDeviceCoordinates( centre );
478
479 wxString cname = getDXFColorName( m_currentColor );
480
481 if( radius > 0 )
482 {
483 if( fill == FILL_T::NO_FILL )
484 {
485 fmt::print( m_outputFile, "0\nCIRCLE\n8\n{}\n10\n{}\n20\n{}\n40\n{}\n",
486 TO_UTF8( cname ),
487 formatCoord( centre_dev.x ),
488 formatCoord( centre_dev.y ),
489 formatCoord( radius ) );
490 }
491 else if( fill == FILL_T::FILLED_SHAPE )
492 {
493 double r = radius * 0.5;
494 fmt::print( m_outputFile, "0\nPOLYLINE\n" );
495 fmt::print( m_outputFile, "8\n{}\n66\n1\n70\n1\n", TO_UTF8( cname ) );
496 fmt::print( m_outputFile, "40\n{}\n41\n{}\n",
498 formatCoord( radius ) );
499 fmt::print( m_outputFile, "0\nVERTEX\n8\n{}\n", TO_UTF8( cname ) );
500 fmt::print( m_outputFile, "10\n{}\n 20\n{}\n42\n1.0\n",
501 formatCoord( centre_dev.x-r ),
502 formatCoord( centre_dev.y ) );
503 fmt::print( m_outputFile, "0\nVERTEX\n8\n{}\n", TO_UTF8( cname ) );
504 fmt::print( m_outputFile, "10\n{}\n 20\n{}\n42\n1.0\n",
505 formatCoord( centre_dev.x+r ),
506 formatCoord( centre_dev.y ) );
507 fmt::print( m_outputFile, "0\nSEQEND\n" );
508 }
509 }
510 else
511 {
512 // Draw as a point
513 fmt::print( m_outputFile, "0\nPOINT\n8\n{}\n10\n{}\n20\n{}\n",
514 TO_UTF8( cname ),
515 formatCoord( centre_dev.x ),
516 formatCoord( centre_dev.y ) );
517 }
518}
519
520
521void DXF_PLOTTER::PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFill, int aWidth,
522 void* aData )
523{
524 if( aCornerList.size() <= 1 )
525 return;
526
527 unsigned last = aCornerList.size() - 1;
528
529 // Plot outlines with lines (thickness = 0) to define the polygon
530 if( aWidth <= 0 || aFill == FILL_T::NO_FILL )
531 {
532 MoveTo( aCornerList[0] );
533
534 for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
535 LineTo( aCornerList[ii] );
536
537 // Close polygon if 'fill' requested
538 if( aFill != FILL_T::NO_FILL )
539 {
540 if( aCornerList[last] != aCornerList[0] )
541 LineTo( aCornerList[0] );
542 }
543
544 PenFinish();
545 return;
546 }
547
548 // The polygon outline has thickness, and is filled
549 // Build and plot the polygon which contains the initial
550 // polygon and its thick outline
551 SHAPE_POLY_SET bufferOutline;
552 SHAPE_POLY_SET bufferPolybase;
553
554 bufferPolybase.NewOutline();
555
556 // enter outline as polygon:
557 for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
558 {
559 TransformOvalToPolygon( bufferOutline, aCornerList[ ii - 1 ], aCornerList[ ii ],
561 }
562
563 // enter the initial polygon:
564 for( const VECTOR2I& corner : aCornerList )
565 bufferPolybase.Append( corner );
566
567 // Merge polygons to build the polygon which contains the initial
568 // polygon and its thick outline
569
570 // create the outline which contains thick outline:
571 bufferPolybase.BooleanAdd( bufferOutline );
572 bufferPolybase.Fracture();
573
574 if( bufferPolybase.OutlineCount() < 1 ) // should not happen
575 return;
576
577 const SHAPE_LINE_CHAIN& path = bufferPolybase.COutline( 0 );
578
579 if( path.PointCount() < 2 ) // should not happen
580 return;
581
582 // Now, output the final polygon to DXF file:
583 last = path.PointCount() - 1;
584 VECTOR2I point = path.CPoint( 0 );
585
586 VECTOR2I startPoint( point.x, point.y );
587 MoveTo( startPoint );
588
589 for( int ii = 1; ii < path.PointCount(); ii++ )
590 {
591 point = path.CPoint( ii );
592 LineTo( VECTOR2I( point.x, point.y ) );
593 }
594
595 // Close polygon, if needed
596 point = path.CPoint( last );
597 VECTOR2I endPoint( point.x, point.y );
598
599 if( endPoint != startPoint )
600 LineTo( startPoint );
601
602 PenFinish();
603}
604
605
606void DXF_PLOTTER::PenTo( const VECTOR2I& pos, char plume )
607{
608 wxASSERT( m_outputFile );
609
610 if( plume == 'Z' )
611 {
612 return;
613 }
614
615 VECTOR2D pos_dev = userToDeviceCoordinates( pos );
616 VECTOR2D pen_lastpos_dev = userToDeviceCoordinates( m_penLastpos );
617
618 if( m_penLastpos != pos && plume == 'D' )
619 {
620 wxASSERT( m_currentLineType >= LINE_STYLE::FIRST_TYPE
621 && m_currentLineType <= LINE_STYLE::LAST_TYPE );
622
623 // DXF LINE
624 wxString cname = getDXFColorName( m_currentColor );
625 const char* lname = getDXFLineType( static_cast<LINE_STYLE>( m_currentLineType ) );
626 fmt::print( m_outputFile, "0\nLINE\n8\n{}\n6\n{}\n10\n{}\n20\n{}\n11\n{}\n21\n{}\n",
627 TO_UTF8( cname ),
628 lname,
629 formatCoord( pen_lastpos_dev.x ),
630 formatCoord( pen_lastpos_dev.y ),
631 formatCoord( pos_dev.x ),
632 formatCoord( pos_dev.y ) );
633 }
634
635 m_penLastpos = pos;
636}
637
638
639void DXF_PLOTTER::SetDash( int aLineWidth, LINE_STYLE aLineStyle )
640{
641 wxASSERT( aLineStyle >= LINE_STYLE::FIRST_TYPE
642 && aLineStyle <= LINE_STYLE::LAST_TYPE );
643
644 m_currentLineType = aLineStyle;
645}
646
647
648void DXF_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
649 const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill, int aWidth )
650{
651 wxASSERT( m_outputFile );
652
653 if( aRadius <= 0 )
654 return;
655
656 EDA_ANGLE startAngle = -aStartAngle;
657 EDA_ANGLE endAngle = startAngle - aAngle;
658
659 // In DXF, arcs are drawn CCW.
660 // If startAngle > endAngle, it is CW. So transform it to CCW
661 if( endAngle < startAngle )
662 std::swap( startAngle, endAngle );
663
664 VECTOR2D centre_device = userToDeviceCoordinates( aCenter );
665 double radius_device = userToDeviceSize( aRadius );
666
667 // Emit a DXF ARC entity
668 wxString cname = getDXFColorName( m_currentColor );
669 fmt::print( m_outputFile,
670 "0\nARC\n8\n{}\n10\n{}\n20\n{}\n40\n{}\n50\n{:.8f}\n51\n{:.8f}\n",
671 TO_UTF8( cname ),
672 formatCoord( centre_device.x ),
673 formatCoord( centre_device.y ),
674 formatCoord( radius_device ),
675 startAngle.AsDegrees(),
676 endAngle.AsDegrees() );
677}
678
679
680void DXF_PLOTTER::ThickSegment( const VECTOR2I& aStart, const VECTOR2I& aEnd, int aWidth, void* aData )
681{
682 const PLOT_PARAMS* cfg = static_cast<const PLOT_PARAMS*>( aData );
683
684 if( cfg && cfg->GetDXFPlotMode() == SKETCH )
685 {
686 std::vector<VECTOR2I> cornerList;
687 SHAPE_POLY_SET outlineBuffer;
688 TransformOvalToPolygon( outlineBuffer, aStart, aEnd, aWidth, GetPlotterArcHighDef(),
689 ERROR_INSIDE );
690 const SHAPE_LINE_CHAIN& path = outlineBuffer.COutline( 0 );
691
692 cornerList.reserve( path.PointCount() );
693
694 for( int jj = 0; jj < path.PointCount(); jj++ )
695 cornerList.emplace_back( path.CPoint( jj ).x, path.CPoint( jj ).y );
696
697 // Ensure the polygon is closed
698 if( cornerList[0] != cornerList[cornerList.size() - 1] )
699 cornerList.push_back( cornerList[0] );
700
701 PlotPoly( cornerList, FILL_T::NO_FILL, DXF_LINE_WIDTH );
702 }
703 else
704 {
705 MoveTo( aStart );
706 FinishTo( aEnd );
707 }
708}
709
710
711void DXF_PLOTTER::ThickArc( const VECTOR2D& centre, const EDA_ANGLE& aStartAngle,
712 const EDA_ANGLE& aAngle, double aRadius, int aWidth, void* aData )
713{
714 const PLOT_PARAMS* cfg = static_cast<const PLOT_PARAMS*>( aData );
715
716 if( cfg && cfg->GetDXFPlotMode() == SKETCH )
717 {
718 Arc( centre, aStartAngle, aAngle, aRadius - aWidth/2, FILL_T::NO_FILL, DXF_LINE_WIDTH );
719 Arc( centre, aStartAngle, aAngle, aRadius + aWidth/2, FILL_T::NO_FILL, DXF_LINE_WIDTH );
720 }
721 else
722 {
723 Arc( centre, aStartAngle, aAngle, aRadius, FILL_T::NO_FILL, DXF_LINE_WIDTH );
724 }
725}
726
727
728void DXF_PLOTTER::ThickRect( const VECTOR2I& p1, const VECTOR2I& p2, int width, void* aData )
729{
730 const PLOT_PARAMS* cfg = static_cast<const PLOT_PARAMS*>( aData );
731
732 if( cfg && cfg->GetDXFPlotMode() == SKETCH )
733 {
734 VECTOR2I offsetp1( p1.x - width/2, p1.y - width/2 );
735 VECTOR2I offsetp2( p2.x + width/2, p2.y + width/2 );
736 Rect( offsetp1, offsetp2, FILL_T::NO_FILL, DXF_LINE_WIDTH );
737
738 offsetp1.x += width;
739 offsetp1.y += width;
740 offsetp2.x -= width;
741 offsetp2.y -= width;
742 Rect( offsetp1, offsetp2, FILL_T::NO_FILL, DXF_LINE_WIDTH );
743 }
744 else
745 {
746 Rect( p1, p2, FILL_T::NO_FILL, DXF_LINE_WIDTH );
747 }
748}
749
750
751void DXF_PLOTTER::ThickCircle( const VECTOR2I& pos, int diametre, int width, void* aData )
752{
753 const PLOT_PARAMS* cfg = static_cast<const PLOT_PARAMS*>( aData );
754
755 if( cfg && cfg->GetDXFPlotMode() == SKETCH )
756 {
757 Circle( pos, diametre - width, FILL_T::NO_FILL, DXF_LINE_WIDTH );
758 Circle( pos, diametre + width, FILL_T::NO_FILL, DXF_LINE_WIDTH );
759 }
760 else
761 {
762 Circle( pos, diametre, FILL_T::NO_FILL, DXF_LINE_WIDTH );
763 }
764}
765
766
767void DXF_PLOTTER::FilledCircle( const VECTOR2I& pos, int diametre, void* aData )
768{
769 const PLOT_PARAMS* cfg = static_cast<const PLOT_PARAMS*>( aData );
770
771 if( cfg && cfg->GetDXFPlotMode() == SKETCH )
772 Circle( pos, diametre, FILL_T::NO_FILL, DXF_LINE_WIDTH );
773 else
774 Circle( pos, diametre, FILL_T::FILLED_SHAPE, 0 );
775}
776
777
778void DXF_PLOTTER::ThickPoly( const SHAPE_POLY_SET& aPoly, int aWidth, void* aData )
779{
780 const PLOT_PARAMS* cfg = static_cast<const PLOT_PARAMS*>( aData );
781
782 if( cfg && cfg->GetDXFPlotMode() == SKETCH )
783 {
784 SHAPE_POLY_SET outline = aPoly.CloneDropTriangulation();
785 outline.Inflate( aWidth / 2, CORNER_STRATEGY::ROUND_ALL_CORNERS, GetPlotterArcHighDef() );
786 PLOTTER::PlotPoly( outline.COutline( 0 ), FILL_T::NO_FILL, DXF_LINE_WIDTH, aData );
787
788 outline = aPoly.CloneDropTriangulation();
789 outline.Deflate( aWidth / 2, CORNER_STRATEGY::ROUND_ALL_CORNERS, GetPlotterArcHighDef() );
790 PLOTTER::PlotPoly( outline.COutline( 0 ), FILL_T::NO_FILL, DXF_LINE_WIDTH, aData );
791 }
792 else
793 {
794 PLOTTER::PlotPoly( aPoly.COutline( 0 ), FILL_T::NO_FILL, aWidth, aData );
795 }
796}
797
798
799void DXF_PLOTTER::FlashPadOval( const VECTOR2I& aPos, const VECTOR2I& aSize,
800 const EDA_ANGLE& aOrient, void* aData )
801{
802 wxASSERT( m_outputFile );
803
804 VECTOR2I size( aSize );
805 EDA_ANGLE orient( aOrient );
806
807 /* The chip is reduced to an oval tablet with size.y > size.x
808 * (Oval vertical orientation 0) */
809 if( size.x > size.y )
810 {
811 std::swap( size.x, size.y );
812 orient += ANGLE_90;
813 }
814
815 ThickOval( aPos, size, orient, DXF_LINE_WIDTH, aData );
816}
817
818
819void DXF_PLOTTER::FlashPadCircle( const VECTOR2I& pos, int diametre, void* aData )
820{
821 wxASSERT( m_outputFile );
822 Circle( pos, diametre, FILL_T::NO_FILL, DXF_LINE_WIDTH );
823}
824
825
826void DXF_PLOTTER::FlashPadRect( const VECTOR2I& aPos, const VECTOR2I& aPadSize,
827 const EDA_ANGLE& aOrient, void* aData )
828{
829 wxASSERT( m_outputFile );
830
831 VECTOR2I size, start, end;
832
833 size.x = aPadSize.x / 2;
834 size.y = aPadSize.y / 2;
835
836 if( size.x < 0 )
837 size.x = 0;
838
839 if( size.y < 0 )
840 size.y = 0;
841
842 // If a dimension is zero, the trace is reduced to 1 line
843 if( size.x == 0 )
844 {
845 start = VECTOR2I( aPos.x, aPos.y - size.y );
846 end = VECTOR2I( aPos.x, aPos.y + size.y );
847 RotatePoint( start, aPos, aOrient );
848 RotatePoint( end, aPos, aOrient );
849 MoveTo( start );
850 FinishTo( end );
851 return;
852 }
853
854 if( size.y == 0 )
855 {
856 start = VECTOR2I( aPos.x - size.x, aPos.y );
857 end = VECTOR2I( aPos.x + size.x, aPos.y );
858 RotatePoint( start, aPos, aOrient );
859 RotatePoint( end, aPos, aOrient );
860 MoveTo( start );
861 FinishTo( end );
862 return;
863 }
864
865 start = VECTOR2I( aPos.x - size.x, aPos.y - size.y );
866 RotatePoint( start, aPos, aOrient );
867 MoveTo( start );
868
869 end = VECTOR2I( aPos.x - size.x, aPos.y + size.y );
870 RotatePoint( end, aPos, aOrient );
871 LineTo( end );
872
873 end = VECTOR2I( aPos.x + size.x, aPos.y + size.y );
874 RotatePoint( end, aPos, aOrient );
875 LineTo( end );
876
877 end = VECTOR2I( aPos.x + size.x, aPos.y - size.y );
878 RotatePoint( end, aPos, aOrient );
879 LineTo( end );
880
881 FinishTo( start );
882}
883
884
885void DXF_PLOTTER::FlashPadRoundRect( const VECTOR2I& aPadPos, const VECTOR2I& aSize,
886 int aCornerRadius, const EDA_ANGLE& aOrient, void* aData )
887{
888 SHAPE_POLY_SET outline;
889 TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient, aCornerRadius, 0.0, 0,
891
892 // TransformRoundRectToPolygon creates only one convex polygon
893 SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );
894
895 MoveTo( VECTOR2I( poly.CPoint( 0 ).x, poly.CPoint( 0 ).y ) );
896
897 for( int ii = 1; ii < poly.PointCount(); ++ii )
898 LineTo( VECTOR2I( poly.CPoint( ii ).x, poly.CPoint( ii ).y ) );
899
900 FinishTo( VECTOR2I( poly.CPoint( 0 ).x, poly.CPoint( 0 ).y ) );
901}
902
903
904void DXF_PLOTTER::FlashPadCustom( const VECTOR2I& aPadPos, const VECTOR2I& aSize,
905 const EDA_ANGLE& aOrient, SHAPE_POLY_SET* aPolygons,
906 void* aData )
907{
908 for( int cnt = 0; cnt < aPolygons->OutlineCount(); ++cnt )
909 {
910 SHAPE_LINE_CHAIN& poly = aPolygons->Outline( cnt );
911
912 MoveTo( VECTOR2I( poly.CPoint( 0 ).x, poly.CPoint( 0 ).y ) );
913
914 for( int ii = 1; ii < poly.PointCount(); ++ii )
915 LineTo( VECTOR2I( poly.CPoint( ii ).x, poly.CPoint( ii ).y ) );
916
917 FinishTo( VECTOR2I( poly.CPoint( 0 ).x, poly.CPoint( 0 ).y ) );
918 }
919}
920
921
922void DXF_PLOTTER::FlashPadTrapez( const VECTOR2I& aPadPos, const VECTOR2I* aCorners,
923 const EDA_ANGLE& aPadOrient, void* aData )
924{
925 wxASSERT( m_outputFile );
926 VECTOR2I coord[4]; /* coord actual corners of a trapezoidal trace */
927
928 for( int ii = 0; ii < 4; ii++ )
929 {
930 coord[ii] = aCorners[ii];
931 RotatePoint( coord[ii], aPadOrient );
932 coord[ii] += aPadPos;
933 }
934
935 // Plot edge:
936 MoveTo( coord[0] );
937 LineTo( coord[1] );
938 LineTo( coord[2] );
939 LineTo( coord[3] );
940 FinishTo( coord[0] );
941}
942
943
944void DXF_PLOTTER::FlashRegularPolygon( const VECTOR2I& aShapePos, int aRadius, int aCornerCount,
945 const EDA_ANGLE& aOrient, void* aData )
946{
947 // Do nothing
948 wxASSERT( 0 );
949}
950
951
959bool containsNonAsciiChars( const wxString& string )
960{
961 for( unsigned i = 0; i < string.length(); i++ )
962 {
963 wchar_t ch = string[i];
964
965 if( ch > 255 )
966 return true;
967 }
968 return false;
969}
970
971
972void DXF_PLOTTER::Text( const VECTOR2I& aPos,
973 const COLOR4D& aColor,
974 const wxString& aText,
975 const EDA_ANGLE& aOrient,
976 const VECTOR2I& aSize,
977 enum GR_TEXT_H_ALIGN_T aH_justify,
978 enum GR_TEXT_V_ALIGN_T aV_justify,
979 int aWidth,
980 bool aItalic,
981 bool aBold,
982 bool aMultilineAllowed,
983 KIFONT::FONT* aFont,
984 const KIFONT::METRICS& aFontMetrics,
985 void* aData )
986{
987 // Fix me: see how to use DXF text mode for multiline texts
988 if( aMultilineAllowed && !aText.Contains( wxT( "\n" ) ) )
989 aMultilineAllowed = false; // the text has only one line.
990
991 bool processSuperSub = aText.Contains( wxT( "^{" ) ) || aText.Contains( wxT( "_{" ) );
992
993 if( m_textAsLines || containsNonAsciiChars( aText ) || aMultilineAllowed || processSuperSub )
994 {
995 // output text as graphics.
996 // Perhaps multiline texts could be handled as DXF text entity
997 // but I do not want spend time about this (JPC)
998 PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify, aWidth, aItalic,
999 aBold, aMultilineAllowed, aFont, aFontMetrics, aData );
1000 }
1001 else
1002 {
1003 TEXT_ATTRIBUTES attrs;
1004 attrs.m_Halign = aH_justify;
1005 attrs.m_Valign =aV_justify;
1006 attrs.m_StrokeWidth = aWidth;
1007 attrs.m_Angle = aOrient;
1008 attrs.m_Italic = aItalic;
1009 attrs.m_Bold = aBold;
1010 attrs.m_Mirrored = aSize.x < 0;
1011 attrs.m_Multiline = false;
1012 plotOneLineOfText( aPos, aColor, aText, attrs );
1013 }
1014}
1015
1016
1018 const COLOR4D& aColor,
1019 const wxString& aText,
1020 const TEXT_ATTRIBUTES& aAttributes,
1021 KIFONT::FONT* aFont,
1022 const KIFONT::METRICS& aFontMetrics,
1023 void* aData )
1024{
1025 TEXT_ATTRIBUTES attrs = aAttributes;
1026
1027 // Fix me: see how to use DXF text mode for multiline texts
1028 if( attrs.m_Multiline && !aText.Contains( wxT( "\n" ) ) )
1029 attrs.m_Multiline = false; // the text has only one line.
1030
1031 bool processSuperSub = aText.Contains( wxT( "^{" ) ) || aText.Contains( wxT( "_{" ) );
1032
1033 if( m_textAsLines || containsNonAsciiChars( aText ) || attrs.m_Multiline || processSuperSub )
1034 {
1035 // output text as graphics.
1036 // Perhaps multiline texts could be handled as DXF text entity
1037 // but I do not want spend time about that (JPC)
1038 PLOTTER::PlotText( aPos, aColor, aText, aAttributes, aFont, aFontMetrics, aData );
1039 }
1040 else
1041 {
1042 plotOneLineOfText( aPos, aColor, aText, attrs );
1043 }
1044}
1045
1046
1047void DXF_PLOTTER::plotOneLineOfText( const VECTOR2I& aPos, const COLOR4D& aColor,
1048 const wxString& aText, const TEXT_ATTRIBUTES& aAttributes )
1049{
1050 /* Emit text as a text entity. This loses formatting and shape but it's
1051 more useful as a CAD object */
1052 VECTOR2D origin_dev = userToDeviceCoordinates( aPos );
1053 SetColor( aColor );
1054 wxString cname = getDXFColorName( m_currentColor );
1055 VECTOR2D size_dev = userToDeviceSize( aAttributes.m_Size );
1056 int h_code = 0, v_code = 0;
1057
1058 switch( aAttributes.m_Halign )
1059 {
1060 case GR_TEXT_H_ALIGN_LEFT: h_code = 0; break;
1061 case GR_TEXT_H_ALIGN_CENTER: h_code = 1; break;
1062 case GR_TEXT_H_ALIGN_RIGHT: h_code = 2; break;
1063 case GR_TEXT_H_ALIGN_INDETERMINATE: wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) ); break;
1064 }
1065
1066 switch( aAttributes.m_Valign )
1067 {
1068 case GR_TEXT_V_ALIGN_TOP: v_code = 3; break;
1069 case GR_TEXT_V_ALIGN_CENTER: v_code = 2; break;
1070 case GR_TEXT_V_ALIGN_BOTTOM: v_code = 1; break;
1071 case GR_TEXT_V_ALIGN_INDETERMINATE: wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) ); break;
1072 }
1073
1074 std::string textStyle = "KICAD";
1075 if( aAttributes.m_Bold )
1076 {
1077 if( aAttributes.m_Italic )
1078 textStyle = "KICADBI";
1079 else
1080 textStyle = "KICADB";
1081 }
1082 else if( aAttributes.m_Italic )
1083 textStyle = "KICADI";
1084
1085 // Position, size, rotation and alignment
1086 // The two alignment point usages is somewhat idiot (see the DXF ref)
1087 // Anyway since we don't use the fit/aligned options, they're the same
1088 fmt::print( m_outputFile,
1089 " 0\n"
1090 "TEXT\n"
1091 " 7\n"
1092 "{}\n" // Text style
1093 " 8\n"
1094 "{}\n" // Layer name
1095 " 10\n"
1096 "{}\n" // First point X
1097 " 11\n"
1098 "{}\n" // Second point X
1099 " 20\n"
1100 "{}\n" // First point Y
1101 " 21\n"
1102 "{}\n" // Second point Y
1103 " 40\n"
1104 "{}\n" // Text height
1105 " 41\n"
1106 "{}\n" // Width factor
1107 " 50\n"
1108 "{:.8f}\n" // Rotation
1109 " 51\n"
1110 "{:.8f}\n" // Oblique angle
1111 " 71\n"
1112 "{}\n" // Mirror flags
1113 " 72\n"
1114 "{}\n" // H alignment
1115 " 73\n"
1116 "{}\n", // V alignment
1117 textStyle,
1118 TO_UTF8( cname ),
1119 formatCoord( origin_dev.x ),
1120 formatCoord( origin_dev.x ),
1121 formatCoord( origin_dev.y ),
1122 formatCoord( origin_dev.y ),
1123 formatCoord( size_dev.y ),
1124 formatCoord( fabs( size_dev.x / size_dev.y ) ),
1125 aAttributes.m_Angle.AsDegrees(),
1126 aAttributes.m_Italic ? DXF_OBLIQUE_ANGLE : 0,
1127 aAttributes.m_Mirrored ? 2 : 0, // X mirror flag
1128 h_code, v_code );
1129
1130 /* There are two issue in emitting the text:
1131 - Our overline character (~) must be converted to the appropriate
1132 control sequence %%O or %%o
1133 - Text encoding in DXF is more or less unspecified since depends on
1134 the DXF declared version, the acad version reading it *and* some
1135 system variables to be put in the header handled only by newer acads
1136 Also before R15 unicode simply is not supported (you need to use
1137 bigfonts which are a massive PITA). Common denominator solution:
1138 use Latin1 (and however someone could choke on it, anyway). Sorry
1139 for the extended latin people. If somewant want to try fixing this
1140 recent version seems to use UTF-8 (and not UCS2 like the rest of
1141 Windows)
1142
1143 XXX Actually there is a *third* issue: older DXF formats are limited
1144 to 255 bytes records (it was later raised to 2048); since I'm lazy
1145 and text so long is not probable I just don't implement this rule.
1146 If someone is interested in fixing this, you have to emit the first
1147 partial lines with group code 3 (max 250 bytes each) and then finish
1148 with a group code 1 (less than 250 bytes). The DXF refs explains it
1149 in no more details...
1150 */
1151
1152 int braceNesting = 0;
1153 int overbarDepth = -1;
1154
1155 fmt::print( m_outputFile, " 1\n" );
1156
1157 for( unsigned int i = 0; i < aText.length(); i++ )
1158 {
1159 /* Here I do a bad thing: writing the output one byte at a time!
1160 but today I'm lazy and I have no idea on how to coerce a Unicode
1161 wxString to spit out latin1 encoded text ...
1162
1163 At least stdio is *supposed* to do output buffering, so there is
1164 hope is not too slow */
1165 wchar_t ch = aText[i];
1166
1167 if( ch > 255 )
1168 {
1169 // I can't encode this...
1170 putc( '?', m_outputFile );
1171 }
1172 else
1173 {
1174 if( aText[i] == '~' && i+1 < aText.length() && aText[i+1] == '{' )
1175 {
1176 fmt::print( m_outputFile, "%%o" );
1177 overbarDepth = braceNesting;
1178
1179 // Skip the '{'
1180 i++;
1181 continue;
1182 }
1183 else if( aText[i] == '{' )
1184 {
1185 braceNesting++;
1186 }
1187 else if( aText[i] == '}' )
1188 {
1189 if( braceNesting > 0 )
1190 braceNesting--;
1191
1192 if( braceNesting == overbarDepth )
1193 {
1194 fmt::print( m_outputFile, "%%O" );
1195 overbarDepth = -1;
1196 continue;
1197 }
1198 }
1199
1200 putc( ch, m_outputFile );
1201 }
1202 }
1203
1204 fmt::print( m_outputFile, "\n" );
1205}
int color
Definition: DXF_plotter.cpp:63
static const struct @18 dxf_layer[NBCOLORS]
The layer/colors palette.
static wxString getDXFColorName(const COLOR4D &aColor)
static const double DXF_OBLIQUE_ANGLE
Oblique angle for DXF native text (I don't remember if 15 degrees is the ISO value....
Definition: DXF_plotter.cpp:39
static std::string formatCoord(double aValue)
bool containsNonAsciiChars(const wxString &string)
Check if a given string contains non-ASCII characters.
static const char * getDXFLineType(LINE_STYLE aType)
const char * name
Definition: DXF_plotter.cpp:62
#define DXF_LINE_WIDTH
Definition: DXF_plotter.cpp:42
@ ERROR_INSIDE
Definition: approximation.h:34
void plotOneLineOfText(const VECTOR2I &aPos, const COLOR4D &aColor, const wxString &aText, const TEXT_ATTRIBUTES &aAttrs)
DXF_UNITS m_plotUnits
Definition: plotter_dxf.h:229
virtual void PlotText(const VECTOR2I &aPos, const COLOR4D &aColor, const wxString &aText, const TEXT_ATTRIBUTES &aAttributes, KIFONT::FONT *aFont, const KIFONT::METRICS &aFontMetrics, void *aData=nullptr) override
bool m_textAsLines
Definition: plotter_dxf.h:225
virtual void FlashPadCustom(const VECTOR2I &aPadPos, const VECTOR2I &aSize, const EDA_ANGLE &aOrient, SHAPE_POLY_SET *aPolygons, void *aData) override
virtual void ThickCircle(const VECTOR2I &pos, int diametre, int width, void *aData) override
void SetUnits(DXF_UNITS aUnit)
Set the units to use for plotting the DXF file.
virtual void SetViewport(const VECTOR2I &aOffset, double aIusPerDecimil, double aScale, bool aMirror) override
Set the scale/position for the DXF plot.
virtual void ThickArc(const VECTOR2D &aCentre, const EDA_ANGLE &aStAngle, const EDA_ANGLE &aAngle, double aRadius, int aWidth, void *aData) override
virtual void Arc(const VECTOR2D &aCenter, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aAngle, double aRadius, FILL_T aFill, int aWidth) override
double GetUnitScaling() const
Get the scale factor to apply to convert the device units to be in the currently set units.
Definition: plotter_dxf.h:206
virtual void FlashPadOval(const VECTOR2I &aPos, const VECTOR2I &aSize, const EDA_ANGLE &aOrient, void *aData) override
DXF oval pad: always done in sketch mode.
virtual void FlashPadRect(const VECTOR2I &aPos, const VECTOR2I &aSize, const EDA_ANGLE &aOrient, void *aData) override
DXF rectangular pad: always done in sketch mode.
virtual void ThickRect(const VECTOR2I &p1, const VECTOR2I &p2, int width, void *aData) override
virtual void FlashPadRoundRect(const VECTOR2I &aPadPos, const VECTOR2I &aSize, int aCornerRadius, const EDA_ANGLE &aOrient, void *aData) override
virtual void ThickPoly(const SHAPE_POLY_SET &aPoly, int aWidth, void *aData) override
virtual bool StartPlot(const wxString &aPageNumber) override
Open the DXF plot with a skeleton header.
unsigned int GetMeasurementDirective() const
Get the correct value for the $MEASUREMENT field given the current units.
Definition: plotter_dxf.h:216
virtual void FlashPadTrapez(const VECTOR2I &aPadPos, const VECTOR2I *aCorners, const EDA_ANGLE &aPadOrient, void *aData) override
DXF trapezoidal pad: only sketch mode is supported.
virtual void Circle(const VECTOR2I &pos, int diametre, FILL_T fill, int width) override
DXF circle: full functionality; it even does 'fills' drawing a circle with a dual-arc polyline wide a...
virtual void FlashPadCircle(const VECTOR2I &pos, int diametre, void *aData) override
DXF round pad: always done in sketch mode; it could be filled but it isn't pretty if other kinds of p...
virtual void FilledCircle(const VECTOR2I &pos, int diametre, void *aData) override
virtual void PlotPoly(const std::vector< VECTOR2I > &aCornerList, FILL_T aFill, int aWidth, void *aData=nullptr) override
DXF polygon: doesn't fill it but at least it close the filled ones DXF does not know thick outline.
unsigned int m_measurementDirective
Definition: plotter_dxf.h:231
virtual bool EndPlot() override
virtual void FlashRegularPolygon(const VECTOR2I &aShapePos, int aDiameter, int aCornerCount, const EDA_ANGLE &aOrient, void *aData) override
Flash a regular polygon.
virtual void PenTo(const VECTOR2I &pos, char plume) override
Moveto/lineto primitive, moves the 'pen' to the specified direction.
virtual void Rect(const VECTOR2I &p1, const VECTOR2I &p2, FILL_T fill, int width) override
DXF rectangle: fill not supported.
virtual void SetColor(const COLOR4D &color) override
The DXF exporter handles 'colors' as layers...
virtual void Text(const VECTOR2I &aPos, const COLOR4D &aColor, const wxString &aText, const EDA_ANGLE &aOrient, const VECTOR2I &aSize, enum GR_TEXT_H_ALIGN_T aH_justify, enum GR_TEXT_V_ALIGN_T aV_justify, int aWidth, bool aItalic, bool aBold, bool aMultilineAllowed, KIFONT::FONT *aFont, const KIFONT::METRICS &aFontMetrics, void *aData=nullptr) override
Draw text with the plotter.
virtual void ThickSegment(const VECTOR2I &start, const VECTOR2I &end, int width, void *aData) override
double m_unitScalingFactor
Definition: plotter_dxf.h:230
virtual void SetDash(int aLineWidth, LINE_STYLE aLineStyle) override
COLOR4D m_currentColor
Definition: plotter_dxf.h:226
LINE_STYLE m_currentLineType
Definition: plotter_dxf.h:227
double AsDegrees() const
Definition: eda_angle.h:116
FONT is an abstract base class for both outline and stroke fonts.
Definition: font.h:131
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
double r
Red component.
Definition: color4d.h:392
double g
Green component.
Definition: color4d.h:393
static EDA_COLOR_T FindNearestLegacyColor(int aR, int aG, int aB)
Returns a legacy color ID that is closest to the given 8-bit RGB values.
Definition: color4d.cpp:540
double b
Blue component.
Definition: color4d.h:394
bool m_plotMirror
Definition: plotter.h:654
void MoveTo(const VECTOR2I &pos)
Definition: plotter.h:261
virtual void ThickOval(const VECTOR2I &aPos, const VECTOR2I &aSize, const EDA_ANGLE &aOrient, int aWidth, void *aData)
Definition: plotter.cpp:485
void FinishTo(const VECTOR2I &pos)
Definition: plotter.h:271
double m_iuPerDeviceUnit
Definition: plotter.h:651
VECTOR2I m_plotOffset
Definition: plotter.h:653
VECTOR2I m_penLastpos
Definition: plotter.h:667
virtual VECTOR2D userToDeviceCoordinates(const VECTOR2I &aCoordinate)
Modify coordinates according to the orientation, scale factor, and offsets trace.
Definition: plotter.cpp:91
VECTOR2I m_paperSize
Definition: plotter.h:675
virtual VECTOR2D userToDeviceSize(const VECTOR2I &size)
Modify size according to the plotter scale factors (VECTOR2I version, returns a VECTOR2D).
Definition: plotter.cpp:116
int GetPlotterArcHighDef() const
Definition: plotter.h:228
double m_plotScale
Plot scale - chosen by the user (even implicitly with 'fit in a4')
Definition: plotter.h:643
bool GetColorMode() const
Definition: plotter.h:149
FILE * m_outputFile
Output file.
Definition: plotter.h:660
void LineTo(const VECTOR2I &pos)
Definition: plotter.h:266
void PenFinish()
Definition: plotter.h:277
virtual void PlotText(const VECTOR2I &aPos, const COLOR4D &aColor, const wxString &aText, const TEXT_ATTRIBUTES &aAttributes, KIFONT::FONT *aFont=nullptr, const KIFONT::METRICS &aFontMetrics=KIFONT::METRICS::Default(), void *aData=nullptr)
Definition: plotter.cpp:687
virtual void PlotPoly(const std::vector< VECTOR2I > &aCornerList, FILL_T aFill, int aWidth, void *aData)=0
Draw a polygon ( filled or not ).
virtual void Text(const VECTOR2I &aPos, const COLOR4D &aColor, const wxString &aText, const EDA_ANGLE &aOrient, const VECTOR2I &aSize, enum GR_TEXT_H_ALIGN_T aH_justify, enum GR_TEXT_V_ALIGN_T aV_justify, int aPenWidth, bool aItalic, bool aBold, bool aMultilineAllowed, KIFONT::FONT *aFont, const KIFONT::METRICS &aFontMetrics, void *aData=nullptr)
Draw text with the plotter.
Definition: plotter.cpp:624
double m_IUsPerDecimil
Definition: plotter.h:649
bool m_colorMode
Definition: plotter.h:663
virtual DXF_OUTLINE_MODE GetDXFPlotMode() const
Definition: plotter.h:109
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
void Fracture()
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
void Deflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError)
int OutlineCount() const
Return the number of outlines in the set.
SHAPE_POLY_SET CloneDropTriangulation() const
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
GR_TEXT_H_ALIGN_T m_Halign
GR_TEXT_V_ALIGN_T m_Valign
EDA_COLOR_T
Legacy color enumeration.
Definition: color4d.h:42
@ NBCOLORS
Number of colors.
Definition: color4d.h:79
@ BLACK
Definition: color4d.h:44
void TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aPosition, const VECTOR2I &aSize, const EDA_ANGLE &aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aInflate, int aError, ERROR_LOC aErrorLoc)
Convert a rectangle with rounded corners and/or chamfered corners to a polygon.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
static constexpr EDA_ANGLE ANGLE_90
Definition: eda_angle.h:406
FILL_T
Definition: eda_shape.h:56
This file contains miscellaneous commonly used macros and functions.
DXF_UNITS
Definition: plotter.h:52
@ SKETCH
Definition: plotter.h:81
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:429
LINE_STYLE
Dashed line types.
Definition: stroke_params.h:46
int radius
VECTOR2I end
GR_TEXT_H_ALIGN_T
This is API surface mapped to common.types.HorizontalAlignment.
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_H_ALIGN_INDETERMINATE
GR_TEXT_V_ALIGN_T
This is API surface mapped to common.types.VertialAlignment.
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_INDETERMINATE
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
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:229
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695