KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_sch_line_ending_io.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <boost/test/unit_test.hpp>
22
23#include <lib_symbol.h>
24#include <sch_field.h>
26#include <sch_line.h>
27#include <sch_shape.h>
28
29#include <line_ending.h>
30#include <stroke_params.h>
31
32#include <wx/filename.h>
33
34
35BOOST_AUTO_TEST_SUITE( SchLineEndingIo )
36
37
38namespace
39{
40
41class TEMP_SYMBOL_LIBRARY
42{
43public:
44 TEMP_SYMBOL_LIBRARY()
45 {
46 m_dir = wxFileName::CreateTempFileName( wxS( "kicad_qa_sch_line_ending_io_" ) );
47 wxRemoveFile( m_dir );
48 wxFileName::Mkdir( m_dir );
49
50 m_path = wxFileName( m_dir, wxS( "line_ending_roundtrip.kicad_sym" ) ).GetFullPath();
51 }
52
53 ~TEMP_SYMBOL_LIBRARY()
54 {
55 if( wxFileName::DirExists( m_dir ) )
56 wxFileName::Rmdir( m_dir, wxPATH_RMDIR_RECURSIVE );
57 }
58
59 const wxString& Path() const { return m_path; }
60
61private:
62 wxString m_dir;
63 wxString m_path;
64};
65
66
67void setEndings( SCH_SHAPE* aShape )
68{
70 aShape->SetStartEndingLength( 508 );
71 aShape->SetStartEndingWidth( 254 );
72 aShape->SetStartEndingStrokeWidth( 76 );
73
75 aShape->SetEndEndingLength( 762 );
76 aShape->SetEndEndingWidth( 508 );
77 aShape->SetEndEndingStrokeWidth( 102 );
78}
79
80
81void checkEnding( const LINE_ENDING& aEnding, LINE_ENDING_STYLE aStyle, int aLength, int aWidth,
82 int aStrokeWidth )
83{
84 BOOST_CHECK_EQUAL( static_cast<int>( aEnding.GetStyle() ), static_cast<int>( aStyle ) );
85 BOOST_CHECK_EQUAL( aEnding.GetLength(), aLength );
86 BOOST_CHECK_EQUAL( aEnding.GetWidth(), aWidth );
87 BOOST_CHECK_EQUAL( aEnding.GetStrokeWidth(), aStrokeWidth );
88}
89
90
91SCH_SHAPE* findSymbolShape( LIB_SYMBOL* aSymbol, SHAPE_T aShape )
92{
93 for( SCH_ITEM& item : aSymbol->GetDrawItems() )
94 {
95 SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( &item );
96
97 if( shape && shape->GetShape() == aShape )
98 return shape;
99 }
100
101 return nullptr;
102}
103
104} // namespace
105
106
107BOOST_AUTO_TEST_CASE( SymbolLibraryLineEndingsRoundTrip )
108{
109 TEMP_SYMBOL_LIBRARY tempLib;
110
111 LIB_SYMBOL symbol( wxS( "LineEndingSymbol" ) );
112 symbol.GetReferenceField().SetText( wxS( "U" ) );
113 symbol.GetValueField().SetText( symbol.GetName() );
114
115 auto* poly = new SCH_SHAPE( SHAPE_T::POLY, LAYER_DEVICE );
116 poly->AddPoint( VECTOR2I( 0, 0 ) );
117 poly->AddPoint( VECTOR2I( 1000, 0 ) );
118 poly->AddPoint( VECTOR2I( 1000, 500 ) );
119 poly->SetStroke( STROKE_PARAMS( 50, LINE_STYLE::SOLID ) );
120 setEndings( poly );
121 symbol.AddDrawItem( poly, false );
122
123 auto* arc = new SCH_SHAPE( SHAPE_T::ARC, LAYER_DEVICE );
124 arc->SetArcGeometry( VECTOR2I( 0, 1000 ), VECTOR2I( 500, 1500 ), VECTOR2I( 1000, 1000 ) );
125 arc->SetStroke( STROKE_PARAMS( 50, LINE_STYLE::SOLID ) );
126 setEndings( arc );
127 symbol.AddDrawItem( arc, false );
128
129 auto* bezier = new SCH_SHAPE( SHAPE_T::BEZIER, LAYER_DEVICE );
130 bezier->SetStart( VECTOR2I( 0, 2000 ) );
131 bezier->SetBezierC1( VECTOR2I( 300, 2500 ) );
132 bezier->SetBezierC2( VECTOR2I( 700, 1500 ) );
133 bezier->SetEnd( VECTOR2I( 1000, 2000 ) );
134 bezier->SetStroke( STROKE_PARAMS( 50, LINE_STYLE::SOLID ) );
135 setEndings( bezier );
136 symbol.AddDrawItem( bezier, false );
137
138 {
140
141 io.CreateLibrary( tempLib.Path() );
142 io.SaveSymbol( tempLib.Path(), std::make_unique<LIB_SYMBOL>( symbol ) );
143 io.SaveLibrary( tempLib.Path() );
144 }
145
146 SCH_IO_KICAD_SEXPR reader;
147 LIB_SYMBOL* loaded = reader.LoadSymbol( tempLib.Path(), symbol.GetName() );
148
149 BOOST_REQUIRE( loaded );
150
151 for( SHAPE_T shapeType : { SHAPE_T::POLY, SHAPE_T::ARC, SHAPE_T::BEZIER } )
152 {
153 SCH_SHAPE* shape = findSymbolShape( loaded, shapeType );
154 BOOST_REQUIRE_MESSAGE( shape, "Expected symbol shape was not reloaded" );
155
156 checkEnding( shape->GetStartEnding(), LINE_ENDING_STYLE::ARROW, 508, 254, 76 );
157 checkEnding( shape->GetEndEnding(), LINE_ENDING_STYLE::ARROW_OPEN, 762, 508, 102 );
158 }
159}
160
161
162BOOST_AUTO_TEST_CASE( GraphicLineBoundingBoxIncludesLineEndings )
163{
164 SCH_LINE line( VECTOR2I( 0, 0 ), LAYER_NOTES );
165 line.SetEndPoint( VECTOR2I( 1000, 0 ) );
166 line.SetLineWidth( 20 );
168 line.SetEndEndingLength( 400 );
169 line.SetEndEndingWidth( 400 );
170
171 BOX2I bbox = line.GetBoundingBox();
172
173 BOOST_CHECK( bbox.GetRight() >= 1200 );
174 BOOST_CHECK( bbox.GetTop() <= -200 );
175 BOOST_CHECK( bbox.GetBottom() >= 200 );
176}
177
178
179BOOST_AUTO_TEST_CASE( WireBoundingBoxIgnoresLineEndingState )
180{
181 SCH_LINE wire( VECTOR2I( 0, 0 ), LAYER_WIRE );
182 wire.SetEndPoint( VECTOR2I( 1000, 0 ) );
183 wire.SetLineWidth( 20 );
185 wire.SetEndEndingLength( 400 );
186 wire.SetEndEndingWidth( 400 );
187
188 BOX2I bbox = wire.GetBoundingBox();
189
190 BOOST_CHECK( bbox.GetRight() < 1200 );
191}
192
193
194BOOST_AUTO_TEST_CASE( GraphicLineHitTestIncludesLineEnding )
195{
196 SCH_LINE line( VECTOR2I( 0, 0 ), LAYER_NOTES );
197 line.SetEndPoint( VECTOR2I( 1000, 0 ) );
198 line.SetLineWidth( 20 );
200 line.SetEndEndingLength( 400 );
201 line.SetEndEndingWidth( 400 );
202
203 BOOST_CHECK( line.HitTest( VECTOR2I( 1100, 150 ), 0 ) );
204
205 BOX2I selection( VECTOR2I( 1100, 100 ), VECTOR2I( 50, 50 ) );
206 BOOST_CHECK( line.HitTest( selection, false, 0 ) );
207}
208
209
210BOOST_AUTO_TEST_CASE( WireHitTestIgnoresLineEndingState )
211{
212 SCH_LINE wire( VECTOR2I( 0, 0 ), LAYER_WIRE );
213 wire.SetEndPoint( VECTOR2I( 1000, 0 ) );
214 wire.SetLineWidth( 20 );
216 wire.SetEndEndingLength( 400 );
217 wire.SetEndEndingWidth( 400 );
218
219 BOOST_CHECK( !wire.HitTest( VECTOR2I( 1100, 150 ), 0 ) );
220}
221
222
223BOOST_AUTO_TEST_CASE( ShortGraphicLineHitTestIncludesConsumedBodyEnding )
224{
225 SCH_LINE line( VECTOR2I( 0, 0 ), LAYER_NOTES );
226 line.SetEndPoint( VECTOR2I( 100, 0 ) );
227 line.SetLineWidth( 20 );
229 line.SetEndEndingLength( 400 );
230 line.SetEndEndingWidth( 400 );
231
232 BOOST_CHECK( line.HitTest( VECTOR2I( -200, 100 ), 0 ) );
233}
234
235
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
constexpr coord_type GetRight() const
Definition box2.h:214
constexpr coord_type GetTop() const
Definition box2.h:226
constexpr coord_type GetBottom() const
Definition box2.h:219
void SetEndEndingLength(int aLength)
Definition eda_shape.h:195
void SetStartEndingStyle(LINE_ENDING_STYLE aStyle)
Definition eda_shape.h:184
void SetEndEndingWidth(int aWidth)
Definition eda_shape.h:197
void SetEndEndingStyle(LINE_ENDING_STYLE aStyle)
Definition eda_shape.h:187
SHAPE_T GetShape() const
Definition eda_shape.h:175
void SetStartEndingLength(int aLength)
Definition eda_shape.h:190
void SetEndEndingStrokeWidth(int aWidth)
Definition eda_shape.h:202
void SetStartEndingWidth(int aWidth)
Definition eda_shape.h:192
const LINE_ENDING & GetStartEnding() const
Definition eda_shape.h:177
const LINE_ENDING & GetEndEnding() const
Definition eda_shape.h:180
void SetStartEndingStrokeWidth(int aWidth)
Definition eda_shape.h:200
Define a library symbol object.
Definition lib_symbol.h:119
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
Definition lib_symbol.h:832
wxString GetName() const override
Definition lib_symbol.h:181
SCH_FIELD & GetValueField()
Return reference to the value field.
Definition lib_symbol.h:437
void AddDrawItem(SCH_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
SCH_FIELD & GetReferenceField()
Return reference to the reference designator field.
Definition lib_symbol.h:441
Decorative shape (arrowhead, circle, square) at the start or end of a graphic line,...
Definition line_ending.h:62
int GetLength() const
Along-line size. 0 = auto.
Definition line_ending.h:84
int GetWidth() const
Perpendicular size. 0 = auto.
Definition line_ending.h:87
LINE_ENDING_STYLE GetStyle() const
Definition line_ending.h:81
int GetStrokeWidth() const
Outline stroke width.
void SetText(const wxString &aText) override
A SCH_IO derivation for loading schematic files using the new s-expression file format.
void SaveLibrary(const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties=nullptr) override
LIB_SYMBOL * LoadSymbol(const wxString &aLibraryPath, const wxString &aAliasName, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load a LIB_SYMBOL object having aPartName from the aLibraryPath containing a library format that this...
void CreateLibrary(const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Create a new empty library at aLibraryPath empty.
void SaveSymbol(const wxString &aLibraryPath, std::unique_ptr< LIB_SYMBOL > aSymbol, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aSymbol to an existing library located at aLibraryPath.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:165
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:39
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition sch_line.cpp:906
void SetEndEndingStyle(LINE_ENDING_STYLE aStyle)
Definition sch_line.h:211
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition sch_line.cpp:315
void SetEndEndingWidth(int aWidth)
Definition sch_line.h:221
void SetLineWidth(const int aSize)
Definition sch_line.cpp:437
void SetEndEndingLength(int aLength)
Definition sch_line.h:219
void SetEndPoint(const VECTOR2I &aPosition)
Definition sch_line.h:146
Simple container to manage line stroke parameters.
SHAPE_T
Definition eda_shape.h:54
@ LAYER_DEVICE
Definition layer_ids.h:488
@ LAYER_WIRE
Definition layer_ids.h:474
@ LAYER_NOTES
Definition layer_ids.h:489
LINE_ENDING_STYLE
Line ending styles for graphic lines, arcs, and beziers.
Definition line_ending.h:44
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(SymbolLibraryLineEndingsRoundTrip)
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683