KiCad PCB EDA Suite
dxf_import_plugin.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 (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25// The DXF reader lib (libdxfrw) comes from dxflib project used in QCAD
26// See http://www.ribbonsoft.com
27// Each time a dxf entity is read, a "call back" function is called
28// like void DXF_IMPORT_PLUGIN::addLine( const DL_LineData& data ) when a line is read.
29// this function just add the BOARD entity from dxf parameters (start and end point ...)
30
31
32#include "dxf_import_plugin.h"
33#include <wx/arrstr.h>
34#include <wx/regex.h>
35
36#include <trigo.h>
37#include <macros.h>
38#include <cmath> // isnan
39#include <board.h>
40#include "common.h"
41
42
43/*
44 * Important notes
45 * 1. All output coordinates of this importer are in mm
46 * 2. DXFs have a concept of world (WCS) and object coordinates (OCS)
47 3. The following objects are world coordinates:
48 - Line
49 - Point
50 - Polyline (3D)
51 - Vertex (3D)
52 - Polymesh
53 - Polyface
54 - Viewport
55 4. The following entities are object coordinates
56 - Circle
57 - Arc
58 - Solid
59 - Trace
60 - Attrib
61 - Shape
62 - Insert
63 - Polyline (2D)
64 - Vertex (2D)
65 - LWPolyline
66 - Hatch
67 - Image
68 - Text
69 * 5. Object coordinates must be run through the arbitrary axis
70 * translation even though they are 2D drawings and most of the time
71 * the import is fine. Sometimes, against all logic, CAD tools like
72 * SolidWorks may randomly insert circles "mirror" that must be unflipped
73 * by following the object to world conversion
74 * 6. Blocks are virtual groups, blocks must be placed by a INSERT entity
75 * 7. Blocks may be repeated multiple times
76 * 8. There is no sane way to make text look perfect like the original CAD.
77 * DXF simply does mpt secifying text/font enough to make it portable.
78 * We however make do try to get it somewhat close/visually appealing.
79 * 9. We silently drop the z coordinate on 3d polylines
80 */
81
82
83// minimum bulge value before resorting to a line segment;
84// the value 0.0218 is equivalent to about 5 degrees arc,
85#define MIN_BULGE 0.0218
86
87#define SCALE_FACTOR(x) (x)
88
89
91{
92 m_xOffset = 0.0; // X coord offset for conversion (in mm)
93 m_yOffset = 0.0; // Y coord offset for conversion (in mm)
94 m_version = 0; // the dxf version, not yet used
95 m_defaultThickness = 0.2; // default thickness (in mm)
96 m_brdLayer = Dwgs_User; // The default import layer
97 m_importAsFPShapes = true;
98 m_minX = m_minY = std::numeric_limits<double>::max();
99 m_maxX = m_maxY = std::numeric_limits<double>::min();
101 m_importCoordinatePrecision = 4; // initial value per dxf spec
102 m_importAnglePrecision = 0; // initial value per dxf spec
103
104 // placeholder layer so we can fallback to something later
105 std::unique_ptr<DXF_IMPORT_LAYER> layer0 =
106 std::make_unique<DXF_IMPORT_LAYER>( "", DXF_IMPORT_LINEWEIGHT_BY_LW_DEFAULT );
107 m_layers.push_back( std::move( layer0 ) );
108
109 m_currentBlock = nullptr;
110}
111
112
114{
115}
116
117
118bool DXF_IMPORT_PLUGIN::Load( const wxString& aFileName )
119{
120 try
121 {
122 return ImportDxfFile( aFileName );
123 }
124 catch( const std::bad_alloc& )
125 {
126 m_layers.clear();
127 m_blocks.clear();
128 m_styles.clear();
129
131
132 reportMsg( _( "Memory was exhausted trying to load the DXF, it may be too large." ) );
133 return false;
134 }
135}
136
137
139{
140 wxCHECK( m_importer, false );
142
143 return true;
144}
145
146
148{
149 return m_maxX - m_minX;
150}
151
152
154{
155 return m_maxY - m_minY;
156}
157
158
160{
162
163 if( m_importer )
165}
166
167
168double DXF_IMPORT_PLUGIN::mapX( double aDxfCoordX )
169{
170 return SCALE_FACTOR( m_xOffset + ( aDxfCoordX * getCurrentUnitScale() ) );
171}
172
173
174double DXF_IMPORT_PLUGIN::mapY( double aDxfCoordY )
175{
176 return SCALE_FACTOR( m_yOffset - ( aDxfCoordY * getCurrentUnitScale() ) );
177}
178
179
180double DXF_IMPORT_PLUGIN::mapDim( double aDxfValue )
181{
182 return SCALE_FACTOR( aDxfValue * getCurrentUnitScale() );
183}
184
185
186bool DXF_IMPORT_PLUGIN::ImportDxfFile( const wxString& aFile )
187{
188 DL_Dxf dxf_reader;
189
190 // wxFopen takes care of unicode filenames across platforms
191 FILE* fp = wxFopen( aFile, wxT( "rt" ) );
192
193 if( fp == nullptr )
194 return false;
195
196 // Note the dxf reader takes care of switching to "C" locale before reading the file
197 // and will close the file after reading
198 bool success = dxf_reader.in( fp, this );
199
200 return success;
201}
202
203
204void DXF_IMPORT_PLUGIN::reportMsg( const wxString& aMessage )
205{
206 // Add message to keep trace of not handled dxf entities
207 m_messages += aMessage;
208 m_messages += '\n';
209}
210
211
212void DXF_IMPORT_PLUGIN::addSpline( const DL_SplineData& aData )
213{
214 // Called when starting reading a spline
217 m_curr_entity.m_EntityFlag = aData.flags;
218 m_curr_entity.m_EntityType = DL_ENTITY_SPLINE;
219 m_curr_entity.m_SplineDegree = aData.degree;
220 m_curr_entity.m_SplineTangentStartX = aData.tangentStartX;
221 m_curr_entity.m_SplineTangentStartY = aData.tangentStartY;
222 m_curr_entity.m_SplineTangentEndX = aData.tangentEndX;
223 m_curr_entity.m_SplineTangentEndY = aData.tangentEndY;
224 m_curr_entity.m_SplineKnotsCount = aData.nKnots;
225 m_curr_entity.m_SplineControlCount = aData.nControl;
226 m_curr_entity.m_SplineFitCount = aData.nFit;
227}
228
229
230void DXF_IMPORT_PLUGIN::addControlPoint( const DL_ControlPointData& aData )
231{
232 // Called for every spline control point, when reading a spline entity
233 m_curr_entity.m_SplineControlPointList.emplace_back( aData.x , aData.y,
234 aData.w );
235}
236
237
238void DXF_IMPORT_PLUGIN::addFitPoint( const DL_FitPointData& aData )
239{
240 // Called for every spline fit point, when reading a spline entity
241 // we store only the X,Y coord values in a VECTOR2D
242 m_curr_entity.m_SplineFitPointList.emplace_back( aData.x, aData.y );
243}
244
245
246void DXF_IMPORT_PLUGIN::addKnot( const DL_KnotData& aData)
247{
248 // Called for every spline knot value, when reading a spline entity
249 m_curr_entity.m_SplineKnotsList.push_back( aData.k );
250}
251
252
253void DXF_IMPORT_PLUGIN::addLayer( const DL_LayerData& aData )
254{
255 wxString name = wxString::FromUTF8( aData.name.c_str() );
256
257 int lw = attributes.getWidth();
258
260 {
262 }
263
264 std::unique_ptr<DXF_IMPORT_LAYER> layer = std::make_unique<DXF_IMPORT_LAYER>( name, lw );
265
266 m_layers.push_back( std::move( layer ) );
267}
268
269
270void DXF_IMPORT_PLUGIN::addLinetype( const DL_LinetypeData& data )
271{
272#if 0
273 wxString name = FROM_UTF8( data.name.c_str() );
274 wxString description = FROM_UTF8( data.description.c_str() );
275#endif
276}
277
278
280{
281 if( lw == DXF_IMPORT_LINEWEIGHT_BY_LAYER && aLayer != nullptr )
282 {
283 lw = aLayer->m_lineWeight;
284 }
285
286 // All lineweights >= 0 are always in 100ths of mm
287 double mm = m_defaultThickness;
288
289 if( lw >= 0 )
290 {
291 mm = lw / 100.0;
292 }
293
294 return SCALE_FACTOR( mm );
295}
296
297
299{
300 DXF_IMPORT_LAYER* layer = m_layers.front().get();
301 wxString layerName = wxString::FromUTF8( aLayerName.c_str() );
302
303 if( !layerName.IsEmpty() )
304 {
305 auto resultIt = std::find_if( m_layers.begin(), m_layers.end(),
306 [layerName]( const auto& it )
307 {
308 return it->m_layerName == layerName;
309 } );
310
311 if( resultIt != m_layers.end() )
312 layer = resultIt->get();
313 }
314
315 return layer;
316}
317
318
320{
321 DXF_IMPORT_BLOCK* block = nullptr;
322 wxString blockName = wxString::FromUTF8( aBlockName.c_str() );
323
324 if( !blockName.IsEmpty() )
325 {
326 auto resultIt = std::find_if( m_blocks.begin(), m_blocks.end(),
327 [blockName]( const auto& it )
328 {
329 return it->m_name == blockName;
330 } );
331
332 if( resultIt != m_blocks.end() )
333 block = resultIt->get();
334 }
335
336 return block;
337}
338
339
341{
342 DXF_IMPORT_STYLE* style = nullptr;
343 wxString styleName = wxString::FromUTF8( aStyleName.c_str() );
344
345 if( !styleName.IsEmpty() )
346 {
347 auto resultIt = std::find_if( m_styles.begin(), m_styles.end(),
348 [styleName]( const auto& it ) { return it->m_name == styleName; } );
349
350 if( resultIt != m_styles.end() )
351 style = resultIt->get();
352 }
353
354 return style;
355}
356
357
358void DXF_IMPORT_PLUGIN::addLine( const DL_LineData& aData )
359{
360 DXF_IMPORT_LAYER* layer = getImportLayer( attributes.getLayer() );
361 double lineWidth = lineWeightToWidth( attributes.getWidth(), layer );
362
363 VECTOR2D start( mapX( aData.x1 ), mapY( aData.y1 ) );
364 VECTOR2D end( mapX( aData.x2 ), mapY( aData.y2 ) );
365
366 GRAPHICS_IMPORTER_BUFFER* bufferToUse =
368 bufferToUse->AddLine( start, end, lineWidth );
369
370 updateImageLimits( start );
371 updateImageLimits( end );
372}
373
374
375void DXF_IMPORT_PLUGIN::addPolyline(const DL_PolylineData& aData )
376{
377 // Convert DXF Polylines into a series of KiCad Lines and Arcs.
378 // A Polyline (as opposed to a LWPolyline) may be a 3D line or
379 // even a 3D Mesh. The only type of Polyline which is guaranteed
380 // to import correctly is a 2D Polyline in X and Y, which is what
381 // we assume of all Polylines. The width used is the width of the Polyline.
382 // per-vertex line widths, if present, are ignored.
385 m_curr_entity.m_EntityFlag = aData.flags;
386 m_curr_entity.m_EntityType = DL_ENTITY_POLYLINE;
387}
388
389
390void DXF_IMPORT_PLUGIN::addVertex( const DL_VertexData& aData )
391{
393 return; // Error
394
395 DXF_IMPORT_LAYER* layer = getImportLayer( attributes.getLayer() );
396 double lineWidth = lineWeightToWidth( attributes.getWidth(), layer );
397
398 /* support for per-vertex-encoded linewidth (Cadence uses it) */
399 /* linewidths are scaled by 100 in DXF */
400 if( aData.startWidth > 0.0 )
401 lineWidth = aData.startWidth / 100.0;
402 else if ( aData.endWidth > 0.0 )
403 lineWidth = aData.endWidth / 100.0;
404
405 const DL_VertexData* vertex = &aData;
406
407 DXF_ARBITRARY_AXIS arbAxis = getArbitraryAxis( getExtrusion() );
408 VECTOR3D vertexCoords = ocsToWcs( arbAxis, VECTOR3D( vertex->x, vertex->y, vertex->z ) );
409
410 if( m_curr_entity.m_EntityParseStatus == 1 ) // This is the first vertex of an entity
411 {
412 m_curr_entity.m_LastCoordinate.x = mapX( vertexCoords.x );
413 m_curr_entity.m_LastCoordinate.y = mapY( vertexCoords.y );
415 m_curr_entity.m_BulgeVertex = vertex->bulge;
417 return;
418 }
419
420 VECTOR2D seg_end( mapX( vertexCoords.x ), mapY( vertexCoords.y ) );
421
423 insertLine( m_curr_entity.m_LastCoordinate, seg_end, lineWidth );
424 else
426 lineWidth );
427
429 m_curr_entity.m_BulgeVertex = vertex->bulge;
430}
431
432
434{
435 DXF_IMPORT_LAYER* layer = getImportLayer( attributes.getLayer() );
436 double lineWidth = lineWeightToWidth( attributes.getWidth(), layer );
437
438 if( m_curr_entity.m_EntityType == DL_ENTITY_POLYLINE ||
439 m_curr_entity.m_EntityType == DL_ENTITY_LWPOLYLINE )
440 {
441 // Polyline flags bit 0 indicates closed (1) or open (0) polyline
443 {
446 lineWidth );
447 else
449 m_curr_entity.m_BulgeVertex, lineWidth );
450 }
451 }
452
453 if( m_curr_entity.m_EntityType == DL_ENTITY_SPLINE )
454 {
455 insertSpline( lineWidth );
456 }
457
459}
460
461
462void DXF_IMPORT_PLUGIN::addBlock( const DL_BlockData& aData )
463{
464 wxString name = wxString::FromUTF8( aData.name.c_str() );
465
466 std::unique_ptr<DXF_IMPORT_BLOCK> block =
467 std::make_unique<DXF_IMPORT_BLOCK>( name, aData.bpx, aData.bpy );
468
469 m_blocks.push_back( std::move( block ) );
470
471 m_currentBlock = m_blocks.back().get();
472}
473
474
476{
477 m_currentBlock = nullptr;
478}
479
480void DXF_IMPORT_PLUGIN::addInsert( const DL_InsertData& aData )
481{
482 DXF_IMPORT_BLOCK* block = getImportBlock( aData.name );
483
484 if( block == nullptr )
485 return;
486
487 DXF_ARBITRARY_AXIS arbAxis = getArbitraryAxis( getExtrusion() );
488 VECTOR3D insertCoords = ocsToWcs( arbAxis, VECTOR3D( aData.ipx, aData.ipy, aData.ipz ) );
489
490 VECTOR2D translation( mapX( insertCoords.x ), mapY( insertCoords.y ) );
491 translation -= VECTOR2D( mapX( block->m_baseX ), mapY( block->m_baseY ) );
492
493
494 for( auto& shape : block->m_buffer.GetShapes() )
495 {
496 std::unique_ptr<IMPORTED_SHAPE> newShape = shape->clone();
497
498 newShape->Translate( translation );
499 newShape->Scale( aData.sx, aData.sy );
500
501 m_internalImporter.AddShape( newShape );
502 }
503}
504
505
506void DXF_IMPORT_PLUGIN::addCircle( const DL_CircleData& aData )
507{
508 DXF_ARBITRARY_AXIS arbAxis = getArbitraryAxis( getExtrusion() );
509 VECTOR3D centerCoords = ocsToWcs( arbAxis, VECTOR3D( aData.cx, aData.cy, aData.cz ) );
510
511 VECTOR2D center( mapX( centerCoords.x ), mapY( centerCoords.y ) );
512 DXF_IMPORT_LAYER* layer = getImportLayer( attributes.getLayer() );
513 double lineWidth = lineWeightToWidth( attributes.getWidth(), layer );
514
515 GRAPHICS_IMPORTER_BUFFER* bufferToUse =
517 bufferToUse->AddCircle( center, mapDim( aData.radius ), lineWidth, false );
518
519 VECTOR2D radiusDelta( mapDim( aData.radius ), mapDim( aData.radius ) );
520
521 updateImageLimits( center + radiusDelta );
522 updateImageLimits( center - radiusDelta );
523}
524
525
526void DXF_IMPORT_PLUGIN::addArc( const DL_ArcData& aData )
527{
528 DXF_ARBITRARY_AXIS arbAxis = getArbitraryAxis( getExtrusion() );
529 VECTOR3D centerCoords = ocsToWcs( arbAxis, VECTOR3D( aData.cx, aData.cy, aData.cz ) );
530
531 // Init arc centre:
532 VECTOR2D center( mapX( centerCoords.x ), mapY( centerCoords.y ) );
533
534 // aData.anglex is in degrees.
535 EDA_ANGLE startangle( aData.angle1, DEGREES_T );
536 EDA_ANGLE endangle( aData.angle2, DEGREES_T );
537
538 // Init arc start point
539 VECTOR2D startPoint( aData.radius, 0.0 );
540 RotatePoint( startPoint, -startangle );
541 VECTOR2D arcStart( mapX( startPoint.x + centerCoords.x ),
542 mapY( startPoint.y + centerCoords.y ) );
543
544 // calculate arc angle (arcs are CCW, and should be < 0 in Pcbnew)
545 EDA_ANGLE angle = -( endangle - startangle );
546
547 if( angle > ANGLE_0 )
548 angle -= ANGLE_360;
549
550 DXF_IMPORT_LAYER* layer = getImportLayer( attributes.getLayer() );
551 double lineWidth = lineWeightToWidth( attributes.getWidth(), layer );
552
555 bufferToUse->AddArc( center, arcStart, angle, lineWidth );
556
557 VECTOR2D radiusDelta( mapDim( aData.radius ), mapDim( aData.radius ) );
558
559 updateImageLimits( center + radiusDelta );
560 updateImageLimits( center - radiusDelta );
561}
562
563
564void DXF_IMPORT_PLUGIN::addText( const DL_TextData& aData )
565{
566 DXF_ARBITRARY_AXIS arbAxis = getArbitraryAxis( getExtrusion() );
567 VECTOR3D refPointCoords = ocsToWcs( arbAxis, VECTOR3D( aData.ipx, aData.ipy, aData.ipz ) );
568 VECTOR3D secPointCoords = ocsToWcs( arbAxis, VECTOR3D( std::isnan( aData.apx ) ? 0 : aData.apx,
569 std::isnan( aData.apy ) ? 0 : aData.apy,
570 std::isnan( aData.apz ) ? 0 : aData.apz ) );
571
572 VECTOR2D refPoint( mapX( refPointCoords.x ), mapY( refPointCoords.y ) );
573 VECTOR2D secPoint( mapX( secPointCoords.x ), mapY( secPointCoords.y ) );
574
575 if( aData.vJustification != 0 || aData.hJustification != 0 || aData.hJustification == 4 )
576 {
577 if( aData.hJustification != 3 && aData.hJustification != 5 )
578 {
579 VECTOR2D tmp = secPoint;
580 secPoint = refPoint;
581 refPoint = tmp;
582 }
583 }
584
585 wxString text = toNativeString( wxString::FromUTF8( aData.text.c_str() ) );
586
587 DXF_IMPORT_STYLE* style = getImportStyle( aData.style.c_str() );
588
589 double textHeight = mapDim( aData.height );
590 // The 0.9 factor gives a better height/width base ratio with our font
591 double charWidth = textHeight * 0.9;
592
593 if( style != nullptr )
594 charWidth *= style->m_widthFactor;
595
596 double textWidth = charWidth * text.length(); // Rough approximation
597 double textThickness = textHeight/8.0; // Use a reasonable line thickness for this text
598
599 VECTOR2D bottomLeft(0.0, 0.0);
600 VECTOR2D bottomRight(0.0, 0.0);
601 VECTOR2D topLeft(0.0, 0.0);
602 VECTOR2D topRight(0.0, 0.0);
603
606
607 switch( aData.vJustification )
608 {
609 case 0: //DRW_Text::VBaseLine:
610 case 1: //DRW_Text::VBottom:
611 vJustify = GR_TEXT_V_ALIGN_BOTTOM;
612
613 topLeft.y = textHeight;
614 topRight.y = textHeight;
615 break;
616
617 case 2: //DRW_Text::VMiddle:
618 vJustify = GR_TEXT_V_ALIGN_CENTER;
619
620 bottomRight.y = -textHeight / 2.0;
621 bottomLeft.y = -textHeight / 2.0;
622 topLeft.y = textHeight / 2.0;
623 topRight.y = textHeight / 2.0;
624 break;
625
626 case 3: //DRW_Text::VTop:
627 vJustify = GR_TEXT_V_ALIGN_TOP;
628
629 bottomLeft.y = -textHeight;
630 bottomRight.y = -textHeight;
631 break;
632 }
633
634 switch( aData.hJustification )
635 {
636 case 0: //DRW_Text::HLeft:
637 case 3: //DRW_Text::HAligned: // no equivalent options in text pcb.
638 case 5: //DRW_Text::HFit: // no equivalent options in text pcb.
639 hJustify = GR_TEXT_H_ALIGN_LEFT;
640
641 bottomRight.x = textWidth;
642 topRight.x = textWidth;
643 break;
644
645 case 1: //DRW_Text::HCenter:
646 case 4: //DRW_Text::HMiddle: // no equivalent options in text pcb.
647 hJustify = GR_TEXT_H_ALIGN_CENTER;
648
649 bottomLeft.x = -textWidth / 2.0;
650 topLeft.x = -textWidth / 2.0;
651 bottomRight.x = textWidth / 2.0;
652 topRight.x = textWidth / 2.0;
653 break;
654
655 case 2: //DRW_Text::HRight:
656 hJustify = GR_TEXT_H_ALIGN_RIGHT;
657
658 bottomLeft.x = -textWidth;
659 topLeft.x = -textWidth;
660 break;
661 }
662
663#if 0
664 wxString sty = wxString::FromUTF8( aData.style.c_str() );
665 sty = sty.ToLower();
666
667 if( aData.textgen == 2 )
668 {
669 // Text dir = left to right;
670 } else if( aData.textgen == 4 )
671 {
672 // Text dir = top to bottom;
673 } else
674 {
675 }
676#endif
677
678 // dxf_lib imports text angle in radians (although there are no comment about that.
679 // So, for the moment, convert this angle to degrees
680 double angle_degree = aData.angle * 180 / M_PI;
681 // We also need the angle in radians. so convert angle_degree to radians
682 // regardless the aData.angle unit
683 double angleInRads = angle_degree * M_PI / 180.0;
684 double cosine = cos(angleInRads);
685 double sine = sin(angleInRads);
686
687 GRAPHICS_IMPORTER_BUFFER* bufferToUse =
689 bufferToUse->AddText( refPoint, text, textHeight, charWidth, textThickness, angle_degree,
690 hJustify, vJustify );
691
692 // Calculate the boundary box and update the image limits:
693 bottomLeft.x = bottomLeft.x * cosine - bottomLeft.y * sine;
694 bottomLeft.y = bottomLeft.x * sine + bottomLeft.y * cosine;
695
696 bottomRight.x = bottomRight.x * cosine - bottomRight.y * sine;
697 bottomRight.y = bottomRight.x * sine + bottomRight.y * cosine;
698
699 topLeft.x = topLeft.x * cosine - topLeft.y * sine;
700 topLeft.y = topLeft.x * sine + topLeft.y * cosine;
701
702 topRight.x = topRight.x * cosine - topRight.y * sine;
703 topRight.y = topRight.x * sine + topRight.y * cosine;
704
705 bottomLeft += refPoint;
706 bottomRight += refPoint;
707 topLeft += refPoint;
708 topRight += refPoint;
709
710 updateImageLimits( bottomLeft );
711 updateImageLimits( bottomRight );
712 updateImageLimits( topLeft );
713 updateImageLimits( topRight );
714
715}
716
717
718void DXF_IMPORT_PLUGIN::addMText( const DL_MTextData& aData )
719{
720 wxString text = toNativeString( wxString::FromUTF8( aData.text.c_str() ) );
721 wxString attrib, tmp;
722
723 DXF_IMPORT_STYLE* style = getImportStyle( aData.style.c_str() );
724
725 double textHeight = mapDim( aData.height );
726
727 // The 0.9 factor gives a better height/width base ratio with our font
728 double charWidth = textHeight * 0.9;
729 if( style != nullptr )
730 charWidth *= style->m_widthFactor;
731
732 double textWidth = charWidth * text.length(); // Rough approximation
733 double textThickness = textHeight/8.0; // Use a reasonable line thickness for this text
734
735 VECTOR2D bottomLeft(0.0, 0.0);
736 VECTOR2D bottomRight(0.0, 0.0);
737 VECTOR2D topLeft(0.0, 0.0);
738 VECTOR2D topRight(0.0, 0.0);
739
740 /* Some texts start by '\' and have formatting chars (font name, font option...)
741 * ending with ';'
742 * Here are some mtext formatting codes:
743 * Format code Purpose
744 * \0...\o Turns overline on and off
745 * \L...\l Turns underline on and off
746 * \~ Inserts a nonbreaking space
747 \\ Inserts a backslash
748 \\\{...\} Inserts an opening and closing brace
749 \\ \File name; Changes to the specified font file
750 \\ \Hvalue; Changes to the text height specified in drawing units
751 \\ \Hvaluex; Changes the text height to a multiple of the current text height
752 \\ \S...^...; Stacks the subsequent text at the \, #, or ^ symbol
753 \\ \Tvalue; Adjusts the space between characters, from.75 to 4 times
754 \\ \Qangle; Changes oblique angle
755 \\ \Wvalue; Changes width factor to produce wide text
756 \\ \A Sets the alignment value; valid values: 0, 1, 2 (bottom, center, top) while( text.StartsWith( wxT("\\") ) )
757 */
758 while( text.StartsWith( wxT( "\\" ) ) )
759 {
760 attrib << text.BeforeFirst( ';' );
761 tmp = text.AfterFirst( ';' );
762 text = tmp;
763 }
764
765 DXF_ARBITRARY_AXIS arbAxis = getArbitraryAxis( getExtrusion() );
766 VECTOR3D textposCoords = ocsToWcs( arbAxis, VECTOR3D( aData.ipx, aData.ipy, aData.ipz ) );
767
768 VECTOR2D textpos( mapX( textposCoords.x ), mapY( textposCoords.y ) );
769
770 // Initialize text justifications:
773
774 if( aData.attachmentPoint <= 3 )
775 {
776 vJustify = GR_TEXT_V_ALIGN_TOP;
777
778 bottomLeft.y = -textHeight;
779 bottomRight.y = -textHeight;
780 }
781 else if( aData.attachmentPoint <= 6 )
782 {
783 vJustify = GR_TEXT_V_ALIGN_CENTER;
784
785 bottomRight.y = -textHeight / 2.0;
786 bottomLeft.y = -textHeight / 2.0;
787 topLeft.y = textHeight / 2.0;
788 topRight.y = textHeight / 2.0;
789 }
790 else
791 {
792 vJustify = GR_TEXT_V_ALIGN_BOTTOM;
793
794 topLeft.y = textHeight;
795 topRight.y = textHeight;
796 }
797
798 if( aData.attachmentPoint % 3 == 1 )
799 {
800 hJustify = GR_TEXT_H_ALIGN_LEFT;
801
802 bottomRight.x = textWidth;
803 topRight.x = textWidth;
804 }
805 else if( aData.attachmentPoint % 3 == 2 )
806 {
807 hJustify = GR_TEXT_H_ALIGN_CENTER;
808
809 bottomLeft.x = -textWidth / 2.0;
810 topLeft.x = -textWidth / 2.0;
811 bottomRight.x = textWidth / 2.0;
812 topRight.x = textWidth / 2.0;
813 }
814 else
815 {
816 hJustify = GR_TEXT_H_ALIGN_RIGHT;
817
818 bottomLeft.x = -textWidth;
819 topLeft.x = -textWidth;
820 }
821
822#if 0 // These setting have no meaning in Pcbnew
823 if( data.alignH == 1 )
824 {
825 // Text is left to right;
826 }
827 else if( data.alignH == 3 )
828 {
829 // Text is top to bottom;
830 }
831 else
832 {
833 // use ByStyle;
834 }
835
836 if( aData.alignV == 1 )
837 {
838 // use AtLeast;
839 }
840 else
841 {
842 // useExact;
843 }
844#endif
845
846 // dxf_lib imports text angle in radians (although there are no comment about that.
847 // So, for the moment, convert this angle to degrees
848 double angle_degree = aData.angle * 180/M_PI;
849 // We also need the angle in radians. so convert angle_degree to radians
850 // regardless the aData.angle unit
851 double angleInRads = angle_degree * M_PI / 180.0;
852 double cosine = cos(angleInRads);
853 double sine = sin(angleInRads);
854
855
856 GRAPHICS_IMPORTER_BUFFER* bufferToUse =
858 bufferToUse->AddText( textpos, text, textHeight, charWidth,
859 textThickness, angle_degree, hJustify, vJustify );
860
861 bottomLeft.x = bottomLeft.x * cosine - bottomLeft.y * sine;
862 bottomLeft.y = bottomLeft.x * sine + bottomLeft.y * cosine;
863
864 bottomRight.x = bottomRight.x * cosine - bottomRight.y * sine;
865 bottomRight.y = bottomRight.x * sine + bottomRight.y * cosine;
866
867 topLeft.x = topLeft.x * cosine - topLeft.y * sine;
868 topLeft.y = topLeft.x * sine + topLeft.y * cosine;
869
870 topRight.x = topRight.x * cosine - topRight.y * sine;
871 topRight.y = topRight.x * sine + topRight.y * cosine;
872
873 bottomLeft += textpos;
874 bottomRight += textpos;
875 topLeft += textpos;
876 topRight += textpos;
877
878 updateImageLimits( bottomLeft );
879 updateImageLimits( bottomRight );
880 updateImageLimits( topLeft );
881 updateImageLimits( topRight );
882
883}
884
885
887{
888 double scale = 1.0;
889 switch( m_currentUnit )
890 {
892 scale = 25.4;
893 break;
894
896 scale = 304.8;
897 break;
898
900 scale = 1.0;
901 break;
902
904 scale = 10.0;
905 break;
906
908 scale = 1000.0;
909 break;
910
912 scale = 2.54e-5;
913 break;
914
916 scale = 0.0254;
917 break;
918
920 scale = 914.4;
921 break;
922
924 scale = 1.0e-7;
925 break;
926
928 scale = 1.0e-6;
929 break;
930
932 scale = 1.0e-3;
933 break;
934
936 scale = 100.0;
937 break;
938
939 default:
940 // use the default of 1.0 for:
941 // 0: Unspecified Units
942 // 3: miles
943 // 7: kilometers
944 // 15: decameters
945 // 16: hectometers
946 // 17: gigameters
947 // 18: AU
948 // 19: lightyears
949 // 20: parsecs
950 scale = 1.0;
951 break;
952 }
953
954 return scale;
955}
956
957
958
959void DXF_IMPORT_PLUGIN::setVariableInt( const std::string& key, int value, int code )
960{
961 // Called for every int variable in the DXF file (e.g. "$INSUNITS").
962
963 if( key == "$DWGCODEPAGE" )
964 {
965 m_codePage = value;
966 return;
967 }
968
969 if( key == "$AUPREC" )
970 {
972 return;
973 }
974
975 if( key == "$LUPREC" )
976 {
978 return;
979 }
980
981 if( key == "$INSUNITS" ) // Drawing units
982 {
983 switch( value )
984 {
985 case 1: // inches
987 break;
988
989 case 2: // feet
991 break;
992
993 case 4: // mm
995 break;
996
997 case 5: // centimeters
999 break;
1000
1001 case 6: // meters
1003 break;
1004
1005 case 8: // microinches
1007 break;
1008
1009 case 9: // mils
1011 break;
1012
1013 case 10: // yards
1015 break;
1016
1017 case 11: // Angstroms
1019 break;
1020
1021 case 12: // nanometers
1023 break;
1024
1025 case 13: // micrometers
1027 break;
1028
1029 case 14: // decimeters
1031 break;
1032
1033 default:
1034 // use the default of 1.0 for:
1035 // 0: Unspecified Units
1036 // 3: miles
1037 // 7: kilometers
1038 // 15: decameters
1039 // 16: hectometers
1040 // 17: gigameters
1041 // 18: AU
1042 // 19: lightyears
1043 // 20: parsecs
1045 break;
1046 }
1047
1048 return;
1049 }
1050}
1051
1052
1053void DXF_IMPORT_PLUGIN::setVariableString( const std::string& key, const std::string& value,
1054 int code )
1055{
1056 // Called for every string variable in the DXF file (e.g. "$ACADVER").
1057}
1058
1059
1060wxString DXF_IMPORT_PLUGIN::toDxfString( const wxString& aStr )
1061{
1062 wxString res;
1063 int j = 0;
1064
1065 for( unsigned i = 0; i<aStr.length(); ++i )
1066 {
1067 int c = aStr[i];
1068
1069 if( c > 175 || c < 11 )
1070 {
1071 res.append( aStr.Mid( j, i - j ) );
1072 j = i;
1073
1074 switch( c )
1075 {
1076 case 0x0A:
1077 res += wxT( "\\P" );
1078 break;
1079
1080 // diameter:
1081#ifdef _WIN32
1082 // windows, as always, is special.
1083 case 0x00D8:
1084#else
1085 case 0x2205:
1086#endif
1087 res += wxT( "%%C" );
1088 break;
1089
1090 // degree:
1091 case 0x00B0:
1092 res += wxT( "%%D" );
1093 break;
1094
1095 // plus/minus
1096 case 0x00B1:
1097 res += wxT( "%%P" );
1098 break;
1099
1100 default:
1101 j--;
1102 break;
1103 }
1104
1105 j++;
1106 }
1107 }
1108
1109 res.append( aStr.Mid( j ) );
1110 return res;
1111}
1112
1113
1114wxString DXF_IMPORT_PLUGIN::toNativeString( const wxString& aData )
1115{
1116 wxString res;
1117
1118 // Ignore font tags:
1119 int j = 0;
1120
1121 for( unsigned i = 0; i < aData.length(); ++i )
1122 {
1123 if( aData[ i ] == 0x7B ) // is '{' ?
1124 {
1125 if( aData[ i + 1 ] == 0x5c && aData[ i + 2 ] == 0x66 ) // is "\f" ?
1126 {
1127 // found font tag, append parsed part
1128 res.append( aData.Mid( j, i - j ) );
1129
1130 // skip to ';'
1131 for( unsigned k = i + 3; k < aData.length(); ++k )
1132 {
1133 if( aData[ k ] == 0x3B )
1134 {
1135 i = j = ++k;
1136 break;
1137 }
1138 }
1139
1140 // add to '}'
1141 for( unsigned k = i; k < aData.length(); ++k )
1142 {
1143 if( aData[ k ] == 0x7D )
1144 {
1145 res.append( aData.Mid( i, k - i ) );
1146 i = j = ++k;
1147 break;
1148 }
1149 }
1150 }
1151 }
1152 }
1153
1154 res.append( aData.Mid( j ) );
1155
1156#if 1
1157 wxRegEx regexp;
1158 // Line feed:
1159 regexp.Compile( wxT( "\\\\P" ) );
1160 regexp.Replace( &res, wxT( "\n" ) );
1161
1162 // Space:
1163 regexp.Compile( wxT( "\\\\~" ) );
1164 regexp.Replace( &res, wxT( " " ) );
1165
1166 // diameter:
1167 regexp.Compile( wxT( "%%[cC]" ) );
1168#ifdef __WINDOWS__
1169 // windows, as always, is special.
1170 regexp.Replace( &res, wxChar( 0xD8 ) );
1171#else
1172 // Empty_set, diameter is 0x2300
1173 regexp.Replace( &res, wxChar( 0x2205 ) );
1174#endif
1175
1176 // degree:
1177 regexp.Compile( wxT( "%%[dD]" ) );
1178 regexp.Replace( &res, wxChar( 0x00B0 ) );
1179 // plus/minus
1180 regexp.Compile( wxT( "%%[pP]" ) );
1181 regexp.Replace( &res, wxChar( 0x00B1 ) );
1182#endif
1183
1184 return res;
1185}
1186
1187
1188void DXF_IMPORT_PLUGIN::addTextStyle( const DL_StyleData& aData )
1189{
1190 wxString name = wxString::FromUTF8( aData.name.c_str() );
1191
1192 std::unique_ptr<DXF_IMPORT_STYLE> style =
1193 std::make_unique<DXF_IMPORT_STYLE>( name, aData.fixedTextHeight, aData.widthFactor, aData.bold, aData.italic );
1194
1195 m_styles.push_back( std::move( style ) );
1196}
1197
1198
1199void DXF_IMPORT_PLUGIN::addPoint( const DL_PointData& aData )
1200{
1201 DXF_ARBITRARY_AXIS arbAxis = getArbitraryAxis( getExtrusion() );
1202 VECTOR3D centerCoords = ocsToWcs( arbAxis, VECTOR3D( aData.x, aData.y, aData.z ) );
1203
1204 VECTOR2D center( mapX( centerCoords.x ), mapY( centerCoords.y ) );
1205
1206 // we emulate points with filled circles
1207 // set the linewidth to something that even small circles look good with
1208 // thickness is optional for dxf points
1209 // note: we had to modify the dxf library to grab the attribute for thickness
1210 double lineWidth = 0.0001;
1211 double thickness = mapDim( std::max( aData.thickness, 0.01 ) );
1212
1213 GRAPHICS_IMPORTER_BUFFER* bufferToUse =
1215 bufferToUse->AddCircle( center, thickness, lineWidth, true );
1216
1217 VECTOR2D radiusDelta( SCALE_FACTOR( thickness ), SCALE_FACTOR( thickness ) );
1218
1219 updateImageLimits( center + radiusDelta );
1220 updateImageLimits( center - radiusDelta );
1221}
1222
1223
1225 const VECTOR2D& aSegEnd, double aWidth )
1226{
1227 VECTOR2D origin( SCALE_FACTOR( aSegStart.x ), SCALE_FACTOR( aSegStart.y ) );
1228 VECTOR2D end( SCALE_FACTOR( aSegEnd.x ), SCALE_FACTOR( aSegEnd.y ) );
1229
1230 GRAPHICS_IMPORTER_BUFFER* bufferToUse =
1232 bufferToUse->AddLine( origin, end, aWidth );
1233
1234 updateImageLimits( origin );
1235 updateImageLimits( end );
1236}
1237
1238
1239void DXF_IMPORT_PLUGIN::insertArc( const VECTOR2D& aSegStart, const VECTOR2D& aSegEnd,
1240 double aBulge, double aWidth )
1241{
1242 VECTOR2D segment_startpoint( SCALE_FACTOR( aSegStart.x ), SCALE_FACTOR( aSegStart.y ) );
1243 VECTOR2D segment_endpoint( SCALE_FACTOR( aSegEnd.x ), SCALE_FACTOR( aSegEnd.y ) );
1244
1245 // ensure aBulge represents an angle from +/- ( 0 .. approx 359.8 deg )
1246 if( aBulge < -2000.0 )
1247 aBulge = -2000.0;
1248 else if( aBulge > 2000.0 )
1249 aBulge = 2000.0;
1250
1251 double ang = 4.0 * atan( aBulge );
1252
1253 // reflect the Y values to put everything in a RHCS
1254 VECTOR2D sp( aSegStart.x, -aSegStart.y );
1255 VECTOR2D ep( aSegEnd.x, -aSegEnd.y );
1256 // angle from end->start
1257 double offAng = atan2( ep.y - sp.y, ep.x - sp.x );
1258 // length of subtended segment = 1/2 distance between the 2 points
1259 double d = 0.5 * sqrt( (sp.x - ep.x) * (sp.x - ep.x) + (sp.y - ep.y) * (sp.y - ep.y) );
1260 // midpoint of the subtended segment
1261 double xm = ( sp.x + ep.x ) * 0.5;
1262 double ym = ( sp.y + ep.y ) * 0.5;
1263 double radius = d / sin( ang * 0.5 );
1264
1265 if( radius < 0.0 )
1266 radius = -radius;
1267
1268 // calculate the height of the triangle with base d and hypotenuse r
1269 double dh2 = radius * radius - d * d;
1270
1271 // this should only ever happen due to rounding errors when r == d
1272 if( dh2 < 0.0 )
1273 dh2 = 0.0;
1274
1275 double h = sqrt( dh2 );
1276
1277 if( ang < 0.0 )
1278 offAng -= M_PI_2;
1279 else
1280 offAng += M_PI_2;
1281
1282 // for angles greater than 180 deg we need to flip the
1283 // direction in which the arc center is found relative
1284 // to the midpoint of the subtended segment.
1285 if( ang < -M_PI )
1286 offAng += M_PI;
1287 else if( ang > M_PI )
1288 offAng -= M_PI;
1289
1290 // center point
1291 double cx = h * cos( offAng ) + xm;
1292 double cy = h * sin( offAng ) + ym;
1293 VECTOR2D center( SCALE_FACTOR( cx ), SCALE_FACTOR( -cy ) );
1294 VECTOR2D arc_start;
1295 EDA_ANGLE angle( ang, RADIANS_T );
1296
1297 if( ang < 0.0 )
1298 {
1299 arc_start = VECTOR2D( SCALE_FACTOR( ep.x ), SCALE_FACTOR( -ep.y ) );
1300 }
1301 else
1302 {
1303 arc_start = VECTOR2D( SCALE_FACTOR( sp.x ), SCALE_FACTOR( -sp.y ) );
1304 angle = -angle;
1305 }
1306
1309 bufferToUse->AddArc( center, arc_start, angle, aWidth );
1310
1311 VECTOR2D radiusDelta( SCALE_FACTOR( radius ), SCALE_FACTOR( radius ) );
1312
1313 updateImageLimits( center + radiusDelta );
1314 updateImageLimits( center - radiusDelta );
1315 return;
1316}
1317
1318
1319#include "tinysplinecpp.h"
1320
1322{
1323 #if 0 // Debug only
1324 wxLogMessage("spl deg %d kn %d ctr %d fit %d",
1329 #endif
1330
1331 unsigned imax = m_curr_entity.m_SplineControlPointList.size();
1332
1333 if( imax < 2 ) // malformed spline
1334 return;
1335
1336#if 0 // set to 1 to approximate the spline by segments between 2 control points
1339
1340 for( unsigned int ii = 1; ii < imax; ++ii )
1341 {
1344
1345 if( startpoint != endpoint )
1346 {
1347 m_internalImporter.AddLine( startpoint, endpoint, aWidth );
1348
1349 updateImageLimits( startpoint );
1350 updateImageLimits( endpoint );
1351
1352 startpoint = endpoint;
1353 }
1354 }
1355#else // Use bezier curves, supported by pcbnew, to approximate the spline
1356 std::vector<double> ctrlp;
1357
1358 for( unsigned ii = 0; ii < imax; ++ii )
1359 {
1360 ctrlp.push_back( m_curr_entity.m_SplineControlPointList[ii].m_x );
1361 ctrlp.push_back( m_curr_entity.m_SplineControlPointList[ii].m_y );
1362 }
1363
1364 std::vector<double> coords;
1365 try
1366 {
1367 tinyspline::BSpline dxfspline( m_curr_entity.m_SplineControlPointList.size(),
1368 /* coord dim */ 2, m_curr_entity.m_SplineDegree );
1369
1370 dxfspline.setCtrlp( ctrlp );
1371 dxfspline.setKnots( m_curr_entity.m_SplineKnotsList );
1372 tinyspline::BSpline beziers( dxfspline.toBeziers() );
1373
1374 coords = beziers.ctrlp();
1375 }
1376 catch( const std::runtime_error& ) //tinyspline throws everything including data validation as runtime errors
1377 {
1378 // invalid spline definition, drop this block
1379 reportMsg( _( "Invalid spline definition encountered" ) );
1380 return;
1381 }
1382
1383 if( coords.size() % 8 != 0 )
1384 {
1385 // somehow we generated a bad Bezier curve
1386 reportMsg( _( "Invalid Bezier curve created" ) );
1387 return;
1388 }
1389
1390 // Each Bezier curve uses 4 vertices (a start point, 2 control points and a end point).
1391 // So we can have more than one Bezier curve ( there are one curve each four vertices)
1392 // However, one can have one Bezier curve with end point = ctrl point 2, having only 3
1393 // defined points in list.
1394 for( unsigned ii = 0; ii < coords.size(); ii += 8 )
1395 {
1396 VECTOR2D start( mapX( coords[ii] ), mapY( coords[ii+1] ) );
1397 VECTOR2D bezierControl1( mapX( coords[ii+2] ), mapY( coords[ii+3] ) );
1398 VECTOR2D bezierControl2( mapX( coords[ii+4] ), mapY( coords[ii+5] ) );
1399 VECTOR2D end;
1400
1401 if( ii+7 < coords.size() )
1402 end = VECTOR2D( mapX( coords[ii+6] ), mapY( coords[ii+7] ) );
1403 else
1404 end = bezierControl2;
1405
1406 GRAPHICS_IMPORTER_BUFFER* bufferToUse =
1408 bufferToUse->AddSpline( start, bezierControl1, bezierControl2, end, aWidth );
1409 }
1410#endif
1411}
1412
1413
1415{
1416 m_minX = std::min( aPoint.x, m_minX );
1417 m_maxX = std::max( aPoint.x, m_maxX );
1418
1419 m_minY = std::min( aPoint.y, m_minY );
1420 m_maxY = std::max( aPoint.y, m_maxY );
1421}
1422
1423
1425{
1426 VECTOR3D arbZ, arbX, arbY;
1427
1428 double direction[3];
1429 aData->getDirection( direction );
1430
1431 arbZ = VECTOR3D( direction[0], direction[1], direction[2] ).Normalize();
1432
1433 if( ( abs( arbZ.x ) < ( 1.0 / 64.0 ) ) && ( abs( arbZ.y ) < ( 1.0 / 64.0 ) ) )
1434 {
1435 arbX = VECTOR3D( 0, 1, 0 ).Cross( arbZ ).Normalize();
1436 }
1437 else
1438 {
1439 arbX = VECTOR3D( 0, 0, 1 ).Cross( arbZ ).Normalize();
1440 }
1441
1442 arbY = arbZ.Cross( arbX ).Normalize();
1443
1444 return DXF_ARBITRARY_AXIS{ arbX, arbY, arbZ };
1445}
1446
1447
1449{
1450 double x, y, z;
1451 x = point.x * arbitraryAxis.vecX.x + point.y * arbitraryAxis.vecX.y
1452 + point.z * arbitraryAxis.vecX.z;
1453 y = point.x * arbitraryAxis.vecY.x + point.y * arbitraryAxis.vecY.y
1454 + point.z * arbitraryAxis.vecY.z;
1455 z = point.x * arbitraryAxis.vecZ.x + point.y * arbitraryAxis.vecZ.y
1456 + point.z * arbitraryAxis.vecZ.z;
1457
1458 return VECTOR3D( x, y, z );
1459}
1460
1461
1463{
1464 VECTOR3D worldX = wcsToOcs( arbitraryAxis, VECTOR3D( 1, 0, 0 ) );
1465 VECTOR3D worldY = wcsToOcs( arbitraryAxis, VECTOR3D( 0, 1, 0 ) );
1466 VECTOR3D worldZ = wcsToOcs( arbitraryAxis, VECTOR3D( 0, 0, 1 ) );
1467
1468 double x, y, z;
1469 x = point.x * worldX.x + point.y * worldX.y + point.z * worldX.z;
1470 y = point.x * worldY.x + point.y * worldY.y + point.z * worldY.z;
1471 z = point.x * worldZ.x + point.y * worldZ.y + point.z * worldZ.z;
1472
1473 return VECTOR3D( x, y, z );
1474}
const char * name
Definition: DXF_plotter.cpp:56
unsigned int m_SplineDegree
std::vector< VECTOR2D > m_SplineFitPointList
unsigned int m_SplineFitCount
std::vector< SPLINE_CTRL_POINT > m_SplineControlPointList
unsigned int m_SplineKnotsCount
unsigned int m_SplineControlCount
std::vector< double > m_SplineKnotsList
A helper class to hold layer settings temporarily during import.
GRAPHICS_IMPORTER_BUFFER m_buffer
A helper class to hold layer settings temporarily during import.
DXF_IMPORT_UNITS m_currentUnit
virtual void addPolyline(const DL_PolylineData &aData) override
double mapY(double aDxfCoordY)
std::vector< std::unique_ptr< DXF_IMPORT_LAYER > > m_layers
static wxString toNativeString(const wxString &aData)
Convert a DXF encoded string into a native Unicode string.
virtual void setVariableInt(const std::string &key, int value, int code) override
Called for every int variable in the DXF file (e.g.
void insertSpline(double aWidth)
virtual void addLine(const DL_LineData &aData) override
void insertLine(const VECTOR2D &aSegStart, const VECTOR2D &aSegEnd, double aWidth)
DXF_IMPORT_BLOCK * getImportBlock(const std::string &aBlockName)
Return the import layer block.
virtual void addBlock(const DL_BlockData &) override
Called for each BLOCK in the DXF file.
virtual void addLayer(const DL_LayerData &aData) override
virtual void addCircle(const DL_CircleData &aData) override
virtual void addMText(const DL_MTextData &aData) override
DXF_IMPORT_LAYER * getImportLayer(const std::string &aLayerName)
Return the import layer data.
static wxString toDxfString(const wxString &aStr)
Convert a native Unicode string into a DXF encoded string.
DXF_IMPORT_STYLE * getImportStyle(const std::string &aStyleName)
Return the import style.
virtual void addInsert(const DL_InsertData &aData) override
VECTOR3D ocsToWcs(const DXF_ARBITRARY_AXIS &arbitraryAxis, VECTOR3D point)
Converts a given object coordinate point to world coordinate using the given arbitrary axis vectors.
double GetImageWidth() const override
Return image width from original imported file.
DXF_ARBITRARY_AXIS getArbitraryAxis(DL_Extrusion *aData)
double GetImageHeight() const override
Return image height from original imported file.
VECTOR3D wcsToOcs(const DXF_ARBITRARY_AXIS &arbitraryAxis, VECTOR3D point)
Converts a given world coordinate point to object coordinate using the given arbitrary axis vectors.
void updateImageLimits(const VECTOR2D &aPoint)
virtual void addTextStyle(const DL_StyleData &aData) override
virtual void addVertex(const DL_VertexData &aData) override
Called for every polyline vertex.
virtual void addSpline(const DL_SplineData &aData) override
Called for every spline.
virtual void addText(const DL_TextData &aData) override
virtual void endBlock() override
virtual void setVariableString(const std::string &key, const std::string &value, int code) override
Called for every string variable in the DXF file (e.g.
virtual void addKnot(const DL_KnotData &aData) override
Called for every spline knot value.
bool ImportDxfFile(const wxString &aFile)
Implementation of the method used for communicate with this filter.
virtual void addArc(const DL_ArcData &aData) override
void SetDefaultLineWidthMM(double aWidth)
Set the default line width when importing dxf items like lines to Pcbnew.
virtual void addFitPoint(const DL_FitPointData &aData) override
Called for every spline fit point.
virtual void addPoint(const DL_PointData &aData) override
double mapDim(double aDxfValue)
void reportMsg(const wxString &aMessage)
double mapX(double aDxfCoordX)
double lineWeightToWidth(int lw, DXF_IMPORT_LAYER *aLayer)
void insertArc(const VECTOR2D &aSegStart, const VECTOR2D &aSegEnd, double aBulge, double aWidth)
std::vector< std::unique_ptr< DXF_IMPORT_BLOCK > > m_blocks
bool Import() override
Actually imports the file.
virtual void endEntity() override
virtual void addControlPoint(const DL_ControlPointData &aData) override
Called for every spline control point.
GRAPHICS_IMPORTER_BUFFER m_internalImporter
std::vector< std::unique_ptr< DXF_IMPORT_STYLE > > m_styles
bool Load(const wxString &aFileName) override
Load file for import.
DXF_IMPORT_BLOCK * m_currentBlock
DXF2BRD_ENTITY_DATA m_curr_entity
virtual void SetImporter(GRAPHICS_IMPORTER *aImporter) override
Set the receiver of the imported shapes.
virtual void addLinetype(const DL_LinetypeData &data) override
A helper class to hold style settings temporarily during import.
std::list< std::unique_ptr< IMPORTED_SHAPE > > & GetShapes()
void AddCircle(const VECTOR2D &aCenter, double aRadius, double aWidth, bool aFilled) override
Create an object representing a circle.
void AddSpline(const VECTOR2D &aStart, const VECTOR2D &BezierControl1, const VECTOR2D &BezierControl2, const VECTOR2D &aEnd, double aWidth) override
Create an object representing an arc.
void ImportTo(GRAPHICS_IMPORTER &aImporter)
void AddArc(const VECTOR2D &aCenter, const VECTOR2D &aStart, const EDA_ANGLE &aAngle, double aWidth) override
Create an object representing an arc.
void AddText(const VECTOR2D &aOrigin, const wxString &aText, double aHeight, double aWidth, double aThickness, double aOrientation, GR_TEXT_H_ALIGN_T aHJustify, GR_TEXT_V_ALIGN_T aVJustify) override
Create an object representing a text.
void AddShape(std::unique_ptr< IMPORTED_SHAPE > &aShape)
void AddLine(const VECTOR2D &aStart, const VECTOR2D &aEnd, double aWidth) override
Create an object representing a line segment.
Interface that creates objects representing shapes for a given data model.
double GetLineWidthMM() const
Return the line width used for importing the outlines (in mm).
GRAPHICS_IMPORTER * m_importer
< Importer used to create objects representing the imported shapes.
virtual void SetImporter(GRAPHICS_IMPORTER *aImporter)
Set the receiver of the imported shapes.
T y
Definition: vector3.h:62
T z
Definition: vector3.h:63
VECTOR3< T > Normalize()
Compute the normalized vector.
Definition: vector3.h:153
VECTOR3< T > Cross(const VECTOR3< T > &aVector) const
Compute cross product of self with aVector.
Definition: vector3.h:127
T x
Definition: vector3.h:61
The common library.
#define SCALE_FACTOR(x)
#define MIN_BULGE
#define DXF_IMPORT_LINEWEIGHT_BY_LW_DEFAULT
#define DXF_IMPORT_LINEWEIGHT_BY_LAYER
#define _(s)
@ RADIANS_T
Definition: eda_angle.h:32
@ DEGREES_T
Definition: eda_angle.h:31
static constexpr EDA_ANGLE & ANGLE_360
Definition: eda_angle.h:418
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:412
@ Dwgs_User
Definition: layer_ids.h:109
This file contains miscellaneous commonly used macros and functions.
static wxString FROM_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:110
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:401
const int scale
Helper class representing the DXF specification's "arbitrary axis".
GR_TEXT_H_ALIGN_T
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
GR_TEXT_V_ALIGN_T
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
#define M_PI_2
Definition: transline.cpp:40
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
VECTOR2< double > VECTOR2D
Definition: vector2d.h:617
VECTOR3< double > VECTOR3D
Definition: vector3.h:204