KiCad PCB EDA Suite
Loading...
Searching...
No Matches
graphics_importer_lib_symbol.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 (C) 2018-2023 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 <lib_symbol.h>
29#include <sch_shape.h>
30#include <sch_text.h>
31#include <memory>
32
33
35 m_symbol( aSymbol ), m_unit( aUnit )
36{
38}
39
40
42{
43 VECTOR2D coord = aCoordinate;
44 coord *= GetScale();
45 coord += GetImportOffsetMM();
46 coord *= GetMillimeterToIuFactor();
47
48 return VECTOR2I( KiROUND( coord.x ), KiROUND( coord.y ) );
49}
50
51
53{
55 double scale = ( std::abs( factor.x ) + std::abs( factor.y ) ) * 0.5;
56
57 if( aLineWidth <= 0.0 )
58 return int( GetLineWidthMM() * scale );
59
60 // aLineWidth is in mm:
61 return int( aLineWidth * scale );
62}
63
64
66{
67 double width = aStroke.GetWidth();
68
69 return STROKE_PARAMS( width != -1 ? MapLineWidth( width ) : -1, aStroke.GetPlotStyle(),
70 aStroke.GetColor() );
71}
72
73
75 const IMPORTED_STROKE& aStroke )
76{
77 VECTOR2I pt0 = MapCoordinate( aStart );
78 VECTOR2I pt1 = MapCoordinate( aEnd );
79
80 // Skip 0 len lines:
81 if( pt0 == pt1 )
82 return;
83
84 std::unique_ptr<SCH_SHAPE> line = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY, LAYER_DEVICE );
85 line->SetParent( m_symbol );
86 line->SetUnit( m_unit );
87 line->SetStroke( MapStrokeParams( aStroke ) );
88
89 line->AddPoint( pt0 );
90 line->AddPoint( pt1 );
91
92 addItem( std::move( line ) );
93}
94
95
96void GRAPHICS_IMPORTER_LIB_SYMBOL::AddCircle( const VECTOR2D& aCenter, double aRadius,
97 const IMPORTED_STROKE& aStroke, bool aFilled,
98 const COLOR4D& aFillColor )
99{
100 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE, LAYER_DEVICE );
101 circle->SetParent( m_symbol );
102 circle->SetUnit( m_unit );
103 circle->SetFillColor( aFillColor );
104 circle->SetFilled( aFilled );
105 circle->SetStroke( MapStrokeParams( aStroke ) );
106 circle->SetStart( MapCoordinate( aCenter ) );
107 circle->SetEnd( MapCoordinate( VECTOR2D( aCenter.x + aRadius, aCenter.y ) ) );
108
109 addItem( std::move( circle ) );
110}
111
112
113void GRAPHICS_IMPORTER_LIB_SYMBOL::AddArc( const VECTOR2D& aCenter, const VECTOR2D& aStart,
114 const EDA_ANGLE& aAngle, const IMPORTED_STROKE& aStroke )
115{
116 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC, LAYER_DEVICE );
117 arc->SetParent( m_symbol );
118 arc->SetUnit( m_unit );
119
124 VECTOR2D end = aStart;
125 VECTOR2D mid = aStart;
126
127 RotatePoint( end, aCenter, -aAngle );
128 RotatePoint( mid, aCenter, -aAngle / 2.0 );
129
130 arc->SetArcGeometry( MapCoordinate( aStart ), MapCoordinate( mid ), MapCoordinate( end ) );
131
132 // Ensure the arc can be handled by KiCad. Arcs with a too big radius cannot.
133 // The criteria used here is radius < MAX_INT / 2.
134 // this is not perfect, but we do not know the exact final position of the arc, so
135 // we cannot test the coordinate values, because the arc can be moved before being placed.
136 VECTOR2D center = CalcArcCenter( arc->GetStart(), arc->GetEnd(), aAngle );
137 double radius = ( center - arc->GetStart() ).EuclideanNorm();
138 constexpr double rd_max_value = std::numeric_limits<VECTOR2I::coord_type>::max() / 2.0;
139
140 if( radius >= rd_max_value )
141 {
142 // Arc cannot be handled: convert it to a segment
143 AddLine( aStart, end, aStroke );
144 return;
145 }
146
147 arc->SetStroke( MapStrokeParams( aStroke ) );
148
149 addItem( std::move( arc ) );
150}
151
152
153void GRAPHICS_IMPORTER_LIB_SYMBOL::AddPolygon( const std::vector<VECTOR2D>& aVertices,
154 const IMPORTED_STROKE& aStroke, bool aFilled,
155 const COLOR4D& aFillColor )
156{
157 std::vector<VECTOR2I> convertedPoints;
158 convertedPoints.reserve( aVertices.size() );
159
160 for( const VECTOR2D& precisePoint : aVertices )
161 convertedPoints.emplace_back( MapCoordinate( precisePoint ) );
162
163 if( convertedPoints.empty() )
164 return;
165
166 std::unique_ptr<SCH_SHAPE> polygon = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY, LAYER_DEVICE );
167 polygon->SetParent( m_symbol );
168 polygon->SetUnit( m_unit );
169
170 if( aFilled )
171 {
172 polygon->SetFillMode( aFillColor != COLOR4D::UNSPECIFIED ? FILL_T::FILLED_WITH_COLOR
173 : FILL_T::FILLED_SHAPE );
174 }
175
176 polygon->SetFillColor( aFillColor );
177 polygon->SetPolyPoints( convertedPoints );
178 polygon->AddPoint( convertedPoints[0] ); // Need to close last point for libedit
179
180 polygon->SetStroke( MapStrokeParams( aStroke ) );
181
182 if( polygon->IsPolyShapeValid() )
183 addItem( std::move( polygon ) );
184}
185
186
187void GRAPHICS_IMPORTER_LIB_SYMBOL::AddText( const VECTOR2D& aOrigin, const wxString& aText,
188 double aHeight, double aWidth, double aThickness,
189 double aOrientation, GR_TEXT_H_ALIGN_T aHJustify,
190 GR_TEXT_V_ALIGN_T aVJustify, const COLOR4D& aColor )
191{
192 auto textItem = std::make_unique<SCH_TEXT>( MapCoordinate( aOrigin ), aText, LAYER_DEVICE );
193 textItem->SetParent( m_symbol );
194 textItem->SetUnit( m_unit );
195 textItem->SetTextColor( aColor );
196 textItem->SetTextThickness( MapLineWidth( aThickness ) );
197 textItem->SetTextAngle( EDA_ANGLE( aOrientation, DEGREES_T ) );
198 textItem->SetTextWidth( aWidth * ImportScalingFactor().x );
199 textItem->SetTextHeight( aHeight * ImportScalingFactor().y );
200 textItem->SetVertJustify( aVJustify );
201 textItem->SetHorizJustify( aHJustify );
202
203 addItem( std::move( textItem ) );
204}
205
206
208 const VECTOR2D& aBezierControl1,
209 const VECTOR2D& aBezierControl2, const VECTOR2D& aEnd,
210 const IMPORTED_STROKE& aStroke )
211{
212 std::unique_ptr<SCH_SHAPE> spline = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER, LAYER_DEVICE );
213 spline->SetParent( m_symbol );
214 spline->SetUnit( m_unit );
215 spline->SetStroke( MapStrokeParams( aStroke ) );
216 spline->SetStart( MapCoordinate( aStart ) );
217 spline->SetBezierC1( MapCoordinate( aBezierControl1 ) );
218 spline->SetBezierC2( MapCoordinate( aBezierControl2 ) );
219 spline->SetEnd( MapCoordinate( aEnd ) );
220 spline->RebuildBezierToSegmentsPointsList( aStroke.GetWidth() / 2 );
221
222 // If the spline is degenerated (i.e. a segment) add it as segment or discard it if
223 // null (i.e. very small) length
224 if( spline->GetBezierPoints().size() <= 2 )
225 {
226 spline->SetShape( SHAPE_T::SEGMENT );
227 int dist = VECTOR2I( spline->GetStart() - spline->GetEnd() ).EuclideanNorm();
228
229// segment smaller than MIN_SEG_LEN_ACCEPTABLE_NM nanometers are skipped.
230#define MIN_SEG_LEN_ACCEPTABLE_NM 20
231 if( dist < MIN_SEG_LEN_ACCEPTABLE_NM )
232 return;
233 }
234
235 addItem( std::move( spline ) );
236}
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
VECTOR2I MapCoordinate(const VECTOR2D &aCoordinate)
Convert an imported coordinate to a board coordinate, according to the internal units,...
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.
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.
STROKE_PARAMS MapStrokeParams(const IMPORTED_STROKE &aStroke)
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.
void AddLine(const VECTOR2D &aStart, const VECTOR2D &aEnd, const IMPORTED_STROKE &aStroke) override
Create an object representing a line segment.
void AddArc(const VECTOR2D &aCenter, const VECTOR2D &aStart, const EDA_ANGLE &aAngle, const IMPORTED_STROKE &aStroke) override
Create an object representing an arc.
int MapLineWidth(double aLineWidth)
If aLineWidth < 0, the default line thickness value is returned.
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.
GRAPHICS_IMPORTER_LIB_SYMBOL(LIB_SYMBOL *aSymbol, int aUnit)
VECTOR2D GetScale() const
double GetMillimeterToIuFactor()
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
Offset (in mm) for imported coordinates.
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:104
Define a library symbol object.
Definition: lib_symbol.h:78
Simple container to manage line stroke parameters.
Definition: stroke_params.h:79
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:283
@ DEGREES_T
Definition: eda_angle.h:31
#define MIN_SEG_LEN_ACCEPTABLE_NM
@ LAYER_DEVICE
Definition: layer_ids.h:370
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:390
const int scale
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
GR_TEXT_H_ALIGN_T
GR_TEXT_V_ALIGN_T
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
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
Definition: trigo.cpp:521
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691
VECTOR2< double > VECTOR2D
Definition: vector2d.h:690