kicad/libs/kimath/include/geometry/shape_compound.h

169 lines
4.6 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016-2020 CERN
* Copyright (C) 2021-2022 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
*/
#ifndef __SHAPE_COMPOUND_H
#define __SHAPE_COMPOUND_H
#include <geometry/shape.h>
#include <math/vector2d.h>
#include <math/box2.h>
#include <list>
#include <vector>
#include <memory>
#include "eda_angle.h"
class SHAPE_SIMPLE;
class SHAPE_COMPOUND : public SHAPE
{
public:
SHAPE_COMPOUND() :
SHAPE( SH_COMPOUND ),
m_dirty( true )
{
}
SHAPE_COMPOUND( const std::vector<SHAPE*>& aShapes );
SHAPE_COMPOUND( const SHAPE_COMPOUND& aOther );
~SHAPE_COMPOUND();
SHAPE_COMPOUND* Clone() const override;
const std::string Format( bool aCplusPlus = true ) const override;
bool Collide( const SEG& aSeg, int aClearance = 0, int* aActual = nullptr,
VECTOR2I* aLocation = nullptr ) const override;
bool Collide( const SHAPE* aShape, int aClearance, VECTOR2I* aMTV ) const override
{
return SHAPE::Collide( aShape, aClearance, aMTV );
}
bool Collide( const SHAPE* aShape, int aClearance = 0, int* aActual = nullptr,
VECTOR2I* aLocation = nullptr ) const override
{
return SHAPE::Collide( aShape, aClearance, aActual, aLocation );
}
const std::vector<SHAPE*>& Shapes() const
{
return m_shapes;
}
const BOX2I BBox( int aClearance = 0 ) const override;
using SHAPE::Distance;
int Distance( const SEG& aSeg ) const;
void Move( const VECTOR2I& aVector ) override;
void AddShape( SHAPE* aShape )
{
// Don't make clients deal with nested SHAPE_COMPOUNDs
if( dynamic_cast<SHAPE_COMPOUND*>( aShape ) )
{
std::vector<const SHAPE*> subshapes;
aShape->GetIndexableSubshapes( subshapes );
for( const SHAPE* subshape : subshapes )
m_shapes.push_back( subshape->Clone() );
delete aShape;
}
else
{
m_shapes.push_back( aShape );
}
m_dirty = true;
}
void AddShape( std::shared_ptr<SHAPE> aShape )
{
// Don't make clients deal with nested SHAPE_COMPOUNDs
if( dynamic_cast<SHAPE_COMPOUND*>( aShape.get() ) )
{
std::vector<const SHAPE*> subshapes;
aShape->GetIndexableSubshapes( subshapes );
for( const SHAPE* subshape : subshapes )
m_shapes.push_back( subshape->Clone() );
}
else
{
m_shapes.push_back( aShape->Clone() );
}
m_dirty = true;
}
bool Empty() const
{
return m_shapes.empty();
}
int Size() const
{
return (int) m_shapes.size();
}
void Rotate( const EDA_ANGLE& aAngle, const VECTOR2I& aCenter = { 0, 0 } ) override;
bool IsSolid() const override;
SHAPE* UniqueSubshape() const
{
return m_shapes.size() != 1 ? nullptr : m_shapes[0];
}
virtual bool HasIndexableSubshapes() const override
{
return true;
}
virtual size_t GetIndexableSubshapeCount() const override
{
return m_shapes.size();
}
virtual void GetIndexableSubshapes( std::vector<const SHAPE*>& aSubshapes ) const override
{
aSubshapes.clear();
aSubshapes.reserve( m_shapes.size() );
std::copy( m_shapes.begin(), m_shapes.end(), std::back_inserter( aSubshapes ) );
}
void TransformToPolygon( SHAPE_POLY_SET& aBuffer, int aError,
ERROR_LOC aErrorLoc ) const override;
private:
BOX2I m_cachedBBox;
bool m_dirty;
std::vector<SHAPE*> m_shapes;
};
#endif // __SHAPE_COMPOUND_H