Add handling of DXF arbitrary axis/extrusions
This fixes some DXFs imports where unforunately CAD tools like SolidWorks randomly decide to mirror circle definitions across the "z" axis (resulting in x or y axis flips in 2d) Most likely live projection from 3D to 2D drawings introduces this. However this is DXF specification to describe it so obtusely with vectors for a 2d drawing.
This commit is contained in:
parent
44f4d41bba
commit
45598f2933
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VECTOR3_H_
|
||||
#define VECTOR3_H_
|
||||
|
||||
/**
|
||||
* VECTOR2_TRAITS
|
||||
* traits class for VECTOR2.
|
||||
*/
|
||||
template <class T>
|
||||
struct VECTOR3_TRAITS
|
||||
{
|
||||
///> extended range/precision types used by operations involving multiple
|
||||
///> multiplications to prevent overflow.
|
||||
typedef T extended_type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct VECTOR3_TRAITS<int>
|
||||
{
|
||||
typedef int64_t extended_type;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* VECTOR3
|
||||
* defines a general 3D-vector.
|
||||
*
|
||||
* This class uses templates to be universal. Several operators are provided to help
|
||||
* easy implementing of linear algebra equations.
|
||||
*
|
||||
*/
|
||||
template <class T = int>
|
||||
class VECTOR3
|
||||
{
|
||||
public:
|
||||
typedef typename VECTOR3_TRAITS<T>::extended_type extended_type;
|
||||
typedef T coord_type;
|
||||
|
||||
static constexpr extended_type ECOORD_MAX = std::numeric_limits<extended_type>::max();
|
||||
static constexpr extended_type ECOORD_MIN = std::numeric_limits<extended_type>::min();
|
||||
|
||||
T x, y, z;
|
||||
|
||||
/// Construct a 3D-vector with x, y = 0
|
||||
VECTOR3();
|
||||
|
||||
/// Construct a vector with given components x, y
|
||||
VECTOR3( T x, T y, T z );
|
||||
|
||||
/// Initializes a vector from another specialization. Beware of rouding
|
||||
/// issues.
|
||||
template <typename CastingType>
|
||||
VECTOR3( const VECTOR3<CastingType>& aVec )
|
||||
{
|
||||
x = (T) aVec.x;
|
||||
y = (T) aVec.y;
|
||||
z = (T) aVec.z;
|
||||
}
|
||||
|
||||
/// Copy a vector
|
||||
VECTOR3( const VECTOR3<T>& aVec )
|
||||
{
|
||||
x = aVec.x;
|
||||
y = aVec.y;
|
||||
z = aVec.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function Cross()
|
||||
* computes cross product of self with aVector
|
||||
*/
|
||||
VECTOR3<T> Cross( const VECTOR3<T>& aVector ) const;
|
||||
|
||||
/**
|
||||
* Function Dot()
|
||||
* computes dot product of self with aVector
|
||||
*/
|
||||
VECTOR3<T>::extended_type Dot( const VECTOR3<T>& aVector ) const;
|
||||
|
||||
/**
|
||||
* Function Euclidean Norm
|
||||
* computes the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
|
||||
* It is used to calculate the length of the vector.
|
||||
* @return Scalar, the euclidean norm
|
||||
*/
|
||||
T EuclideanNorm() const;
|
||||
|
||||
/**
|
||||
* Function Normalize()
|
||||
* computes the normalized vector
|
||||
*/
|
||||
VECTOR3<T> Normalize();
|
||||
|
||||
/// Equality operator
|
||||
bool operator==( const VECTOR3<T>& aVector ) const;
|
||||
|
||||
/// Not equality operator
|
||||
bool operator!=( const VECTOR3<T>& aVector ) const;
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
VECTOR3<T>::VECTOR3()
|
||||
{
|
||||
x = y = z = 0.0;
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
VECTOR3<T>::VECTOR3( T aX, T aY, T aZ )
|
||||
{
|
||||
x = aX;
|
||||
y = aY;
|
||||
z = aZ;
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
VECTOR3<T> VECTOR3<T>::Cross( const VECTOR3<T>& aVector ) const
|
||||
{
|
||||
return VECTOR3<T>( ( y * aVector.z ) - ( z * aVector.y ),
|
||||
( z * aVector.x ) - ( x * aVector.z ),
|
||||
( x * aVector.y ) - ( y * aVector.x )
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
typename VECTOR3<T>::extended_type VECTOR3<T>::Dot( const VECTOR3<T>& aVector ) const
|
||||
{
|
||||
return extended_type{x} * extended_type{aVector.x}
|
||||
+ extended_type{y} * extended_type{aVector.y}
|
||||
+ extended_type{z} * extended_type{aVector.z};
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
T VECTOR3<T>::EuclideanNorm() const
|
||||
{
|
||||
return sqrt( (extended_type) x * x + (extended_type) y * y + (extended_type) z * z );
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
VECTOR3<T> VECTOR3<T>::Normalize()
|
||||
{
|
||||
T norm = EuclideanNorm();
|
||||
x /= norm;
|
||||
y /= norm;
|
||||
z /= norm;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
bool VECTOR3<T>::operator==( VECTOR3<T> const& aVector ) const
|
||||
{
|
||||
return ( aVector.x == x ) && ( aVector.y == y ) && ( aVector.z == z );
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
bool VECTOR3<T>::operator!=( VECTOR3<T> const& aVector ) const
|
||||
{
|
||||
return ( aVector.x != x ) || ( aVector.y != y ) || ( aVector.z != z );
|
||||
}
|
||||
|
||||
|
||||
/* Default specializations */
|
||||
typedef VECTOR3<double> VECTOR3D;
|
||||
typedef VECTOR3<int> VECTOR3I;
|
||||
typedef VECTOR3<unsigned int> VECTOR3U;
|
||||
|
||||
#endif // VECTOR3_H_
|
|
@ -40,8 +40,38 @@
|
|||
|
||||
|
||||
/*
|
||||
* Important note: all DXF coordinates and sizes are converted to mm.
|
||||
* they will be converted to internal units later.
|
||||
* Important notes
|
||||
* 1. All output coordinates of this importer are in mm
|
||||
* 2. DXFs have a concept of world (WCS) and object coordinates (OCS)
|
||||
3. The following objects are world coordinates:
|
||||
- Line
|
||||
- Point
|
||||
- Polyline (3D)
|
||||
- Vertex (3D)
|
||||
- Polymesh
|
||||
- Polyface
|
||||
- Viewport
|
||||
4. The following entities are object coordinates
|
||||
- Circle
|
||||
- Arc
|
||||
- Solid
|
||||
- Trace
|
||||
- Attrib
|
||||
- Shape
|
||||
- Insert
|
||||
- Polyline (2D)
|
||||
- Vertex (2D)
|
||||
- LWPolyline
|
||||
- Hatch
|
||||
- Image
|
||||
- Text
|
||||
* 5. Object coordinates must be run through the arbtirary axis
|
||||
* translation even though they are 2D drawings and most of the time
|
||||
* the import is fine. Sometimes, agaisnt all logic, CAD tools like
|
||||
* SolidWorks may randomly insert circles "mirror" that must be unflipped
|
||||
* by following the object to world conversion
|
||||
* 6. Blocks are virtual groups, blocks must be placed by a INSERT entity
|
||||
* 7. Blocks may be repeated multiple times
|
||||
*/
|
||||
|
||||
|
||||
|
@ -52,6 +82,7 @@
|
|||
//#define SCALE_FACTOR(x) millimeter2iu(x) /* no longer used */
|
||||
#define SCALE_FACTOR(x) (x)
|
||||
|
||||
|
||||
DXF_IMPORT_PLUGIN::DXF_IMPORT_PLUGIN() : DL_CreationAdapter()
|
||||
{
|
||||
m_xOffset = 0.0; // X coord offset for conversion (in mm)
|
||||
|
@ -342,18 +373,20 @@ void DXF_IMPORT_PLUGIN::addVertex( const DL_VertexData& aData )
|
|||
|
||||
const DL_VertexData* vertex = &aData;
|
||||
|
||||
DXF_ARBITRARY_AXIS arbAxis = getArbitraryAxis( getExtrusion() );
|
||||
VECTOR3D vertexCoords = ocsToWcs( arbAxis, VECTOR3D( vertex->x, vertex->y, vertex->z ) );
|
||||
|
||||
if( m_curr_entity.m_EntityParseStatus == 1 ) // This is the first vertex of an entity
|
||||
{
|
||||
m_curr_entity.m_LastCoordinate.x = m_xOffset + vertex->x * getCurrentUnitScale();
|
||||
m_curr_entity.m_LastCoordinate.y = m_yOffset - vertex->y * getCurrentUnitScale();
|
||||
m_curr_entity.m_LastCoordinate.x = mapX( vertexCoords.x );
|
||||
m_curr_entity.m_LastCoordinate.y = mapY( vertexCoords.y );
|
||||
m_curr_entity.m_PolylineStart = m_curr_entity.m_LastCoordinate;
|
||||
m_curr_entity.m_BulgeVertex = vertex->bulge;
|
||||
m_curr_entity.m_EntityParseStatus = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
VECTOR2D seg_end( m_xOffset + vertex->x * getCurrentUnitScale(),
|
||||
m_yOffset - vertex->y * getCurrentUnitScale() );
|
||||
VECTOR2D seg_end( mapX( vertexCoords.x ), mapY( vertexCoords.y ) );
|
||||
|
||||
if( std::abs( m_curr_entity.m_BulgeVertex ) < MIN_BULGE )
|
||||
insertLine( m_curr_entity.m_LastCoordinate, seg_end, lineWidth );
|
||||
|
@ -371,6 +404,14 @@ void DXF_IMPORT_PLUGIN::endEntity()
|
|||
DXF_IMPORT_LAYER* layer = getImportLayer( attributes.getLayer() );
|
||||
double lineWidth = lineWeightToWidth( attributes.getWidth(), layer );
|
||||
|
||||
// skip 3d polylines we obviously can't support
|
||||
// TODO: maybe inform the user somehow this was encountered?
|
||||
if( m_curr_entity.m_EntityFlag & DL_POLYLINE3D )
|
||||
{
|
||||
m_curr_entity.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_curr_entity.m_EntityType == DL_ENTITY_POLYLINE ||
|
||||
m_curr_entity.m_EntityType == DL_ENTITY_LWPOLYLINE )
|
||||
{
|
||||
|
@ -420,8 +461,12 @@ void DXF_IMPORT_PLUGIN::addInsert( const DL_InsertData& aData )
|
|||
if( block == nullptr )
|
||||
return;
|
||||
|
||||
VECTOR2D translation( mapX( aData.ipx ), mapY( aData.ipy ) );
|
||||
VECTOR2D scale( mapX( aData.sx ), mapY( aData.sy ) );
|
||||
DXF_ARBITRARY_AXIS arbAxis = getArbitraryAxis( getExtrusion() );
|
||||
VECTOR3D insertCoords = ocsToWcs( arbAxis, VECTOR3D( aData.ipx, aData.ipy, aData.ipz ) );
|
||||
|
||||
VECTOR2D translation( mapX( insertCoords.x ), mapY( insertCoords.y ) );
|
||||
|
||||
// TODO: implement handling of scale
|
||||
|
||||
for( auto& shape : block->m_buffer.GetShapes() )
|
||||
{
|
||||
|
@ -433,9 +478,13 @@ void DXF_IMPORT_PLUGIN::addInsert( const DL_InsertData& aData )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void DXF_IMPORT_PLUGIN::addCircle( const DL_CircleData& aData )
|
||||
{
|
||||
VECTOR2D center( mapX( aData.cx ), mapY( aData.cy ) );
|
||||
DXF_ARBITRARY_AXIS arbAxis = getArbitraryAxis( getExtrusion() );
|
||||
VECTOR3D centerCoords = ocsToWcs( arbAxis, VECTOR3D( aData.cx, aData.cy, aData.cz ) );
|
||||
|
||||
VECTOR2D center( mapX( centerCoords.x ), mapY( centerCoords.y ) );
|
||||
DXF_IMPORT_LAYER* layer = getImportLayer( attributes.getLayer() );
|
||||
double lineWidth = lineWeightToWidth( attributes.getWidth(), layer );
|
||||
|
||||
|
@ -455,8 +504,11 @@ void DXF_IMPORT_PLUGIN::addArc( const DL_ArcData& aData )
|
|||
if( m_currentBlock != nullptr )
|
||||
return;
|
||||
|
||||
DXF_ARBITRARY_AXIS arbAxis = getArbitraryAxis( getExtrusion() );
|
||||
VECTOR3D centerCoords = ocsToWcs( arbAxis, VECTOR3D( aData.cx, aData.cy, aData.cz ) );
|
||||
|
||||
// Init arc centre:
|
||||
VECTOR2D center( mapX( aData.cx ), mapY( aData.cy ) );
|
||||
VECTOR2D center( mapX( centerCoords.x ), mapY( centerCoords.y ) );
|
||||
|
||||
// aData.anglex is in degrees.
|
||||
double startangle = aData.angle1;
|
||||
|
@ -465,7 +517,8 @@ void DXF_IMPORT_PLUGIN::addArc( const DL_ArcData& aData )
|
|||
// Init arc start point
|
||||
VECTOR2D startPoint( aData.radius, 0.0 );
|
||||
startPoint = startPoint.Rotate( startangle * M_PI / 180.0 );
|
||||
VECTOR2D arcStart( mapX( startPoint.x + aData.cx ), mapY( startPoint.y + aData.cy ) );
|
||||
VECTOR2D arcStart(
|
||||
mapX( startPoint.x + centerCoords.x ), mapY( startPoint.y + centerCoords.y ) );
|
||||
|
||||
// calculate arc angle (arcs are CCW, and should be < 0 in Pcbnew)
|
||||
double angle = -( endangle - startangle );
|
||||
|
@ -489,8 +542,12 @@ void DXF_IMPORT_PLUGIN::addArc( const DL_ArcData& aData )
|
|||
|
||||
void DXF_IMPORT_PLUGIN::addText( const DL_TextData& aData )
|
||||
{
|
||||
VECTOR2D refPoint( mapX( aData.ipx ), mapY( aData.ipy ) );
|
||||
VECTOR2D secPoint( mapX( aData.apx ), mapY( aData.apy ) );
|
||||
DXF_ARBITRARY_AXIS arbAxis = getArbitraryAxis( getExtrusion() );
|
||||
VECTOR3D refPointCoords = ocsToWcs( arbAxis, VECTOR3D( aData.ipx, aData.ipy, aData.ipz ) );
|
||||
VECTOR3D secPointCoords = ocsToWcs( arbAxis, VECTOR3D( aData.apx, aData.apy, aData.apz ) );
|
||||
|
||||
VECTOR2D refPoint( mapX( refPointCoords.x ), mapY( refPointCoords.y ) );
|
||||
VECTOR2D secPoint( mapX( secPointCoords.x ), mapY( secPointCoords.y ) );
|
||||
|
||||
if( aData.vJustification != 0 || aData.hJustification != 0 || aData.hJustification == 4 )
|
||||
{
|
||||
|
@ -670,7 +727,10 @@ void DXF_IMPORT_PLUGIN::addMText( const DL_MTextData& aData )
|
|||
text = tmp;
|
||||
}
|
||||
|
||||
VECTOR2D textpos( mapX( aData.ipx ), mapY( aData.ipy ) );
|
||||
DXF_ARBITRARY_AXIS arbAxis = getArbitraryAxis( getExtrusion() );
|
||||
VECTOR3D textposCoords = ocsToWcs( arbAxis, VECTOR3D( aData.ipx, aData.ipy, aData.ipz ) );
|
||||
|
||||
VECTOR2D textpos( mapX( textposCoords.x ), mapY( textposCoords.y ) );
|
||||
|
||||
// Initialize text justifications:
|
||||
EDA_TEXT_HJUSTIFY_T hJustify = GR_TEXT_HJUSTIFY_LEFT;
|
||||
|
@ -1267,3 +1327,56 @@ void DXF_IMPORT_PLUGIN::updateImageLimits( const VECTOR2D& aPoint )
|
|||
m_minY = std::min( aPoint.y, m_minY );
|
||||
m_maxY = std::max( aPoint.y, m_maxY );
|
||||
}
|
||||
|
||||
|
||||
DXF_ARBITRARY_AXIS DXF_IMPORT_PLUGIN::getArbitraryAxis( DL_Extrusion* aData )
|
||||
{
|
||||
VECTOR3D arbZ, arbX, arbY;
|
||||
|
||||
double direction[3];
|
||||
aData->getDirection( direction );
|
||||
|
||||
arbZ = VECTOR3D( direction[0], direction[1], direction[2] ).Normalize();
|
||||
|
||||
if( ( abs( arbZ.x ) < ( 1.0 / 64.0 ) ) && ( abs( arbZ.y ) < ( 1.0 / 64.0 ) ) )
|
||||
{
|
||||
arbX = VECTOR3D( 0, 1, 0 ).Cross( arbZ ).Normalize();
|
||||
}
|
||||
else
|
||||
{
|
||||
arbX = VECTOR3D( 0, 0, 1 ).Cross( arbZ ).Normalize();
|
||||
}
|
||||
|
||||
arbY = arbZ.Cross( arbX ).Normalize();
|
||||
|
||||
return DXF_ARBITRARY_AXIS{ arbX, arbY, arbZ };
|
||||
}
|
||||
|
||||
|
||||
VECTOR3D DXF_IMPORT_PLUGIN::wcsToOcs( const DXF_ARBITRARY_AXIS& arbitraryAxis, VECTOR3D point )
|
||||
{
|
||||
double x, y, z;
|
||||
x = point.x * arbitraryAxis.vecX.x + point.y * arbitraryAxis.vecX.y
|
||||
+ point.z * arbitraryAxis.vecX.z;
|
||||
y = point.x * arbitraryAxis.vecY.x + point.y * arbitraryAxis.vecY.y
|
||||
+ point.z * arbitraryAxis.vecY.z;
|
||||
z = point.x * arbitraryAxis.vecZ.x + point.y * arbitraryAxis.vecZ.y
|
||||
+ point.z * arbitraryAxis.vecZ.z;
|
||||
|
||||
return VECTOR3D( x, y, z );
|
||||
}
|
||||
|
||||
|
||||
VECTOR3D DXF_IMPORT_PLUGIN::ocsToWcs( const DXF_ARBITRARY_AXIS& arbitraryAxis, VECTOR3D point )
|
||||
{
|
||||
VECTOR3D worldX = wcsToOcs( arbitraryAxis, VECTOR3D( 1, 0, 0 ) );
|
||||
VECTOR3D worldY = wcsToOcs( arbitraryAxis, VECTOR3D( 0, 1, 0 ) );
|
||||
VECTOR3D worldZ = wcsToOcs( arbitraryAxis, VECTOR3D( 0, 0, 1 ) );
|
||||
|
||||
double x, y, z;
|
||||
x = point.x * worldX.x + point.y * worldX.y + point.z * worldX.z;
|
||||
y = point.x * worldY.x + point.y * worldY.y + point.z * worldY.z;
|
||||
z = point.x * worldZ.x + point.y * worldZ.y + point.z * worldZ.z;
|
||||
|
||||
return VECTOR3D( x, y, z );
|
||||
}
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include <dl_creationadapter.h>
|
||||
#include <dl_dxf.h>
|
||||
#include <math/vector3.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <wx/wx.h>
|
||||
|
||||
|
@ -176,6 +177,16 @@ enum class DXF_IMPORT_UNITS
|
|||
PARSECS = 20
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class representing the DXF specification's "arbitrary axis"
|
||||
*/
|
||||
struct DXF_ARBITRARY_AXIS
|
||||
{
|
||||
VECTOR3D vecX;
|
||||
VECTOR3D vecY;
|
||||
VECTOR3D vecZ;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class import DXF ASCII files and convert basic entities to board entities.
|
||||
* It depends on the dxflib library.
|
||||
|
@ -317,6 +328,18 @@ private:
|
|||
double lineWeightToWidth( int lw, DXF_IMPORT_LAYER* aLayer );
|
||||
double getCurrentUnitScale();
|
||||
|
||||
DXF_ARBITRARY_AXIS getArbitraryAxis( DL_Extrusion* aData );
|
||||
|
||||
/***
|
||||
* Converts a given world coordinate point to object coordinate using the given arbitrary axis vectors
|
||||
*/
|
||||
VECTOR3D wcsToOcs( const DXF_ARBITRARY_AXIS& arbitraryAxis, VECTOR3D point );
|
||||
|
||||
/***
|
||||
* Converts a given object coordinate point to world coordinate using the given arbitrary axis vectors
|
||||
*/
|
||||
VECTOR3D ocsToWcs( const DXF_ARBITRARY_AXIS& arbitraryAxis, VECTOR3D point );
|
||||
|
||||
/**
|
||||
* Returns the import layer data
|
||||
*
|
||||
|
|
|
@ -36,6 +36,9 @@ set( KIMATH_SRCS
|
|||
geometry/test_shape_poly_set_iterator.cpp
|
||||
geometry/test_poly_grid_partition.cpp
|
||||
geometry/test_shape_line_chain.cpp
|
||||
|
||||
math/test_vector2.cpp
|
||||
math/test_vector3.cpp
|
||||
)
|
||||
|
||||
add_executable( qa_kimath ${KIMATH_SRCS} )
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020 KiCad Developers, see CHANGELOG.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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test suite for KiCad math code.
|
||||
*/
|
||||
|
||||
#include <unit_test_utils/unit_test_utils.h>
|
||||
|
||||
// Code under test
|
||||
#include <math/vector2d.h>
|
||||
|
||||
/**
|
||||
* Declare the test suite
|
||||
*/
|
||||
BOOST_AUTO_TEST_SUITE( VECTOR2TESTS )
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_cross_product, *boost::unit_test::tolerance( 0.000001 ) )
|
||||
{
|
||||
VECTOR2I v1(0, 1);
|
||||
VECTOR2I v2(1, 0);
|
||||
|
||||
BOOST_CHECK( v2.Cross( v1 ) == 1 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_dot_product, *boost::unit_test::tolerance( 0.000001 ) )
|
||||
{
|
||||
VECTOR2I v1( 0, 1 );
|
||||
VECTOR2I v2( 1, 0 );
|
||||
|
||||
BOOST_CHECK( v2.Dot( v1 ) == 0 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020 KiCad Developers, see CHANGELOG.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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test suite for KiCad math code.
|
||||
*/
|
||||
|
||||
#include <unit_test_utils/unit_test_utils.h>
|
||||
|
||||
// Code under test
|
||||
#include <math/vector3.h>
|
||||
|
||||
/**
|
||||
* Declare the test suite
|
||||
*/
|
||||
BOOST_AUTO_TEST_SUITE( VECTOR3TESTS )
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_cross_product, *boost::unit_test::tolerance( 0.000001 ) )
|
||||
{
|
||||
VECTOR3I v1( 0, 1, 2 );
|
||||
VECTOR3I v2( 2, 1, 0 );
|
||||
|
||||
BOOST_CHECK( v1.Cross( v2 ) == VECTOR3I(-2, 4 ,-2) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_dot_product, *boost::unit_test::tolerance( 0.000001 ) )
|
||||
{
|
||||
VECTOR3I v1( 0, 1, 2 );
|
||||
VECTOR3I v2( 2, 1, 0 );
|
||||
|
||||
BOOST_CHECK( v1.Dot( v2 ) == 1 );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
Loading…
Reference in New Issue