KiCad PCB EDA Suite
Loading...
Searching...
No Matches
easyeda_parser_base.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) 2023 Alex Shvartzkop <[email protected]>
5 * Copyright (C) 2023-2024 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#include "easyeda_parser_base.h"
26
27#include <bezier_curves.h>
28#include <ki_exception.h>
29#include <wx/translation.h>
30#include <eda_text.h>
31
32
33double EASYEDA_PARSER_BASE::Convert( const wxString& aValue )
34{
35 double value = 0;
36
37 if( !aValue.ToCDouble( &value ) )
38 THROW_IO_ERROR( wxString::Format( _( "Failed to parse number from '%s'" ), aValue ) );
39
40 return value;
41}
42
43
44double EASYEDA_PARSER_BASE::RelPosX( double aValue )
45{
46 double value = aValue - m_relOrigin.x;
47 return ScaleSize( value );
48}
49
50
51double EASYEDA_PARSER_BASE::RelPosY( double aValue )
52{
53 double value = aValue - m_relOrigin.y;
54 return ScaleSize( value );
55}
56
57
58double EASYEDA_PARSER_BASE::RelPosX( const wxString& aValue )
59{
60 return RelPosX( Convert( aValue ) );
61}
62
63
64double EASYEDA_PARSER_BASE::RelPosY( const wxString& aValue )
65{
66 return RelPosY( Convert( aValue ) );
67}
68
69
71 const wxString& baselineAlign )
72{
73 int upOffset = 0;
74
75 if( baselineAlign == wxS( "" ) || baselineAlign == wxS( "auto" )
76 || baselineAlign == wxS( "use-script" ) || baselineAlign == wxS( "no-change" )
77 || baselineAlign == wxS( "reset-size" ) || baselineAlign == wxS( "alphabetic" )
78 || baselineAlign == wxS( "inherit" ) )
79 {
80 upOffset = textItem->GetTextSize().y;
81 }
82 else if( baselineAlign == wxS( "ideographic" ) || baselineAlign == wxS( "text-after-edge" ) )
83 {
84 upOffset = textItem->GetTextSize().y * 1.2;
85 }
86 else if( baselineAlign == wxS( "central" ) )
87 {
88 upOffset = textItem->GetTextSize().y * 0.5;
89 }
90 else if( baselineAlign == wxS( "middle" ) )
91 {
92 upOffset = textItem->GetTextSize().y * 0.6;
93 }
94 else if( baselineAlign == wxS( "mathematical" ) )
95 {
96 upOffset = textItem->GetTextSize().y * 0.1;
97 }
98 else if( baselineAlign == wxS( "hanging" ) || baselineAlign == wxS( "text-before-edge" ) )
99 {
100 upOffset = 0;
101 }
102
103 VECTOR2I offset( 0, -upOffset );
104 RotatePoint( offset, textItem->GetTextAngle() );
105
106 textItem->SetTextPos( textItem->GetTextPos() + offset );
107}
108
109
110std::vector<SHAPE_LINE_CHAIN>
111EASYEDA_PARSER_BASE::ParseLineChains( const wxString& data, int aArcMinSegLen, bool aForceClosed )
112{
113 std::vector<SHAPE_LINE_CHAIN> result;
114
115 VECTOR2D prevPt;
116 SHAPE_LINE_CHAIN chain;
117
118 size_t pos = 0;
119 auto readNumber = [&]( wxString& aOut )
120 {
121 wxUniChar ch = data[pos];
122
123 while( ch == ' ' || ch == ',' )
124 ch = data[++pos];
125
126 while( isdigit( ch ) || ch == '.' || ch == '-' )
127 {
128 aOut += ch;
129 pos++;
130
131 if( pos == data.size() )
132 break;
133
134 ch = data[pos];
135 }
136 };
137
138 do
139 {
140 wxUniChar sym = data[pos++];
141
142 if( sym == ' ' )
143 continue;
144
145 if( sym == 'M' )
146 {
147 wxString xStr, yStr;
148
149 readNumber( xStr );
150 readNumber( yStr );
151
152 if( chain.PointCount() > 1 )
153 {
154 if( aForceClosed )
155 chain.SetClosed( true );
156
157 result.emplace_back( chain );
158 }
159
160 chain.Clear();
161
162 VECTOR2D pt( Convert( xStr ), Convert( yStr ) );
163 chain.Append( RelPos( pt ) );
164
165 prevPt = pt;
166 }
167 else if( sym == 'Z' )
168 {
169 if( chain.PointCount() > 2 )
170 {
171 chain.SetClosed( true );
172 result.emplace_back( chain );
173 }
174 chain.Clear();
175 }
176 else if( sym == 'L' || isdigit( sym ) || sym == '-' )
177 {
178 // We may not have a command, just coordinates:
179 // M 4108.8 3364.1 3982.598 3295.6914
180 if( isdigit( sym ) || sym == '-' )
181 pos--;
182
183 while( true )
184 {
185 if( pos >= data.size() )
186 break;
187
188 wxUniChar ch = data[pos];
189
190 while( ch == ' ' || ch == ',' )
191 {
192 if( ++pos >= data.size() )
193 break;
194
195 ch = data[pos];
196 }
197
198 if( !isdigit( ch ) && ch != '-' )
199 break;
200
201 wxString xStr, yStr;
202
203 readNumber( xStr );
204 readNumber( yStr );
205
206 VECTOR2D pt( Convert( xStr ), Convert( yStr ) );
207 chain.Append( RelPos( pt ) );
208
209 prevPt = pt;
210 };
211 }
212 else if( sym == 'A' )
213 {
214 wxString radX, radY, unknown, farFlag, cwFlag, endX, endY;
215
216 readNumber( radX );
217 readNumber( radY );
218 readNumber( unknown );
219 readNumber( farFlag );
220 readNumber( cwFlag );
221 readNumber( endX );
222 readNumber( endY );
223
224 bool isFar = farFlag == wxS( "1" );
225 bool cw = cwFlag == wxS( "1" );
226 VECTOR2D rad( Convert( radX ), Convert( radY ) );
227 VECTOR2D end( Convert( endX ), Convert( endY ) );
228
229 VECTOR2D start = prevPt;
230 VECTOR2D delta = end - start;
231
232 double d = delta.EuclideanNorm();
233 double h = sqrt( std::max( 0.0, rad.x * rad.x - d * d / 4 ) );
234
235 //( !far && cw ) => h
236 //( far && cw ) => -h
237 //( !far && !cw ) => -h
238 //( far && !cw ) => h
239 VECTOR2D arcCenter =
240 start + delta / 2 + delta.Perpendicular().Resize( ( isFar ^ cw ) ? h : -h );
241
242 SHAPE_ARC arc;
243 arc.ConstructFromStartEndCenter( RelPos( start ), RelPos( end ), RelPos( arcCenter ),
244 !cw );
245
246 chain.Append( arc, aArcMinSegLen );
247
248 prevPt = end;
249 }
250 else if( sym == 'C' )
251 {
252 wxString p1_xStr, p1_yStr, p2_xStr, p2_yStr, p3_xStr, p3_yStr;
253 readNumber( p1_xStr );
254 readNumber( p1_yStr );
255 readNumber( p2_xStr );
256 readNumber( p2_yStr );
257 readNumber( p3_xStr );
258 readNumber( p3_yStr );
259
260 VECTOR2D pt1( Convert( p1_xStr ), Convert( p1_yStr ) );
261 VECTOR2D pt2( Convert( p2_xStr ), Convert( p2_yStr ) );
262 VECTOR2D pt3( Convert( p3_xStr ), Convert( p3_yStr ) );
263
264 std::vector<VECTOR2I> ctrlPoints = { RelPos( prevPt ), RelPos( pt1 ), RelPos( pt2 ),
265 RelPos( pt3 ) };
266 BEZIER_POLY converter( ctrlPoints );
267
268 std::vector<VECTOR2I> bezierPoints;
269 converter.GetPoly( bezierPoints, aArcMinSegLen );
270
271 chain.Append( bezierPoints );
272
273 prevPt = pt3;
274 }
275 } while( pos < data.size() );
276
277 if( chain.PointCount() > 1 )
278 {
279 if( aForceClosed )
280 chain.SetClosed( true );
281
282 result.emplace_back( chain );
283 }
284
285 return result;
286}
Bezier curves to polygon converter.
Definition: bezier_curves.h:38
void GetPoly(std::vector< VECTOR2I > &aOutput, int aMaxError=10)
Convert a Bezier curve to a polygon.
std::vector< SHAPE_LINE_CHAIN > ParseLineChains(const wxString &aData, int aArcMinSegLen, bool aForceClosed)
static double Convert(const wxString &aValue)
double RelPosX(double aValue)
double RelPosY(double aValue)
VECTOR2< T > RelPos(const VECTOR2< T > &aVec)
void TransformTextToBaseline(EDA_TEXT *textItem, const wxString &baselineAlign)
virtual double ScaleSize(double aValue)=0
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:79
const VECTOR2I & GetTextPos() const
Definition: eda_text.h:253
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:130
void SetTextPos(const VECTOR2I &aPoint)
Definition: eda_text.cpp:464
VECTOR2I GetTextSize() const
Definition: eda_text.h:241
SHAPE_ARC & ConstructFromStartEndCenter(const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aCenter, bool aClockwise=false, double aWidth=0)
Constructs this arc from the given start, end and center.
Definition: shape_arc.cpp:212
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Clear()
Remove all points from the line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
#define _(s)
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:39
constexpr int delta
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