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, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
27
28#include <board.h>
29#include <footprint.h>
30#include <pcb_shape.h>
31#include <pcb_text.h>
32#include <memory>
33#include <tuple>
34
35
44
45
46void GRAPHICS_IMPORTER_PCBNEW::SetLayerMap( const std::map<wxString, PCB_LAYER_ID>& aLayerMap )
47{
48 m_layerMap = aLayerMap;
49 m_useLayerMap = true;
50}
51
52
58
59
60bool GRAPHICS_IMPORTER_PCBNEW::CanImportSourceLayer( const wxString& aSourceLayer ) const
61{
62 if( !m_useLayerMap )
63 return true;
64
65 auto it = m_layerMap.find( aSourceLayer );
66
67 return it != m_layerMap.end() && it->second != PCB_LAYER_ID::UNDEFINED_LAYER
68 && it->second != PCB_LAYER_ID::UNSELECTED_LAYER;
69}
70
71
72void GRAPHICS_IMPORTER_PCBNEW::SetCurrentSourceLayer( const wxString& aSourceLayer )
73{
75
76 if( !m_useLayerMap )
77 return;
78
79 auto it = m_layerMap.find( aSourceLayer );
80
81 if( it != m_layerMap.end() && it->second != PCB_LAYER_ID::UNDEFINED_LAYER
82 && it->second != PCB_LAYER_ID::UNSELECTED_LAYER )
83 {
84 m_layer = it->second;
85 }
86}
87
88
90{
91 VECTOR2D coord = aCoordinate;
92 coord *= GetScale();
93 coord += GetImportOffsetMM();
94 coord *= GetMillimeterToIuFactor();
95
96 return KiROUND( coord.x, coord.y );
97}
98
99
101{
102 VECTOR2D factor = ImportScalingFactor();
103 double scale = ( factor.x + factor.y ) * 0.5;
104
105 if( aLineWidth <= 0.0 )
106 return int( GetLineWidthMM() * scale );
107
108 // aLineWidth is in mm:
109 return int( aLineWidth * scale );
110}
111
112
114{
115 // Historicaly -1 meant no-stroke in Eeschema, but this has never been the case for
116 // PCBNew. (The importer, which doesn't know which program it's creating content for,
117 // also uses -1 for no-stroke.)
118 int width = ( aStroke.GetWidth() == -1 ) ? 0 : MapLineWidth( aStroke.GetWidth() );
119
120 return STROKE_PARAMS( width, aStroke.GetPlotStyle(), aStroke.GetColor() );
121}
122
123
124void GRAPHICS_IMPORTER_PCBNEW::AddLine( const VECTOR2D& aStart, const VECTOR2D& aEnd,
125 const IMPORTED_STROKE& aStroke )
126{
127 std::unique_ptr<PCB_SHAPE> line = std::make_unique<PCB_SHAPE>( m_parent );
128 line->SetShape( SHAPE_T::SEGMENT );
129 line->SetLayer( GetLayer() );
130 line->SetStroke( MapStrokeParams( aStroke ) );
131 line->SetStart( MapCoordinate( aStart ) );
132 line->SetEnd( MapCoordinate( aEnd ) );
133
134 // Skip 0 len lines:
135 if( line->GetStart() == line->GetEnd() )
136 return;
137
138 addItem( std::move( line ) );
139}
140
141
142void GRAPHICS_IMPORTER_PCBNEW::AddCircle( const VECTOR2D& aCenter, double aRadius,
143 const IMPORTED_STROKE& aStroke, bool aFilled,
144 const COLOR4D& aFillColor )
145{
146 std::unique_ptr<PCB_SHAPE> circle = std::make_unique<PCB_SHAPE>( m_parent );
147 circle->SetShape( SHAPE_T::CIRCLE );
148 circle->SetFilled( aFilled );
149 circle->SetLayer( GetLayer() );
150 circle->SetStroke( MapStrokeParams( aStroke ) );
151 circle->SetStart( MapCoordinate( aCenter ) );
152 circle->SetEnd( MapCoordinate( VECTOR2D( aCenter.x + aRadius, aCenter.y ) ) );
153
154 addItem( std::move( circle ) );
155}
156
157
158void GRAPHICS_IMPORTER_PCBNEW::AddArc( const VECTOR2D& aCenter, const VECTOR2D& aStart,
159 const EDA_ANGLE& aAngle, const IMPORTED_STROKE& aStroke )
160{
165 VECTOR2D end = aStart;
166 VECTOR2D mid = aStart;
167
168 RotatePoint( end, aCenter, -aAngle );
169 RotatePoint( mid, aCenter, -aAngle / 2.0 );
170
171 // Ensure the arc can be handled by Pcbnew. Arcs with a too big radius cannot.
172 // The criteria used here is radius < MAX_INT / 2.
173 // this is not perfect, but we do not know the exact final position of the arc, so
174 // we cannot test the coordinate values, because the arc can be moved before being placed.
175 VECTOR2D center = MapCoordinate( aCenter );
176 double radius = ( center - MapCoordinate( aStart ) ).EuclideanNorm();
177 double rd_max_value = std::numeric_limits<VECTOR2I::coord_type>::max() / 2.0;
178
179 if( radius >= rd_max_value )
180 {
181 // Arc cannot be handled: convert it to a segment
182 AddLine( aStart, end, aStroke );
183 return;
184 }
185
186 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( m_parent );
187 arc->SetShape( SHAPE_T::ARC );
188 arc->SetLayer( GetLayer() );
189
190 arc->SetArcGeometry( MapCoordinate( aStart ), MapCoordinate( mid ), MapCoordinate( end ) );
191 arc->SetStroke( MapStrokeParams( aStroke ) );
192
193 addItem( std::move( arc ) );
194}
195
196
197void GRAPHICS_IMPORTER_PCBNEW::AddPolygon( const std::vector<VECTOR2D>& aVertices,
198 const IMPORTED_STROKE& aStroke, bool aFilled,
199 const COLOR4D& aFillColor )
200{
201 std::vector<VECTOR2I> convertedPoints;
202 convertedPoints.reserve( aVertices.size() );
203
204 for( const VECTOR2D& precisePoint : aVertices )
205 convertedPoints.emplace_back( MapCoordinate( precisePoint ) );
206
207 std::unique_ptr<PCB_SHAPE> polygon = std::make_unique<PCB_SHAPE>( m_parent );
208 polygon->SetShape( SHAPE_T::POLY );
209 polygon->SetFilled( aFilled );
210 polygon->SetLayer( GetLayer() );
211 polygon->SetPolyPoints( convertedPoints );
212
213 if( FOOTPRINT* parentFP = polygon->GetParentFootprint() )
214 {
215 polygon->Rotate( { 0, 0 }, parentFP->GetOrientation() );
216 polygon->Move( parentFP->GetPosition() );
217 }
218
219 polygon->SetStroke( MapStrokeParams( aStroke ) );
220
221 if( polygon->IsPolyShapeValid() )
222 addItem( std::move( polygon ) );
223}
224
225
226void GRAPHICS_IMPORTER_PCBNEW::AddText( const VECTOR2D& aOrigin, const wxString& aText,
227 double aHeight, double aWidth, double aThickness,
228 double aOrientation, GR_TEXT_H_ALIGN_T aHJustify,
229 GR_TEXT_V_ALIGN_T aVJustify, const COLOR4D& aColor )
230{
231 std::unique_ptr<PCB_TEXT> textItem = std::make_unique<PCB_TEXT>( m_parent );
232 textItem->SetLayer( GetLayer() );
233 textItem->SetTextThickness( MapLineWidth( aThickness ) );
234 textItem->SetTextPos( MapCoordinate( aOrigin ) );
235 textItem->SetTextAngle( EDA_ANGLE( aOrientation, DEGREES_T ) );
236 textItem->SetTextWidth( aWidth * ImportScalingFactor().x );
237 textItem->SetTextHeight( aHeight * ImportScalingFactor().y );
238 textItem->SetVertJustify( aVJustify );
239 textItem->SetHorizJustify( aHJustify );
240 textItem->SetText( aText );
241
242 addItem( std::move( textItem ) );
243}
244
245
246void GRAPHICS_IMPORTER_PCBNEW::AddSpline( const VECTOR2D& aStart, const VECTOR2D& aBezierControl1,
247 const VECTOR2D& aBezierControl2, const VECTOR2D& aEnd,
248 const IMPORTED_STROKE& aStroke )
249{
250 std::unique_ptr<PCB_SHAPE> spline = std::make_unique<PCB_SHAPE>( m_parent );
251
252 spline->SetLayer( GetLayer() );
253 spline->SetStroke( MapStrokeParams( aStroke ) );
254 spline->SetStart( MapCoordinate( aStart ) );
255 spline->SetBezierC1( MapCoordinate( aBezierControl1 ));
256 spline->SetBezierC2( MapCoordinate( aBezierControl2 ));
257 spline->SetEnd( MapCoordinate( aEnd ) );
258
259 if( setupSplineOrLine( *spline, ARC_HIGH_DEF ) )
260 {
261 addItem( std::move( spline ) );
262 }
263}
264
265
266void GRAPHICS_IMPORTER_PCBNEW::AddEllipse( const VECTOR2D& aCenter, double aMajorRadius, double aMinorRadius,
267 const EDA_ANGLE& aRotation, const IMPORTED_STROKE& aStroke, bool aFilled,
268 const COLOR4D& aFillColor )
269{
270 std::unique_ptr<PCB_SHAPE> ellipse = std::make_unique<PCB_SHAPE>( m_parent );
271 ellipse->SetShape( SHAPE_T::ELLIPSE );
272 ellipse->SetLayer( GetLayer() );
273 ellipse->SetStroke( MapStrokeParams( aStroke ) );
274 ellipse->SetFilled( aFilled );
275
276 VECTOR2I center = MapCoordinate( aCenter );
277 ellipse->SetEllipseCenter( center );
278 ellipse->SetEllipseMajorRadius( KiROUND( aMajorRadius * ImportScalingFactor().x ) );
279 ellipse->SetEllipseMinorRadius( KiROUND( aMinorRadius * ImportScalingFactor().y ) );
280 ellipse->SetEllipseRotation( aRotation );
281
282 addItem( std::move( ellipse ) );
283}
284
285
286void GRAPHICS_IMPORTER_PCBNEW::AddEllipseArc( const VECTOR2D& aCenter, double aMajorRadius, double aMinorRadius,
287 const EDA_ANGLE& aRotation, const EDA_ANGLE& aStartAngle,
288 const EDA_ANGLE& aEndAngle, const IMPORTED_STROKE& aStroke )
289{
290 std::unique_ptr<PCB_SHAPE> arc = std::make_unique<PCB_SHAPE>( m_parent );
291 arc->SetShape( SHAPE_T::ELLIPSE_ARC );
292 arc->SetLayer( GetLayer() );
293 arc->SetStroke( MapStrokeParams( aStroke ) );
294
295 VECTOR2I center = MapCoordinate( aCenter );
296 arc->SetEllipseCenter( center );
297 arc->SetEllipseMajorRadius( KiROUND( aMajorRadius * ImportScalingFactor().x ) );
298 arc->SetEllipseMinorRadius( KiROUND( aMinorRadius * ImportScalingFactor().y ) );
299 arc->SetEllipseRotation( aRotation );
300 arc->SetEllipseStartAngle( aStartAngle );
301 arc->SetEllipseEndAngle( aEndAngle );
302
303 addItem( std::move( arc ) );
304}
constexpr int ARC_HIGH_DEF
Definition base_units.h:141
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:125
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
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:105
Simple container to manage line stroke parameters.
@ DEGREES_T
Definition eda_angle.h:31
@ ELLIPSE
Definition eda_shape.h:56
@ SEGMENT
Definition eda_shape.h:50
@ ELLIPSE_ARC
Definition eda_shape.h:57
@ Dwgs_User
Definition layer_ids.h:107
@ UNSELECTED_LAYER
Definition layer_ids.h:62
@ UNDEFINED_LAYER
Definition layer_ids.h:61
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:229
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687
VECTOR2< double > VECTOR2D
Definition vector2d.h:686