KiCad PCB EDA Suite
Loading...
Searching...
No Matches
graphics_importer_pcbnew.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) 2016 CERN
5 * @author Maciej Suminski <[email protected]>
6 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
23
24#include <board.h>
25#include <footprint.h>
26#include <pcb_shape.h>
27#include <pcb_text.h>
28#include <memory>
29#include <tuple>
30
31
40
41
42void GRAPHICS_IMPORTER_PCBNEW::SetLayerMap( const std::map<wxString, PCB_LAYER_ID>& aLayerMap )
43{
44 m_layerMap = aLayerMap;
45 m_useLayerMap = true;
46}
47
48
54
55
56bool GRAPHICS_IMPORTER_PCBNEW::CanImportSourceLayer( const wxString& aSourceLayer ) const
57{
58 if( !m_useLayerMap )
59 return true;
60
61 auto it = m_layerMap.find( aSourceLayer );
62
63 return it != m_layerMap.end() && it->second != PCB_LAYER_ID::UNDEFINED_LAYER
64 && it->second != PCB_LAYER_ID::UNSELECTED_LAYER;
65}
66
67
68void GRAPHICS_IMPORTER_PCBNEW::SetCurrentSourceLayer( const wxString& aSourceLayer )
69{
71
72 if( !m_useLayerMap )
73 return;
74
75 auto it = m_layerMap.find( aSourceLayer );
76
77 if( it != m_layerMap.end() && it->second != PCB_LAYER_ID::UNDEFINED_LAYER
78 && it->second != PCB_LAYER_ID::UNSELECTED_LAYER )
79 {
80 m_layer = it->second;
81 }
82}
83
84
86{
87 VECTOR2D coord = aCoordinate;
88 coord *= GetScale();
89 coord += GetImportOffsetMM();
90 coord *= GetMillimeterToIuFactor();
91
92 return KiROUND( coord.x, coord.y );
93}
94
95
97{
99 double scale = ( factor.x + factor.y ) * 0.5;
100
101 if( aLineWidth <= 0.0 )
102 return int( GetLineWidthMM() * scale );
103
104 // aLineWidth is in mm:
105 return int( aLineWidth * scale );
106}
107
108
110{
111 // Historicaly -1 meant no-stroke in Eeschema, but this has never been the case for
112 // PCBNew. (The importer, which doesn't know which program it's creating content for,
113 // also uses -1 for no-stroke.)
114 int width = ( aStroke.GetWidth() == -1 ) ? 0 : MapLineWidth( aStroke.GetWidth() );
115
116 return STROKE_PARAMS( width, aStroke.GetPlotStyle(), aStroke.GetColor() );
117}
118
119
120void GRAPHICS_IMPORTER_PCBNEW::AddLine( const VECTOR2D& aStart, const VECTOR2D& aEnd,
121 const IMPORTED_STROKE& aStroke )
122{
123 std::unique_ptr<PCB_SHAPE> line = std::make_unique<PCB_SHAPE>( m_parent );
124 line->SetShape( SHAPE_T::SEGMENT );
125 line->SetLayer( GetLayer() );
126 line->SetStroke( MapStrokeParams( aStroke ) );
127 line->SetStart( MapCoordinate( aStart ) );
128 line->SetEnd( MapCoordinate( aEnd ) );
129
130 // Skip 0 len lines:
131 if( line->GetStart() == line->GetEnd() )
132 return;
133
134 addItem( std::move( line ) );
135}
136
137
138void GRAPHICS_IMPORTER_PCBNEW::AddCircle( const VECTOR2D& aCenter, double aRadius,
139 const IMPORTED_STROKE& aStroke, bool aFilled,
140 const COLOR4D& aFillColor )
141{
142 std::unique_ptr<PCB_SHAPE> circle = std::make_unique<PCB_SHAPE>( m_parent );
143 circle->SetShape( SHAPE_T::CIRCLE );
144 circle->SetFilled( aFilled );
145 circle->SetLayer( GetLayer() );
146 circle->SetStroke( MapStrokeParams( aStroke ) );
147 circle->SetStart( MapCoordinate( aCenter ) );
148 circle->SetEnd( MapCoordinate( VECTOR2D( aCenter.x + aRadius, aCenter.y ) ) );
149
150 addItem( std::move( circle ) );
151}
152
153
154void GRAPHICS_IMPORTER_PCBNEW::AddArc( const VECTOR2D& aCenter, const VECTOR2D& aStart,
155 const EDA_ANGLE& aAngle, const IMPORTED_STROKE& aStroke )
156{
161 VECTOR2D end = aStart;
162 VECTOR2D mid = aStart;
163
164 RotatePoint( end, aCenter, -aAngle );
165 RotatePoint( mid, aCenter, -aAngle / 2.0 );
166
167 // Ensure the arc can be handled by Pcbnew. Arcs with a too big radius cannot.
168 // The criteria used here is radius < MAX_INT / 2.
169 // this is not perfect, but we do not know the exact final position of the arc, so
170 // we cannot test the coordinate values, because the arc can be moved before being placed.
171 VECTOR2D center = MapCoordinate( aCenter );
172 double radius = ( center - MapCoordinate( aStart ) ).EuclideanNorm();
173 double rd_max_value = std::numeric_limits<VECTOR2I::coord_type>::max() / 2.0;
174
175 if( radius >= rd_max_value )
176 {
177 // Arc cannot be handled: convert it to a segment
178 AddLine( aStart, end, aStroke );
179 return;
180 }
181
182 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( m_parent );
183 arc->SetShape( SHAPE_T::ARC );
184 arc->SetLayer( GetLayer() );
185
186 arc->SetArcGeometry( MapCoordinate( aStart ), MapCoordinate( mid ), MapCoordinate( end ) );
187 arc->SetStroke( MapStrokeParams( aStroke ) );
188
189 addItem( std::move( arc ) );
190}
191
192
193void GRAPHICS_IMPORTER_PCBNEW::AddPolygon( const std::vector<VECTOR2D>& aVertices,
194 const IMPORTED_STROKE& aStroke, bool aFilled,
195 const COLOR4D& aFillColor )
196{
197 std::vector<VECTOR2I> convertedPoints;
198 convertedPoints.reserve( aVertices.size() );
199
200 for( const VECTOR2D& precisePoint : aVertices )
201 convertedPoints.emplace_back( MapCoordinate( precisePoint ) );
202
203 std::unique_ptr<PCB_SHAPE> polygon = std::make_unique<PCB_SHAPE>( m_parent );
204 polygon->SetShape( SHAPE_T::POLY );
205 polygon->SetFilled( aFilled );
206 polygon->SetLayer( GetLayer() );
207 polygon->SetPolyPoints( convertedPoints );
208
209 if( FOOTPRINT* parentFP = polygon->GetParentFootprint() )
210 {
211 polygon->Rotate( { 0, 0 }, parentFP->GetOrientation() );
212 polygon->Move( parentFP->GetPosition() );
213 }
214
215 polygon->SetStroke( MapStrokeParams( aStroke ) );
216
217 if( polygon->IsPolyShapeValid() )
218 addItem( std::move( polygon ) );
219}
220
221
222void GRAPHICS_IMPORTER_PCBNEW::AddText( const VECTOR2D& aOrigin, const wxString& aText,
223 double aHeight, double aWidth, double aThickness,
224 double aOrientation, GR_TEXT_H_ALIGN_T aHJustify,
225 GR_TEXT_V_ALIGN_T aVJustify, const COLOR4D& aColor )
226{
227 std::unique_ptr<PCB_TEXT> textItem = std::make_unique<PCB_TEXT>( m_parent );
228 textItem->SetLayer( GetLayer() );
229 textItem->SetTextThickness( MapLineWidth( aThickness ) );
230 textItem->SetTextPos( MapCoordinate( aOrigin ) );
231 textItem->SetTextAngle( EDA_ANGLE( aOrientation, DEGREES_T ) );
232 textItem->SetTextWidth( aWidth * ImportScalingFactor().x );
233 textItem->SetTextHeight( aHeight * ImportScalingFactor().y );
234 textItem->SetVertJustify( aVJustify );
235 textItem->SetHorizJustify( aHJustify );
236 textItem->SetText( aText );
237
238 addItem( std::move( textItem ) );
239}
240
241
242void GRAPHICS_IMPORTER_PCBNEW::AddSpline( const VECTOR2D& aStart, const VECTOR2D& aBezierControl1,
243 const VECTOR2D& aBezierControl2, const VECTOR2D& aEnd,
244 const IMPORTED_STROKE& aStroke )
245{
246 std::unique_ptr<PCB_SHAPE> spline = std::make_unique<PCB_SHAPE>( m_parent );
247
248 spline->SetLayer( GetLayer() );
249 spline->SetStroke( MapStrokeParams( aStroke ) );
250 spline->SetStart( MapCoordinate( aStart ) );
251 spline->SetBezierC1( MapCoordinate( aBezierControl1 ));
252 spline->SetBezierC2( MapCoordinate( aBezierControl2 ));
253 spline->SetEnd( MapCoordinate( aEnd ) );
254
255 if( setupSplineOrLine( *spline, ARC_HIGH_DEF ) )
256 {
257 addItem( std::move( spline ) );
258 }
259}
260
261
262void GRAPHICS_IMPORTER_PCBNEW::AddEllipse( const VECTOR2D& aCenter, double aMajorRadius, double aMinorRadius,
263 const EDA_ANGLE& aRotation, const IMPORTED_STROKE& aStroke, bool aFilled,
264 const COLOR4D& aFillColor )
265{
266 std::unique_ptr<PCB_SHAPE> ellipse = std::make_unique<PCB_SHAPE>( m_parent );
267 ellipse->SetShape( SHAPE_T::ELLIPSE );
268 ellipse->SetLayer( GetLayer() );
269 ellipse->SetStroke( MapStrokeParams( aStroke ) );
270 ellipse->SetFilled( aFilled );
271
272 VECTOR2I center = MapCoordinate( aCenter );
273 ellipse->SetEllipseCenter( center );
274 ellipse->SetEllipseMajorRadius( KiROUND( aMajorRadius * ImportScalingFactor().x ) );
275 ellipse->SetEllipseMinorRadius( KiROUND( aMinorRadius * ImportScalingFactor().y ) );
276 ellipse->SetEllipseRotation( aRotation );
277
278 addItem( std::move( ellipse ) );
279}
280
281
282void GRAPHICS_IMPORTER_PCBNEW::AddEllipseArc( const VECTOR2D& aCenter, double aMajorRadius, double aMinorRadius,
283 const EDA_ANGLE& aRotation, const EDA_ANGLE& aStartAngle,
284 const EDA_ANGLE& aEndAngle, const IMPORTED_STROKE& aStroke )
285{
286 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( m_parent );
287 arc->SetShape( SHAPE_T::ELLIPSE_ARC );
288 arc->SetLayer( GetLayer() );
289 arc->SetStroke( MapStrokeParams( aStroke ) );
290
291 VECTOR2I center = MapCoordinate( aCenter );
292 arc->SetEllipseCenter( center );
293 arc->SetEllipseMajorRadius( KiROUND( aMajorRadius * ImportScalingFactor().x ) );
294 arc->SetEllipseMinorRadius( KiROUND( aMinorRadius * ImportScalingFactor().y ) );
295 arc->SetEllipseRotation( aRotation );
296 arc->SetEllipseStartAngle( aStartAngle );
297 arc->SetEllipseEndAngle( aEndAngle );
298
299 addItem( std::move( arc ) );
300}
constexpr int ARC_HIGH_DEF
Definition base_units.h:137
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:986
Abstract interface for BOARD_ITEMs capable of storing other items inside.
GRAPHICS_IMPORTER_PCBNEW(BOARD_ITEM_CONTAINER *aParent)
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, const COLOR4D &aColor=COLOR4D::UNSPECIFIED) override
Create an object representing a text.
bool CanImportSourceLayer(const wxString &aSourceLayer) const override
Return true if shapes from a given source layer should be imported.
std::map< wxString, PCB_LAYER_ID > m_layerMap
void AddArc(const VECTOR2D &aCenter, const VECTOR2D &aStart, const EDA_ANGLE &aAngle, const IMPORTED_STROKE &aStroke) override
Create an object representing an arc.
void SetLayerMap(const std::map< wxString, PCB_LAYER_ID > &aLayerMap)
void AddCircle(const VECTOR2D &aCenter, double aRadius, const IMPORTED_STROKE &aStroke, bool aFilled, const COLOR4D &aFillColor=COLOR4D::UNSPECIFIED) override
Create an object representing a circle.
void AddLine(const VECTOR2D &aStart, const VECTOR2D &aEnd, const IMPORTED_STROKE &aStroke) override
Create an object representing a line segment.
void AddEllipse(const VECTOR2D &aCenter, double aMajorRadius, double aMinorRadius, const EDA_ANGLE &aRotation, const IMPORTED_STROKE &aStroke, bool aFilled, const COLOR4D &aFillColor=COLOR4D::UNSPECIFIED) override
Create an object representing a closed ellipse.
void AddSpline(const VECTOR2D &aStart, const VECTOR2D &aBezierControl1, const VECTOR2D &aBezierControl2, const VECTOR2D &aEnd, const IMPORTED_STROKE &aStroke) override
Create an object representing an arc.
void AddEllipseArc(const VECTOR2D &aCenter, double aMajorRadius, double aMinorRadius, const EDA_ANGLE &aRotation, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aEndAngle, const IMPORTED_STROKE &aStroke) override
Create an object representing an elliptical arc.
int MapLineWidth(double aLineWidth)
If aLineWidth < 0, the default line thickness value is returned.
PCB_LAYER_ID m_layer
< Target layer for the imported shapes.
void AddPolygon(const std::vector< VECTOR2D > &aVertices, const IMPORTED_STROKE &aStroke, bool aFilled, const COLOR4D &aFillColor=COLOR4D::UNSPECIFIED) override
Create an object representing a polygon.
STROKE_PARAMS MapStrokeParams(const IMPORTED_STROKE &aStroke)
void SetCurrentSourceLayer(const wxString &aSourceLayer) override
Set the source layer for the next buffered shape to be imported.
VECTOR2I MapCoordinate(const VECTOR2D &aCoordinate)
Convert an imported coordinate to a board coordinate, according to the internal units,...
VECTOR2D GetScale() const
double GetLineWidthMM() const
Return the line width used for importing the outlines (in mm).
void addItem(std::unique_ptr< EDA_ITEM > aItem)
Add an item to the imported shapes list.
double m_millimeterToIu
Factor to convert millimeters to Internal Units.
bool setupSplineOrLine(EDA_SHAPE &aShape, int aAccuracy)
Configure a shape as a spline or a line segment if it's degenerate.
const VECTOR2D & GetImportOffsetMM() const
VECTOR2D ImportScalingFactor() const
A clone of IMPORTED_STROKE, but with floating-point width.
LINE_STYLE GetPlotStyle() const
double GetWidth() const
KIGFX::COLOR4D GetColor() const
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
Simple container to manage line stroke parameters.
@ DEGREES_T
Definition eda_angle.h:31
@ ELLIPSE
Definition eda_shape.h:52
@ SEGMENT
Definition eda_shape.h:46
@ ELLIPSE_ARC
Definition eda_shape.h:53
@ Dwgs_User
Definition layer_ids.h:103
@ UNSELECTED_LAYER
Definition layer_ids.h:58
@ UNDEFINED_LAYER
Definition layer_ids.h:57
const int scale
VECTOR2I center
int radius
VECTOR2I end
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
GR_TEXT_H_ALIGN_T
This is API surface mapped to common.types.HorizontalAlignment.
GR_TEXT_V_ALIGN_T
This is API surface mapped to common.types.VertialAlignment.
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:225
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682