geometry: derive SHAPE_LINE_CHAIN, SHAPE_SIMPLE and SHAPE_POLY_SET::TRIANGULATED_POLYGON::TRI from a common base class allowing to simplify collision detection
This commit is contained in:
parent
eb6e1c4f90
commit
74623b8c98
|
@ -30,6 +30,7 @@
|
|||
#include <math/vector2d.h>
|
||||
#include <math/box2.h>
|
||||
|
||||
class SHAPE_LINE_CHAIN;
|
||||
|
||||
/**
|
||||
* Enum SHAPE_TYPE
|
||||
|
@ -46,7 +47,8 @@ enum SHAPE_TYPE
|
|||
SH_POLY_SET, ///> set of polygons (with holes, etc.)
|
||||
SH_COMPOUND, ///> compound shape, consisting of multiple simple shapes
|
||||
SH_ARC, ///> circular arc
|
||||
SH_NULL ///> empty shape (no shape...)
|
||||
SH_NULL, ///> empty shape (no shape...),
|
||||
SH_POLY_SET_TRIANGLE ///> a single triangle belonging to a POLY_SET triangulation
|
||||
};
|
||||
|
||||
static inline wxString SHAPE_TYPE_asString( SHAPE_TYPE a )
|
||||
|
@ -62,22 +64,15 @@ static inline wxString SHAPE_TYPE_asString( SHAPE_TYPE a )
|
|||
case SH_COMPOUND: return "SH_COMPOUND";
|
||||
case SH_ARC: return "SH_ARC";
|
||||
case SH_NULL: return "SH_NULL";
|
||||
case SH_POLY_SET_TRIANGLE: return "SH_POLY_SET_TRIANGLE";
|
||||
}
|
||||
|
||||
return wxEmptyString; // Just to quiet GCC.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* SHAPE
|
||||
*
|
||||
* Represents an abstract shape on 2D plane.
|
||||
*/
|
||||
class SHAPE
|
||||
class SHAPE_BASE
|
||||
{
|
||||
protected:
|
||||
typedef VECTOR2I::extended_type ecoord;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -85,11 +80,11 @@ public:
|
|||
* Creates an empty shape of type aType
|
||||
*/
|
||||
|
||||
SHAPE( SHAPE_TYPE aType ) : m_type( aType )
|
||||
SHAPE_BASE( SHAPE_TYPE aType ) : m_type( aType )
|
||||
{}
|
||||
|
||||
// Destructor
|
||||
virtual ~SHAPE()
|
||||
virtual ~SHAPE_BASE()
|
||||
{}
|
||||
|
||||
/**
|
||||
|
@ -103,6 +98,45 @@ public:
|
|||
return m_type;
|
||||
}
|
||||
|
||||
virtual bool HasIndexableSubshapes() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual size_t GetIndexableSubshapeCount() { return 0; }
|
||||
|
||||
virtual void GetIndexableSubshape( SHAPE_BASE& aSubshape ) const {};
|
||||
|
||||
protected:
|
||||
///> type of our shape
|
||||
SHAPE_TYPE m_type;
|
||||
};
|
||||
|
||||
/**
|
||||
* SHAPE
|
||||
*
|
||||
* Represents an abstract shape on 2D plane.
|
||||
*/
|
||||
class SHAPE : public SHAPE_BASE
|
||||
{
|
||||
protected:
|
||||
typedef VECTOR2I::extended_type ecoord;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Creates an empty shape of type aType
|
||||
*/
|
||||
|
||||
SHAPE( SHAPE_TYPE aType ) : SHAPE_BASE( aType )
|
||||
{}
|
||||
|
||||
// Destructor
|
||||
virtual ~SHAPE()
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Function Clone()
|
||||
*
|
||||
|
@ -202,11 +236,82 @@ public:
|
|||
virtual bool Parse( std::stringstream& aStream );
|
||||
|
||||
virtual const std::string Format( ) const;
|
||||
|
||||
protected:
|
||||
///> type of our shape
|
||||
SHAPE_TYPE m_type;
|
||||
};
|
||||
|
||||
|
||||
class SHAPE_LINE_CHAIN_BASE : public SHAPE
|
||||
{
|
||||
public:
|
||||
SHAPE_LINE_CHAIN_BASE( SHAPE_TYPE aType ) : SHAPE( aType )
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
virtual ~SHAPE_LINE_CHAIN_BASE()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Function Collide()
|
||||
*
|
||||
* Checks if point aP lies closer to us than aClearance.
|
||||
* @param aP the point to check for collisions with
|
||||
* @param aClearance minimum distance that does not qualify as a collision.
|
||||
* @param aActual an optional pointer to an int to store the actual distance in the event
|
||||
* of a collision.
|
||||
* @return true, when a collision has been found
|
||||
*/
|
||||
virtual bool Collide( const VECTOR2I& aP, int aClearance = 0, int* aActual = nullptr ) const override;
|
||||
|
||||
/**
|
||||
* Function Collide()
|
||||
*
|
||||
* Checks if segment aSeg lies closer to us than aClearance.
|
||||
* @param aSeg the segment to check for collisions with
|
||||
* @param aClearance minimum distance that does not qualify as a collision.
|
||||
* @param aActual an optional pointer to an int to store the actual distance in the event
|
||||
* of a collision.
|
||||
* @return true, when a collision has been found
|
||||
*/
|
||||
|
||||
virtual bool Collide( const SEG& aSeg, int aClearance = 0, int* aActual = nullptr ) const override;
|
||||
SEG::ecoord SquaredDistance( const VECTOR2I& aP, bool aOutlineOnly = false ) const;
|
||||
|
||||
/**
|
||||
* Function PointInside()
|
||||
*
|
||||
* Checks if point aP lies inside a polygon (any type) defined by the line chain.
|
||||
* For closed shapes only.
|
||||
* @param aPt point to check
|
||||
* @param aUseBBoxCache gives better peformance if the bounding box caches have been
|
||||
* generated.
|
||||
* @return true if the point is inside the shape (edge is not treated as being inside).
|
||||
*/
|
||||
bool PointInside( const VECTOR2I& aPt, int aAccuracy = 0, bool aUseBBoxCache = false ) const;
|
||||
|
||||
/**
|
||||
* Function PointOnEdge()
|
||||
*
|
||||
* Checks if point aP lies on an edge or vertex of the line chain.
|
||||
* @param aP point to check
|
||||
* @return true if the point lies on the edge.
|
||||
*/
|
||||
bool PointOnEdge( const VECTOR2I& aP, int aAccuracy = 0 ) const;
|
||||
|
||||
/**
|
||||
* Function EdgeContainingPoint()
|
||||
*
|
||||
* Checks if point aP lies on an edge or vertex of the line chain.
|
||||
* @param aP point to check
|
||||
* @return index of the first edge containing the point, otherwise negative
|
||||
*/
|
||||
int EdgeContainingPoint( const VECTOR2I& aP, int aAccuracy = 0 ) const;
|
||||
|
||||
virtual const VECTOR2I GetPoint( int aIndex ) const = 0;
|
||||
virtual const SEG GetSegment( int aIndex ) const = 0;
|
||||
virtual size_t GetPointCount() const = 0;
|
||||
virtual size_t GetSegmentCount() const = 0;
|
||||
virtual bool IsClosed() const = 0;
|
||||
};
|
||||
|
||||
#endif // __SHAPE_H
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
*
|
||||
* SHAPE_LINE_CHAIN class shall not be used for polygons!
|
||||
*/
|
||||
class SHAPE_LINE_CHAIN : public SHAPE
|
||||
class SHAPE_LINE_CHAIN : public SHAPE_LINE_CHAIN_BASE
|
||||
{
|
||||
private:
|
||||
typedef std::vector<VECTOR2I>::iterator point_iter;
|
||||
|
@ -99,7 +99,7 @@ public:
|
|||
* Constructor
|
||||
* Initializes an empty line chain.
|
||||
*/
|
||||
SHAPE_LINE_CHAIN() : SHAPE( SH_LINE_CHAIN ), m_closed( false ), m_width( 0 )
|
||||
SHAPE_LINE_CHAIN() : SHAPE_LINE_CHAIN_BASE( SH_LINE_CHAIN ), m_closed( false ), m_width( 0 )
|
||||
{}
|
||||
|
||||
/**
|
||||
|
@ -107,7 +107,7 @@ public:
|
|||
*/
|
||||
|
||||
SHAPE_LINE_CHAIN( const SHAPE_LINE_CHAIN& aShape )
|
||||
: SHAPE( SH_LINE_CHAIN ),
|
||||
: SHAPE_LINE_CHAIN_BASE( SH_LINE_CHAIN ),
|
||||
m_points( aShape.m_points ),
|
||||
m_shapes( aShape.m_shapes ),
|
||||
m_arcs( aShape.m_arcs ),
|
||||
|
@ -119,7 +119,7 @@ public:
|
|||
SHAPE_LINE_CHAIN( const std::vector<int>& aV);
|
||||
|
||||
SHAPE_LINE_CHAIN( const std::vector<wxPoint>& aV, bool aClosed = false )
|
||||
: SHAPE( SH_LINE_CHAIN ), m_closed( aClosed ), m_width( 0 )
|
||||
: SHAPE_LINE_CHAIN_BASE( SH_LINE_CHAIN ), m_closed( aClosed ), m_width( 0 )
|
||||
{
|
||||
m_points.reserve( aV.size() );
|
||||
|
||||
|
@ -130,14 +130,14 @@ public:
|
|||
}
|
||||
|
||||
SHAPE_LINE_CHAIN( const std::vector<VECTOR2I>& aV, bool aClosed = false )
|
||||
: SHAPE( SH_LINE_CHAIN ), m_closed( aClosed ), m_width( 0 )
|
||||
: SHAPE_LINE_CHAIN_BASE( SH_LINE_CHAIN ), m_closed( aClosed ), m_width( 0 )
|
||||
{
|
||||
m_points = aV;
|
||||
m_shapes = std::vector<ssize_t>( aV.size(), ssize_t( SHAPE_IS_PT ) );
|
||||
}
|
||||
|
||||
SHAPE_LINE_CHAIN( const SHAPE_ARC& aArc, bool aClosed = false )
|
||||
: SHAPE( SH_LINE_CHAIN ),
|
||||
: SHAPE_LINE_CHAIN_BASE( SH_LINE_CHAIN ),
|
||||
m_closed( aClosed ),
|
||||
m_width( 0 )
|
||||
{
|
||||
|
@ -147,7 +147,7 @@ public:
|
|||
}
|
||||
|
||||
SHAPE_LINE_CHAIN( const ClipperLib::Path& aPath ) :
|
||||
SHAPE( SH_LINE_CHAIN ),
|
||||
SHAPE_LINE_CHAIN_BASE( SH_LINE_CHAIN ),
|
||||
m_closed( true ),
|
||||
m_width( 0 )
|
||||
{
|
||||
|
@ -194,7 +194,7 @@ public:
|
|||
*
|
||||
* @return aClosed: true, when our line is closed.
|
||||
*/
|
||||
bool IsClosed() const
|
||||
bool IsClosed() const override
|
||||
{
|
||||
return m_closed;
|
||||
}
|
||||
|
@ -372,30 +372,6 @@ public:
|
|||
return m_bbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function Collide()
|
||||
*
|
||||
* Checks if point aP lies closer to us than aClearance.
|
||||
* @param aP the point to check for collisions with
|
||||
* @param aClearance minimum distance that does not qualify as a collision.
|
||||
* @param aActual an optional pointer to an int to store the actual distance in the event
|
||||
* of a collision.
|
||||
* @return true, when a collision has been found
|
||||
*/
|
||||
bool Collide( const VECTOR2I& aP, int aClearance = 0, int* aActual = nullptr ) const override;
|
||||
|
||||
/**
|
||||
* Function Collide()
|
||||
*
|
||||
* Checks if segment aSeg lies closer to us than aClearance.
|
||||
* @param aSeg the segment to check for collisions with
|
||||
* @param aClearance minimum distance that does not qualify as a collision.
|
||||
* @param aActual an optional pointer to an int to store the actual distance in the event
|
||||
* of a collision.
|
||||
* @return true, when a collision has been found
|
||||
*/
|
||||
bool Collide( const SEG& aSeg, int aClearance = 0, int* aActual = nullptr ) const override;
|
||||
|
||||
/**
|
||||
* Function Distance()
|
||||
*
|
||||
|
@ -404,7 +380,6 @@ public:
|
|||
* @return minimum distance.
|
||||
*/
|
||||
int Distance( const VECTOR2I& aP, bool aOutlineOnly = false ) const;
|
||||
SEG::ecoord SquaredDistance( const VECTOR2I& aP, bool aOutlineOnly = false ) const;
|
||||
|
||||
/**
|
||||
* Function Reverse()
|
||||
|
@ -600,37 +575,6 @@ public:
|
|||
*/
|
||||
int PathLength( const VECTOR2I& aP ) const;
|
||||
|
||||
/**
|
||||
* Function PointInside()
|
||||
*
|
||||
* Checks if point aP lies inside a polygon (any type) defined by the line chain.
|
||||
* For closed shapes only.
|
||||
* @param aPt point to check
|
||||
* @param aUseBBoxCache gives better peformance if the bounding box caches have been
|
||||
* generated.
|
||||
* @return true if the point is inside the shape (edge is not treated as being inside).
|
||||
*/
|
||||
bool PointInside( const VECTOR2I& aPt, int aAccuracy = 0, bool aUseBBoxCache = false ) const;
|
||||
|
||||
|
||||
/**
|
||||
* Function PointOnEdge()
|
||||
*
|
||||
* Checks if point aP lies on an edge or vertex of the line chain.
|
||||
* @param aP point to check
|
||||
* @return true if the point lies on the edge.
|
||||
*/
|
||||
bool PointOnEdge( const VECTOR2I& aP, int aAccuracy = 0 ) const;
|
||||
|
||||
/**
|
||||
* Function EdgeContainingPoint()
|
||||
*
|
||||
* Checks if point aP lies on an edge or vertex of the line chain.
|
||||
* @param aP point to check
|
||||
* @return index of the first edge containing the point, otherwise negative
|
||||
*/
|
||||
int EdgeContainingPoint( const VECTOR2I& aP, int aAccuracy = 0 ) const;
|
||||
|
||||
/**
|
||||
* Function CheckClearance()
|
||||
*
|
||||
|
@ -775,6 +719,11 @@ public:
|
|||
return aSegment < m_shapes.size() && m_shapes[aSegment] != SHAPE_IS_PT;
|
||||
}
|
||||
|
||||
virtual const VECTOR2I GetPoint( int aIndex ) const override { return CPoint(aIndex); }
|
||||
virtual const SEG GetSegment( int aIndex ) const override { return CSegment(aIndex); }
|
||||
virtual size_t GetPointCount() const override { return PointCount(); }
|
||||
virtual size_t GetSegmentCount() const override { return SegmentCount(); }
|
||||
|
||||
private:
|
||||
|
||||
constexpr static ssize_t SHAPE_IS_PT = -1;
|
||||
|
|
|
@ -71,13 +71,64 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
class TRIANGULATED_POLYGON
|
||||
{
|
||||
public:
|
||||
struct TRI
|
||||
struct TRI : public SHAPE_LINE_CHAIN_BASE
|
||||
{
|
||||
TRI( int _a = 0, int _b = 0, int _c = 0 ) : a( _a ), b( _b ), c( _c )
|
||||
TRI( int _a = 0, int _b = 0, int _c = 0, TRIANGULATED_POLYGON* aParent = nullptr ) :
|
||||
SHAPE_LINE_CHAIN_BASE( SH_POLY_SET_TRIANGLE ),
|
||||
a( _a ), b( _b ), c( _c ), parent( aParent )
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Rotate( double aAngle, const VECTOR2I& aCenter = { 0, 0 } ) override {};
|
||||
|
||||
virtual void Move( const VECTOR2I& aVector ) override {};
|
||||
|
||||
virtual bool IsSolid() const override { return true; }
|
||||
|
||||
virtual bool IsClosed() const override { return true; }
|
||||
|
||||
virtual const BOX2I BBox( int aClearance = 0 ) const override
|
||||
{
|
||||
BOX2I bbox( parent->m_vertices[a] );
|
||||
bbox.Merge( parent->m_vertices[b] );
|
||||
bbox.Merge( parent->m_vertices[c] );
|
||||
|
||||
if( aClearance != 0 )
|
||||
bbox.Inflate( aClearance );
|
||||
|
||||
return bbox;
|
||||
}
|
||||
|
||||
virtual const VECTOR2I GetPoint( int aIndex ) const override
|
||||
{
|
||||
switch(aIndex)
|
||||
{
|
||||
case 0: return parent->m_vertices[a];
|
||||
case 1: return parent->m_vertices[b];
|
||||
case 2: return parent->m_vertices[c];
|
||||
default: assert(false);
|
||||
}
|
||||
return VECTOR2I(0, 0);
|
||||
}
|
||||
|
||||
virtual const SEG GetSegment( int aIndex ) const override
|
||||
{
|
||||
switch(aIndex)
|
||||
{
|
||||
case 0: return SEG( parent->m_vertices[a], parent->m_vertices[b] );
|
||||
case 1: return SEG( parent->m_vertices[b], parent->m_vertices[c] );
|
||||
case 2: return SEG( parent->m_vertices[c], parent->m_vertices[a] );
|
||||
default: assert(false);
|
||||
}
|
||||
return SEG();
|
||||
}
|
||||
|
||||
virtual size_t GetPointCount() const override { return 3; }
|
||||
virtual size_t GetSegmentCount() const override { return 3; }
|
||||
|
||||
|
||||
int a, b, c;
|
||||
TRIANGULATED_POLYGON* parent;
|
||||
};
|
||||
|
||||
void Clear()
|
||||
|
@ -101,7 +152,7 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
|
||||
void AddTriangle( int a, int b, int c )
|
||||
{
|
||||
m_triangles.emplace_back( a, b, c );
|
||||
m_triangles.emplace_back( a, b, c, this );
|
||||
}
|
||||
|
||||
void AddVertex( const VECTOR2I& aP )
|
||||
|
|
|
@ -39,7 +39,8 @@
|
|||
* Internally the vertices are held in a SHAPE_LINE_CHAIN, please note that
|
||||
* there is a "virtual" line segment between the last and first vertex.
|
||||
*/
|
||||
class SHAPE_SIMPLE : public SHAPE
|
||||
|
||||
class SHAPE_SIMPLE : public SHAPE_LINE_CHAIN_BASE
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
@ -47,20 +48,20 @@ public:
|
|||
* Creates an empty polygon
|
||||
*/
|
||||
SHAPE_SIMPLE() :
|
||||
SHAPE( SH_SIMPLE )
|
||||
SHAPE_LINE_CHAIN_BASE( SH_SIMPLE )
|
||||
{
|
||||
m_points.SetClosed( true );
|
||||
}
|
||||
|
||||
SHAPE_SIMPLE( const SHAPE_LINE_CHAIN& aPoly ) :
|
||||
SHAPE( SH_SIMPLE ),
|
||||
SHAPE_LINE_CHAIN_BASE( SH_SIMPLE ),
|
||||
m_points( aPoly )
|
||||
{
|
||||
m_points.SetClosed( true );
|
||||
}
|
||||
|
||||
SHAPE_SIMPLE( const SHAPE_SIMPLE& aOther ) :
|
||||
SHAPE( SH_SIMPLE ), m_points( aOther.m_points )
|
||||
SHAPE_LINE_CHAIN_BASE( SH_SIMPLE ), m_points( aOther.m_points )
|
||||
{}
|
||||
|
||||
SHAPE* Clone() const override
|
||||
|
@ -179,6 +180,16 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
virtual const VECTOR2I GetPoint( int aIndex ) const override { return m_points.CPoint(aIndex); }
|
||||
virtual const SEG GetSegment( int aIndex ) const override { return m_points.CSegment(aIndex); }
|
||||
virtual size_t GetPointCount() const override { return m_points.PointCount(); }
|
||||
virtual size_t GetSegmentCount() const override { return m_points.SegmentCount(); }
|
||||
|
||||
bool IsClosed() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// vertices
|
||||
SHAPE_LINE_CHAIN m_points;
|
||||
|
|
|
@ -162,15 +162,15 @@ static VECTOR2I pushoutForce( const SHAPE_CIRCLE& aA, const SEG& aB, int aCleara
|
|||
return f;
|
||||
}
|
||||
|
||||
|
||||
static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_LINE_CHAIN& aB, int aClearance,
|
||||
#if 0
|
||||
static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_LINE_CHAIN_BASE& aB, int aClearance,
|
||||
int* aActual, VECTOR2I* aMTV )
|
||||
{
|
||||
bool collided = false;
|
||||
|
||||
for( int s = 0; s < aB.SegmentCount(); s++ )
|
||||
for( int s = 0; s < aB.GetSegmentCount(); s++ )
|
||||
{
|
||||
if( aA.Collide( aB.CSegment( s ), aClearance, aActual ) )
|
||||
if( aA.Collide( aB.GetSegment( s ), aClearance, aActual ) )
|
||||
{
|
||||
collided = true;
|
||||
break;
|
||||
|
@ -185,9 +185,9 @@ static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_LINE_CHAIN& aB,
|
|||
SHAPE_CIRCLE cmoved( aA );
|
||||
VECTOR2I f_total( 0, 0 );
|
||||
|
||||
for( int s = 0; s < aB.SegmentCount(); s++ )
|
||||
for( int s = 0; s < aB.GetSegmentCount(); s++ )
|
||||
{
|
||||
VECTOR2I f = pushoutForce( cmoved, aB.CSegment( s ), aClearance );
|
||||
VECTOR2I f = pushoutForce( cmoved, aB.GetSegment( s ), aClearance );
|
||||
cmoved.SetCenter( cmoved.GetCenter() + f );
|
||||
f_total += f;
|
||||
}
|
||||
|
@ -197,13 +197,13 @@ static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_LINE_CHAIN& aB,
|
|||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_SIMPLE& aB, int aClearance,
|
||||
static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_LINE_CHAIN_BASE& aB, int aClearance,
|
||||
int* aActual, VECTOR2I* aMTV )
|
||||
{
|
||||
int min_dist = aClearance + aA.GetRadius();
|
||||
ecoord dist_sq = aB.Vertices().SquaredDistance( aA.GetCenter() );
|
||||
ecoord dist_sq = aB.SquaredDistance( aA.GetCenter() );
|
||||
|
||||
if( dist_sq > (ecoord) min_dist * min_dist )
|
||||
return false;
|
||||
|
@ -216,9 +216,9 @@ static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_SIMPLE& aB, int
|
|||
SHAPE_CIRCLE cmoved( aA );
|
||||
VECTOR2I f_total( 0, 0 );
|
||||
|
||||
for( int s = 0; s < aB.Vertices().SegmentCount(); s++ )
|
||||
for( int s = 0; s < aB.GetSegmentCount(); s++ )
|
||||
{
|
||||
VECTOR2I f = pushoutForce( cmoved, aB.Vertices().CSegment( s ), aClearance );
|
||||
VECTOR2I f = pushoutForce( cmoved, aB.GetSegment( s ), aClearance );
|
||||
cmoved.SetCenter( cmoved.GetCenter() + f );
|
||||
f_total += f;
|
||||
}
|
||||
|
@ -242,14 +242,15 @@ static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_SEGMENT& aSeg, i
|
|||
}
|
||||
|
||||
|
||||
static inline bool Collide( const SHAPE_LINE_CHAIN& aA, const SHAPE_LINE_CHAIN& aB, int aClearance,
|
||||
static inline bool Collide( const SHAPE_LINE_CHAIN_BASE& aA, const SHAPE_LINE_CHAIN_BASE& aB, int aClearance,
|
||||
int* aActual, VECTOR2I* aMTV )
|
||||
{
|
||||
// TODO: why doesn't this handle MTV?
|
||||
// TODO: worse, why this doesn't handle closed shapes?
|
||||
|
||||
for( int i = 0; i < aB.SegmentCount(); i++ )
|
||||
for( int i = 0; i < aB.GetSegmentCount(); i++ )
|
||||
{
|
||||
if( aA.Collide( aB.CSegment( i ), aClearance, aActual ) )
|
||||
if( aA.Collide( aB.GetSegment( i ), aClearance, aActual ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -257,29 +258,15 @@ static inline bool Collide( const SHAPE_LINE_CHAIN& aA, const SHAPE_LINE_CHAIN&
|
|||
}
|
||||
|
||||
|
||||
static inline bool Collide( const SHAPE_LINE_CHAIN& aA, const SHAPE_SIMPLE& aB, int aClearance,
|
||||
int* aActual, VECTOR2I* aMTV )
|
||||
{
|
||||
return Collide( aA, aB.Vertices(), aClearance, aActual, aMTV );
|
||||
}
|
||||
|
||||
|
||||
static inline bool Collide( const SHAPE_SIMPLE& aA, const SHAPE_SIMPLE& aB, int aClearance,
|
||||
int* aActual, VECTOR2I* aMTV )
|
||||
{
|
||||
return Collide( aA.Vertices(), aB.Vertices(), aClearance, aActual, aMTV );
|
||||
}
|
||||
|
||||
|
||||
static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_LINE_CHAIN& aB, int aClearance,
|
||||
static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_LINE_CHAIN_BASE& aB, int aClearance,
|
||||
int* aActual, VECTOR2I* aMTV )
|
||||
{
|
||||
int minActual = INT_MAX;
|
||||
int actual;
|
||||
|
||||
for( int s = 0; s < aB.SegmentCount(); s++ )
|
||||
for( int s = 0; s < aB.GetSegmentCount(); s++ )
|
||||
{
|
||||
if( aA.Collide( aB.CSegment( s ), aClearance, &actual ) )
|
||||
if( aA.Collide( aB.GetSegment( s ), aClearance, &actual ) )
|
||||
{
|
||||
minActual = std::min( minActual, actual );
|
||||
|
||||
|
@ -298,13 +285,6 @@ static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_LINE_CHAIN& aB, in
|
|||
}
|
||||
|
||||
|
||||
static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_SIMPLE& aB, int aClearance,
|
||||
int* aActual, VECTOR2I* aMTV )
|
||||
{
|
||||
return Collide( aA, aB.Vertices(), aClearance, aActual, aMTV );
|
||||
}
|
||||
|
||||
|
||||
static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_SEGMENT& aSeg, int aClearance,
|
||||
int* aActual, VECTOR2I* aMTV )
|
||||
{
|
||||
|
@ -343,7 +323,7 @@ static inline bool Collide( const SHAPE_SEGMENT& aA, const SHAPE_SEGMENT& aB, in
|
|||
}
|
||||
|
||||
|
||||
static inline bool Collide( const SHAPE_LINE_CHAIN& aA, const SHAPE_SEGMENT& aB, int aClearance,
|
||||
static inline bool Collide( const SHAPE_LINE_CHAIN_BASE& aA, const SHAPE_SEGMENT& aB, int aClearance,
|
||||
int* aActual, VECTOR2I* aMTV )
|
||||
{
|
||||
int actual;
|
||||
|
@ -362,12 +342,6 @@ static inline bool Collide( const SHAPE_LINE_CHAIN& aA, const SHAPE_SEGMENT& aB,
|
|||
}
|
||||
|
||||
|
||||
static inline bool Collide( const SHAPE_SIMPLE& aA, const SHAPE_SEGMENT& aB, int aClearance,
|
||||
int* aActual, VECTOR2I* aMTV )
|
||||
{
|
||||
return Collide( aA.Vertices(), aB, aClearance, aActual, aMTV );
|
||||
}
|
||||
|
||||
static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_RECT& aB, int aClearance,
|
||||
int* aActual, VECTOR2I* aMTV )
|
||||
{
|
||||
|
@ -407,12 +381,12 @@ static inline bool Collide( const SHAPE_ARC& aA, const SHAPE_SEGMENT& aB, int aC
|
|||
return Collide( lc, aB, aClearance, aActual, aMTV );
|
||||
}
|
||||
|
||||
static inline bool Collide( const SHAPE_ARC& aA, const SHAPE_SIMPLE& aB, int aClearance,
|
||||
static inline bool Collide( const SHAPE_ARC& aA, const SHAPE_LINE_CHAIN_BASE& aB, int aClearance,
|
||||
int* aActual, VECTOR2I* aMTV )
|
||||
{
|
||||
const auto lc = aA.ConvertToPolyline();
|
||||
|
||||
return Collide( lc, aB.Vertices(), aClearance, aActual, aMTV );
|
||||
return Collide( lc, aB, aClearance, aActual, aMTV );
|
||||
}
|
||||
|
||||
static inline bool Collide( const SHAPE_ARC& aA, const SHAPE_ARC& aB, int aClearance,
|
||||
|
@ -454,6 +428,7 @@ static bool collideSingleShapes( const SHAPE* aA, const SHAPE* aB, int aClearanc
|
|||
{
|
||||
case SH_NULL:
|
||||
return false;
|
||||
|
||||
case SH_RECT:
|
||||
switch( aB->Type() )
|
||||
{
|
||||
|
@ -470,7 +445,8 @@ static bool collideSingleShapes( const SHAPE* aA, const SHAPE* aB, int aClearanc
|
|||
return CollCase<SHAPE_RECT, SHAPE_SEGMENT>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
||||
case SH_SIMPLE:
|
||||
return CollCase<SHAPE_RECT, SHAPE_SIMPLE>( aA, aB, aClearance, aActual, aMTV );
|
||||
case SH_POLY_SET_TRIANGLE:
|
||||
return CollCase<SHAPE_RECT, SHAPE_LINE_CHAIN_BASE>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
||||
case SH_ARC:
|
||||
return CollCaseReversed<SHAPE_RECT, SHAPE_ARC>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
@ -499,7 +475,8 @@ static bool collideSingleShapes( const SHAPE* aA, const SHAPE* aB, int aClearanc
|
|||
return CollCase<SHAPE_CIRCLE, SHAPE_SEGMENT>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
||||
case SH_SIMPLE:
|
||||
return CollCase<SHAPE_CIRCLE, SHAPE_SIMPLE>( aA, aB, aClearance, aActual, aMTV );
|
||||
case SH_POLY_SET_TRIANGLE:
|
||||
return CollCase<SHAPE_CIRCLE, SHAPE_LINE_CHAIN_BASE>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
||||
case SH_ARC:
|
||||
return CollCaseReversed<SHAPE_CIRCLE, SHAPE_ARC>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
@ -528,7 +505,8 @@ static bool collideSingleShapes( const SHAPE* aA, const SHAPE* aB, int aClearanc
|
|||
return CollCase<SHAPE_LINE_CHAIN, SHAPE_SEGMENT>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
||||
case SH_SIMPLE:
|
||||
return CollCase<SHAPE_LINE_CHAIN, SHAPE_SIMPLE>( aA, aB, aClearance, aActual, aMTV );
|
||||
case SH_POLY_SET_TRIANGLE:
|
||||
return CollCase<SHAPE_LINE_CHAIN, SHAPE_LINE_CHAIN_BASE>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
||||
case SH_ARC:
|
||||
return CollCaseReversed<SHAPE_LINE_CHAIN, SHAPE_ARC>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
@ -557,7 +535,8 @@ static bool collideSingleShapes( const SHAPE* aA, const SHAPE* aB, int aClearanc
|
|||
return CollCase<SHAPE_SEGMENT, SHAPE_SEGMENT>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
||||
case SH_SIMPLE:
|
||||
return CollCase<SHAPE_SIMPLE, SHAPE_SEGMENT>( aB, aA, aClearance, aActual, aMTV );
|
||||
case SH_POLY_SET_TRIANGLE:
|
||||
return CollCase<SHAPE_LINE_CHAIN_BASE, SHAPE_SEGMENT>( aB, aA, aClearance, aActual, aMTV );
|
||||
|
||||
case SH_ARC:
|
||||
return CollCaseReversed<SHAPE_SEGMENT, SHAPE_ARC>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
@ -571,25 +550,27 @@ static bool collideSingleShapes( const SHAPE* aA, const SHAPE* aB, int aClearanc
|
|||
break;
|
||||
|
||||
case SH_SIMPLE:
|
||||
case SH_POLY_SET_TRIANGLE:
|
||||
switch( aB->Type() )
|
||||
{
|
||||
case SH_RECT:
|
||||
return CollCase<SHAPE_RECT, SHAPE_SIMPLE>( aB, aA, aClearance, aActual, aMTV );
|
||||
return CollCase<SHAPE_RECT, SHAPE_LINE_CHAIN_BASE>( aB, aA, aClearance, aActual, aMTV );
|
||||
|
||||
case SH_CIRCLE:
|
||||
return CollCase<SHAPE_CIRCLE, SHAPE_SIMPLE>( aB, aA, aClearance, aActual, aMTV );
|
||||
return CollCase<SHAPE_CIRCLE, SHAPE_LINE_CHAIN_BASE>( aB, aA, aClearance, aActual, aMTV );
|
||||
|
||||
case SH_LINE_CHAIN:
|
||||
return CollCase<SHAPE_LINE_CHAIN, SHAPE_SIMPLE>( aB, aA, aClearance, aActual, aMTV );
|
||||
return CollCase<SHAPE_LINE_CHAIN, SHAPE_LINE_CHAIN_BASE>( aB, aA, aClearance, aActual, aMTV );
|
||||
|
||||
case SH_SEGMENT:
|
||||
return CollCase<SHAPE_SIMPLE, SHAPE_SEGMENT>( aA, aB, aClearance, aActual, aMTV );
|
||||
return CollCase<SHAPE_LINE_CHAIN_BASE, SHAPE_SEGMENT>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
||||
case SH_SIMPLE:
|
||||
return CollCase<SHAPE_SIMPLE, SHAPE_SIMPLE>( aA, aB, aClearance, aActual, aMTV );
|
||||
case SH_POLY_SET_TRIANGLE:
|
||||
return CollCase<SHAPE_LINE_CHAIN_BASE, SHAPE_LINE_CHAIN_BASE>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
||||
case SH_ARC:
|
||||
return CollCaseReversed<SHAPE_SIMPLE, SHAPE_ARC>( aA, aB, aClearance, aActual, aMTV );
|
||||
return CollCaseReversed<SHAPE_LINE_CHAIN_BASE, SHAPE_ARC>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
||||
case SH_NULL:
|
||||
return false;
|
||||
|
@ -615,7 +596,8 @@ static bool collideSingleShapes( const SHAPE* aA, const SHAPE* aB, int aClearanc
|
|||
return CollCase<SHAPE_ARC, SHAPE_SEGMENT>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
||||
case SH_SIMPLE:
|
||||
return CollCase<SHAPE_ARC, SHAPE_SIMPLE>( aA, aB, aClearance, aActual, aMTV );
|
||||
case SH_POLY_SET_TRIANGLE:
|
||||
return CollCase<SHAPE_ARC, SHAPE_LINE_CHAIN_BASE>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
||||
case SH_ARC:
|
||||
return CollCase<SHAPE_ARC, SHAPE_ARC>( aA, aB, aClearance, aActual, aMTV );
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
class SHAPE;
|
||||
|
||||
SHAPE_LINE_CHAIN::SHAPE_LINE_CHAIN( const std::vector<int>& aV)
|
||||
: SHAPE( SH_LINE_CHAIN ), m_closed( false ), m_width( 0 )
|
||||
: SHAPE_LINE_CHAIN_BASE( SH_LINE_CHAIN ), m_closed( false ), m_width( 0 )
|
||||
{
|
||||
for(size_t i = 0; i < aV.size(); i+= 2 )
|
||||
{
|
||||
|
@ -85,14 +85,16 @@ void SHAPE_LINE_CHAIN::convertArc( ssize_t aArcIndex )
|
|||
}
|
||||
|
||||
|
||||
bool SHAPE_LINE_CHAIN::Collide( const VECTOR2I& aP, int aClearance, int* aActual ) const
|
||||
bool SHAPE_LINE_CHAIN_BASE::Collide( const VECTOR2I& aP, int aClearance, int* aActual ) const
|
||||
{
|
||||
SEG::ecoord dist_sq = VECTOR2I::ECOORD_MAX;
|
||||
SEG::ecoord clearance_sq = SEG::Square( aClearance );
|
||||
|
||||
for( int i = 0; i < SegmentCount(); i++ )
|
||||
// fixme: why this only checks open curves?
|
||||
|
||||
for( int i = 0; i < GetSegmentCount(); i++ )
|
||||
{
|
||||
const SEG& s = CSegment( i );
|
||||
const SEG& s = GetSegment( i );
|
||||
dist_sq = std::min( dist_sq, s.SquaredDistance( aP ) );
|
||||
|
||||
if( ( dist_sq == 0 || dist_sq < clearance_sq ) && !aActual )
|
||||
|
@ -125,14 +127,14 @@ void SHAPE_LINE_CHAIN::Rotate( double aAngle, const VECTOR2I& aCenter )
|
|||
}
|
||||
|
||||
|
||||
bool SHAPE_LINE_CHAIN::Collide( const SEG& aSeg, int aClearance, int* aActual ) const
|
||||
bool SHAPE_LINE_CHAIN_BASE::Collide( const SEG& aSeg, int aClearance, int* aActual ) const
|
||||
{
|
||||
SEG::ecoord dist_sq = VECTOR2I::ECOORD_MAX;
|
||||
SEG::ecoord clearance_sq = SEG::Square( aClearance );
|
||||
|
||||
for( int i = 0; i < SegmentCount(); i++ )
|
||||
for( int i = 0; i < GetSegmentCount(); i++ )
|
||||
{
|
||||
const SEG& s = CSegment( i );
|
||||
const SEG& s = GetSegment( i );
|
||||
dist_sq = std::min( dist_sq, s.SquaredDistance( aSeg ) );
|
||||
|
||||
if( ( dist_sq == 0 || dist_sq < clearance_sq ) && !aActual )
|
||||
|
@ -292,15 +294,15 @@ int SHAPE_LINE_CHAIN::Distance( const VECTOR2I& aP, bool aOutlineOnly ) const
|
|||
}
|
||||
|
||||
|
||||
SEG::ecoord SHAPE_LINE_CHAIN::SquaredDistance( const VECTOR2I& aP, bool aOutlineOnly ) const
|
||||
SEG::ecoord SHAPE_LINE_CHAIN_BASE::SquaredDistance( const VECTOR2I& aP, bool aOutlineOnly ) const
|
||||
{
|
||||
ecoord d = VECTOR2I::ECOORD_MAX;
|
||||
|
||||
if( IsClosed() && PointInside( aP ) && !aOutlineOnly )
|
||||
return 0;
|
||||
|
||||
for( int s = 0; s < SegmentCount(); s++ )
|
||||
d = std::min( d, CSegment( s ).SquaredDistance( aP ) );
|
||||
for( int s = 0; s < GetSegmentCount(); s++ )
|
||||
d = std::min( d, GetSegment( s ).SquaredDistance( aP ) );
|
||||
|
||||
return d;
|
||||
}
|
||||
|
@ -601,16 +603,18 @@ int SHAPE_LINE_CHAIN::PathLength( const VECTOR2I& aP ) const
|
|||
}
|
||||
|
||||
|
||||
bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aPt, int aAccuracy, bool aUseBBoxCache ) const
|
||||
bool SHAPE_LINE_CHAIN_BASE::PointInside( const VECTOR2I& aPt, int aAccuracy, bool aUseBBoxCache ) const
|
||||
{
|
||||
/*
|
||||
* Don't check the bounding box unless it's cached. Building it is about the same speed as
|
||||
* the rigorous test below and so just slows things down by doing potentially two tests.
|
||||
*/
|
||||
if( aUseBBoxCache && !m_bbox.Contains( aPt ) )
|
||||
return false;
|
||||
//if( aUseBBoxCache && !m_bbox.Contains( aPt ) )
|
||||
//return false;
|
||||
|
||||
if( !m_closed || PointCount() < 3 )
|
||||
// fixme: bbox cache...
|
||||
|
||||
if( !IsClosed() || GetPointCount() < 3 )
|
||||
return false;
|
||||
|
||||
bool inside = false;
|
||||
|
@ -626,13 +630,12 @@ bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aPt, int aAccuracy, bool aUs
|
|||
* Note: we open-code CPoint() here so that we don't end up calculating the size of the
|
||||
* vector number-of-points times. This has a non-trivial impact on zone fill times.
|
||||
*/
|
||||
const std::vector<VECTOR2I>& points = CPoints();
|
||||
int pointCount = points.size();
|
||||
int pointCount = GetPointCount();
|
||||
|
||||
for( int i = 0; i < pointCount; )
|
||||
{
|
||||
const auto p1 = points[ i++ ];
|
||||
const auto p2 = points[ i == pointCount ? 0 : i ];
|
||||
const auto p1 = GetPoint( i++ );
|
||||
const auto p2 = GetPoint( i == pointCount ? 0 : i );
|
||||
const auto diff = p2 - p1;
|
||||
|
||||
if( diff.y != 0 )
|
||||
|
@ -653,25 +656,25 @@ bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aPt, int aAccuracy, bool aUs
|
|||
}
|
||||
|
||||
|
||||
bool SHAPE_LINE_CHAIN::PointOnEdge( const VECTOR2I& aPt, int aAccuracy ) const
|
||||
bool SHAPE_LINE_CHAIN_BASE::PointOnEdge( const VECTOR2I& aPt, int aAccuracy ) const
|
||||
{
|
||||
return EdgeContainingPoint( aPt, aAccuracy ) >= 0;
|
||||
}
|
||||
|
||||
int SHAPE_LINE_CHAIN::EdgeContainingPoint( const VECTOR2I& aPt, int aAccuracy ) const
|
||||
int SHAPE_LINE_CHAIN_BASE::EdgeContainingPoint( const VECTOR2I& aPt, int aAccuracy ) const
|
||||
{
|
||||
if( !PointCount() )
|
||||
if( !GetPointCount() )
|
||||
return -1;
|
||||
|
||||
else if( PointCount() == 1 )
|
||||
else if( GetPointCount() == 1 )
|
||||
{
|
||||
VECTOR2I dist = m_points[0] - aPt;
|
||||
VECTOR2I dist = GetPoint(0) - aPt;
|
||||
return ( hypot( dist.x, dist.y ) <= aAccuracy + 1 ) ? 0 : -1;
|
||||
}
|
||||
|
||||
for( int i = 0; i < SegmentCount(); i++ )
|
||||
for( int i = 0; i < GetSegmentCount(); i++ )
|
||||
{
|
||||
const SEG s = CSegment( i );
|
||||
const SEG s = GetSegment( i );
|
||||
|
||||
if( s.A == aPt || s.B == aPt )
|
||||
return i;
|
||||
|
|
Loading…
Reference in New Issue