Add conversion from CADSTAR SHAPE to SHAPE_POLY_SET
This commit is contained in:
parent
7e01816b73
commit
ee6e86d1db
|
@ -27,6 +27,7 @@
|
|||
#include <wx/xml/xml.h>
|
||||
|
||||
#include <dsnlexer.h>
|
||||
#include <geometry/shape_poly_set.h>
|
||||
#include <plugins/cadstar/cadstar_archive_parser.h>
|
||||
#include <eda_item.h>
|
||||
#include <eda_text.h>
|
||||
|
@ -481,6 +482,45 @@ void CADSTAR_ARCHIVE_PARSER::VERTEX::Parse( XNODE* aNode, PARSER_CONTEXT* aConte
|
|||
}
|
||||
|
||||
|
||||
void CADSTAR_ARCHIVE_PARSER::VERTEX::AppendToChain( SHAPE_LINE_CHAIN* aChainToAppendTo,
|
||||
const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback ) const
|
||||
{
|
||||
VECTOR2I endPoint = aCadstarToKicadPointCallback( End );
|
||||
|
||||
if( Type == VERTEX_TYPE::POINT )
|
||||
{
|
||||
aChainToAppendTo->Append( endPoint );
|
||||
return;
|
||||
}
|
||||
|
||||
wxCHECK_MSG( aChainToAppendTo->PointCount() > 0, /*void*/,
|
||||
"Can't append an arc to vertex to an empty chain" );
|
||||
|
||||
VECTOR2I startPoint = aChainToAppendTo->GetPoint( -1 );
|
||||
VECTOR2I centerPoint;
|
||||
|
||||
if( Type == VERTEX_TYPE::ANTICLOCKWISE_SEMICIRCLE || Type == VERTEX_TYPE::CLOCKWISE_SEMICIRCLE )
|
||||
centerPoint = ( startPoint / 2 ) + ( endPoint / 2 );
|
||||
else
|
||||
centerPoint = aCadstarToKicadPointCallback( Center );
|
||||
|
||||
bool clockwise = Type == VERTEX_TYPE::CLOCKWISE_ARC
|
||||
|| Type == VERTEX_TYPE::CLOCKWISE_SEMICIRCLE;
|
||||
|
||||
// A bit of a hack to figure out if we need to invert clockwise due to the transform
|
||||
VECTOR2I transform = aCadstarToKicadPointCallback( { 500, 500 } )
|
||||
- aCadstarToKicadPointCallback( { 0, 0 } );
|
||||
|
||||
if( ( transform.x > 0 && transform.y < 0 ) || ( transform.x < 0 && transform.y > 0 ) )
|
||||
clockwise = !clockwise;
|
||||
|
||||
SHAPE_ARC arc;
|
||||
arc.ConstructFromStartEndCenter( startPoint, endPoint, centerPoint, clockwise );
|
||||
|
||||
aChainToAppendTo->Append( arc );
|
||||
}
|
||||
|
||||
|
||||
void CADSTAR_ARCHIVE_PARSER::CUTOUT::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
||||
{
|
||||
wxASSERT( aNode->GetName() == wxT( "CUTOUT" ) );
|
||||
|
@ -545,6 +585,45 @@ void CADSTAR_ARCHIVE_PARSER::SHAPE::Parse( XNODE* aNode, PARSER_CONTEXT* aContex
|
|||
}
|
||||
}
|
||||
|
||||
SHAPE_LINE_CHAIN CADSTAR_ARCHIVE_PARSER::SHAPE::OutlineAsChain(
|
||||
const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback ) const
|
||||
{
|
||||
SHAPE_LINE_CHAIN outline;
|
||||
|
||||
for( const auto& vertex : Vertices )
|
||||
vertex.AppendToChain( &outline, aCadstarToKicadPointCallback );
|
||||
|
||||
if( Type != SHAPE_TYPE::OPENSHAPE )
|
||||
outline.SetClosed( true );
|
||||
|
||||
return outline;
|
||||
}
|
||||
|
||||
|
||||
SHAPE_POLY_SET CADSTAR_ARCHIVE_PARSER::SHAPE::ConvertToPolySet(
|
||||
const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback ) const
|
||||
{
|
||||
SHAPE_POLY_SET polyset;
|
||||
|
||||
wxCHECK( Type != SHAPE_TYPE::OPENSHAPE, polyset ); // We shouldn't convert openshapes to polyset!
|
||||
|
||||
polyset.AddOutline( OutlineAsChain( aCadstarToKicadPointCallback) );
|
||||
|
||||
for( const auto& cutout : Cutouts )
|
||||
{
|
||||
SHAPE_LINE_CHAIN hole;
|
||||
|
||||
for( const auto& cutoutVertex : cutout.Vertices )
|
||||
cutoutVertex.AppendToChain( &hole, aCadstarToKicadPointCallback );
|
||||
|
||||
hole.SetClosed( true );
|
||||
|
||||
polyset.AddHole( hole );
|
||||
}
|
||||
|
||||
return polyset;
|
||||
}
|
||||
|
||||
|
||||
CADSTAR_ARCHIVE_PARSER::UNITS CADSTAR_ARCHIVE_PARSER::ParseUnits( XNODE* aNode )
|
||||
{
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include <vector>
|
||||
#include <xnode.h>
|
||||
|
||||
#include <math/vector2d.h>
|
||||
|
||||
// THROW_IO_ERROR definitions to ensure consistent wording is used in the error messages
|
||||
|
||||
#define THROW_MISSING_NODE_IO_ERROR( nodename, location ) \
|
||||
|
@ -79,6 +81,8 @@
|
|||
class EDA_TEXT;
|
||||
class wxXmlAttribute;
|
||||
class PROGRESS_REPORTER;
|
||||
class SHAPE_LINE_CHAIN;
|
||||
class SHAPE_POLY_SET;
|
||||
|
||||
/**
|
||||
* @brief Helper functions and common structures for CADSTAR PCB and Schematic archive files.
|
||||
|
@ -396,9 +400,8 @@ public:
|
|||
*/
|
||||
struct POINT : wxPoint, PARSER
|
||||
{
|
||||
POINT() : wxPoint( UNDEFINED_VALUE, UNDEFINED_VALUE )
|
||||
{
|
||||
}
|
||||
POINT() : wxPoint( UNDEFINED_VALUE, UNDEFINED_VALUE ) {}
|
||||
POINT( int aX, int aY ) : wxPoint( aX, aY ) {}
|
||||
|
||||
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
||||
};
|
||||
|
@ -413,6 +416,12 @@ public:
|
|||
};
|
||||
|
||||
|
||||
struct TRANSFORM
|
||||
{
|
||||
virtual wxPoint Apply( POINT aCadstarPoint ) = 0;
|
||||
};
|
||||
|
||||
|
||||
enum class VERTEX_TYPE
|
||||
{
|
||||
POINT,
|
||||
|
@ -428,12 +437,19 @@ public:
|
|||
*/
|
||||
struct VERTEX : PARSER
|
||||
{
|
||||
VERTEX( VERTEX_TYPE aType = VERTEX_TYPE::POINT, POINT aEnd = POINT(), POINT aCenter = POINT() ) :
|
||||
Type( aType ), End( aEnd ), Center( aCenter )
|
||||
{}
|
||||
|
||||
VERTEX_TYPE Type;
|
||||
POINT Center;
|
||||
POINT End;
|
||||
POINT Center;
|
||||
|
||||
static bool IsVertex( XNODE* aNode );
|
||||
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
||||
|
||||
void AppendToChain( SHAPE_LINE_CHAIN* aChainToAppendTo,
|
||||
const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback ) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -465,6 +481,12 @@ public:
|
|||
|
||||
static bool IsShape( XNODE* aNode );
|
||||
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
||||
|
||||
SHAPE_LINE_CHAIN OutlineAsChain( const std::function<VECTOR2I( const VECTOR2I& )>
|
||||
aCadstarToKicadPointCallback ) const;
|
||||
|
||||
SHAPE_POLY_SET ConvertToPolySet( const std::function<VECTOR2I( const VECTOR2I& )>
|
||||
aCadstarToKicadPointCallback ) const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -51,6 +51,8 @@ set( QA_COMMON_SRCS
|
|||
plugins/altium/test_altium_parser.cpp
|
||||
plugins/altium/test_altium_parser_utils.cpp
|
||||
|
||||
plugins/cadstar/test_cadstar_archive_parser.cpp
|
||||
|
||||
view/test_zoom_controller.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file test_cadstar_archive_parser.cpp
|
||||
* Test suite for #CADSTAR_ARCHIVE_PARSER
|
||||
*/
|
||||
|
||||
#include <qa_utils/wx_utils/unit_test_utils.h>
|
||||
|
||||
#include <common/plugins/cadstar/cadstar_archive_parser.h>
|
||||
|
||||
#include <qa_utils/geometry/geometry.h> // For KI_TEST::IsVecWithinTol
|
||||
#include <geometry/shape_line_chain.h>
|
||||
#include <geometry/shape_arc.h> // For SHAPE_ARC::DefaultAccuracyForPCB()
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( CadstartArchiveParser )
|
||||
|
||||
|
||||
struct VERTEX_APPEND_CASE
|
||||
{
|
||||
std::string m_CaseName;
|
||||
CADSTAR_ARCHIVE_PARSER::VERTEX m_VertexToAppend;
|
||||
BOX2I m_ExpBBox;
|
||||
int m_ExpBBoxError;
|
||||
};
|
||||
|
||||
std::function<wxPoint( const wxPoint& )> m_CadstarToKicadPointCallback;
|
||||
|
||||
using vt=CADSTAR_ARCHIVE_PARSER::VERTEX_TYPE;
|
||||
|
||||
|
||||
static const std::vector<VERTEX_APPEND_CASE> appendToChainCases
|
||||
{
|
||||
{
|
||||
"Append a point on x",
|
||||
{ vt::POINT, { 500000, 0 } },
|
||||
{ /* BBOX Position: */ { 0, 0 }, /* Size:*/ { 500000, 0 } },
|
||||
0
|
||||
},
|
||||
{
|
||||
"Append a point on y",
|
||||
{ vt::POINT, { 0, 500000 } },
|
||||
{ /* BBOX Position: */ { 0, 0 }, /* Size:*/ { 0, 500000 } },
|
||||
0
|
||||
},
|
||||
{
|
||||
"Append a Semicircle (clockwise)",
|
||||
{ vt::CLOCKWISE_SEMICIRCLE, { 500000, 0 } },
|
||||
{ /* BBOX Position: */ { 0, 0 }, /* Size: */ { 500000, 250000 } },
|
||||
int( SHAPE_ARC::DefaultAccuracyForPCB() ) // acceptable error when converting to line segments
|
||||
},
|
||||
{
|
||||
"Append a Semicircle (anticlockwise)",
|
||||
{ vt::ANTICLOCKWISE_SEMICIRCLE, { 500000, 0 } },
|
||||
{ /* BBOX Position: */ { 0, -250000 }, /* Size: */ { 500000, 250000 } },
|
||||
int( SHAPE_ARC::DefaultAccuracyForPCB() ) // acceptable error when converting to line segments
|
||||
},
|
||||
{
|
||||
"Append a 90 degree Arc (clockwise)",
|
||||
{ vt::CLOCKWISE_ARC, { 250000, 250000 }, { 250000, 0 } },
|
||||
{ /* BBOX Position: */ { 0, 0 }, /* Size: */ { 250000, 250000 } },
|
||||
int( SHAPE_ARC::DefaultAccuracyForPCB() ) // acceptable error when converting to line segments
|
||||
},
|
||||
{
|
||||
"Append a 90 degree Arc (anticlockwise)",
|
||||
{ vt::ANTICLOCKWISE_ARC, { 250000, -250000 }, { 250000, 0 } },
|
||||
{ /* BBOX Position: */ { 0, -250000 }, /* Size: */ { 250000, 250000 } },
|
||||
int( SHAPE_ARC::DefaultAccuracyForPCB() ) // acceptable error when converting to line segments
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( AppendToChain )
|
||||
{
|
||||
static const std::vector<VECTOR2D> coordinateMultipliers =
|
||||
{
|
||||
{ 0.1, 0.1 },
|
||||
{ 0.1, -0.1 }, // y inversion
|
||||
{ 1, 1 },
|
||||
{ 1, -1 }, // y inversion
|
||||
{ 10, 10 },
|
||||
{ 10, -10 } // y inversion
|
||||
};
|
||||
|
||||
|
||||
for( const auto& c : appendToChainCases )
|
||||
{
|
||||
BOOST_TEST_INFO_SCOPE( c.m_CaseName );
|
||||
|
||||
for( const VECTOR2D& mult : coordinateMultipliers )
|
||||
{
|
||||
BOOST_TEST_INFO_SCOPE( "Applied scaling x=" << mult.x << " y=" << mult.y );
|
||||
|
||||
SHAPE_LINE_CHAIN chain( { 0, 0 } ); // starting chain contains a point at 0,0
|
||||
|
||||
auto transformCoord =
|
||||
[&]( const VECTOR2I& aPt ) -> VECTOR2I
|
||||
{
|
||||
int x = double( aPt.x ) * mult.x;
|
||||
int y = double( aPt.y ) * mult.y;
|
||||
return { x, y };
|
||||
};
|
||||
|
||||
c.m_VertexToAppend.AppendToChain( &chain, transformCoord );
|
||||
|
||||
BOX2I expBoxTransformed;
|
||||
expBoxTransformed.SetOrigin( transformCoord( c.m_ExpBBox.GetPosition() ) );
|
||||
expBoxTransformed.SetSize( transformCoord( c.m_ExpBBox.GetSize() ) );
|
||||
expBoxTransformed.Normalize();
|
||||
|
||||
BOOST_CHECK_PREDICATE(
|
||||
KI_TEST::IsVecWithinTol<VECTOR2I>,
|
||||
( chain.BBox().GetPosition() )( expBoxTransformed.GetPosition() ) ( c.m_ExpBBoxError ) );
|
||||
|
||||
BOOST_CHECK_PREDICATE(
|
||||
KI_TEST::IsVecWithinTol<VECTOR2I>,
|
||||
( chain.BBox().GetSize() )( expBoxTransformed.GetSize() ) ( c.m_ExpBBoxError ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
Loading…
Reference in New Issue