bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aPt, int aAccuracy ) const
{
    BOX2I bbox = BBox();
    bbox.Inflate( aAccuracy );

    if( !m_closed || PointCount() < 3 || !BBox().Contains( aPt ) )
        return false;

    bool inside = false;

    /**
     * To check for interior points, we draw a line in the positive x direction from
     * the point.  If it intersects an even number of segments, the point is outside the
     * line chain (it had to first enter and then exit).  Otherwise, it is inside the chain.
     *
     * Note: slope might be denormal here in the case of a horizontal line but we require our
     * y to move from above to below the point (or vice versa)
     */
    for( int i = 0; i < PointCount(); i++ )
    {
        const auto p1 = CPoint( i );
        const auto p2 = CPoint( i + 1 ); // CPoint wraps, so ignore counts
        const auto diff = p2 - p1;

        if( diff.y != 0 )
        {
            const int d = rescale( diff.x, ( aPt.y - p1.y ), diff.y );

            if( ( ( p1.y > aPt.y ) != ( p2.y > aPt.y ) ) && ( aPt.x - p1.x < d ) )
                inside = !inside;
        }
    }
    return inside && !PointOnEdge( aPt, aAccuracy );
}
void SHAPE_LINE_CHAIN::Remove( int aStartIndex, int aEndIndex )
{
    if( aEndIndex < 0 )
        aEndIndex += PointCount();

    if( aStartIndex < 0 )
        aStartIndex += PointCount();

    m_points.erase( m_points.begin() + aStartIndex, m_points.begin() + aEndIndex + 1 );
}
void SHAPE_LINE_CHAIN::Replace( int aStartIndex, int aEndIndex, const SHAPE_LINE_CHAIN& aLine )
{
    if( aEndIndex < 0 )
        aEndIndex += PointCount();

    if( aStartIndex < 0 )
        aStartIndex += PointCount();

    m_points.erase( m_points.begin() + aStartIndex, m_points.begin() + aEndIndex + 1 );
    m_points.insert( m_points.begin() + aStartIndex, aLine.m_points.begin(), aLine.m_points.end() );
}
const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int aStartIndex, int aEndIndex ) const
{
    SHAPE_LINE_CHAIN rv;

    if( aEndIndex < 0 )
        aEndIndex += PointCount();

    if( aStartIndex < 0 )
        aStartIndex += PointCount();

    for( int i = aStartIndex; i <= aEndIndex; i++ )
        rv.Append( m_points[i] );

    return rv;
}
Beispiel #5
0
void FTContour::buildBackOutset(float outset)
{
    for(size_t i = 0; i < PointCount(); ++i)
    {
        AddBackPoint(Point(i) + Outset(i) * outset);
    }
}
Beispiel #6
0
void FTContour::SetParity(int parity)
{
    size_t size = PointCount();
    FTPoint vOutset;

    if(((parity & 1) && clockwise) || (!(parity & 1) && !clockwise))
    {
        // Contour orientation is wrong! We must reverse all points.
        // FIXME: could it be worth writing FTVector::reverse() for this?
        for(size_t i = 0; i < size / 2; i++)
        {
            FTPoint tmp = pointList[i];
            pointList[i] = pointList[size - 1 - i];
            pointList[size - 1 -i] = tmp;
        }

        clockwise = !clockwise;
    }

    for(size_t i = 0; i < size; i++)
    {
        size_t prev, cur, next;

        prev = (i + size - 1) % size;
        cur = i;
        next = (i + size + 1) % size;

        vOutset = ComputeOutsetPoint(Point(prev), Point(cur), Point(next));
        AddOutsetPoint(vOutset);
    }
}
void SHAPE_LINE_CHAIN::Replace( int aStartIndex, int aEndIndex, const VECTOR2I& aP )
{
    if( aEndIndex < 0 )
        aEndIndex += PointCount();

    if( aStartIndex < 0 )
        aStartIndex += PointCount();

    if( aStartIndex == aEndIndex )
        m_points[aStartIndex] = aP;
    else
    {
        m_points.erase( m_points.begin() + aStartIndex + 1, m_points.begin() + aEndIndex + 1 );
        m_points[aStartIndex] = aP;
    }
}
int SHAPE_LINE_CHAIN::Find( const VECTOR2I& aP ) const
{
    for( int s = 0; s < PointCount(); s++ )
        if( CPoint( s ) == aP )
            return s;

    return -1;
}
const std::string SHAPE_LINE_CHAIN::Format() const
{
    std::stringstream ss;

    ss << m_points.size() << " " << ( m_closed ? 1 : 0 ) << " ";

    for( int i = 0; i < PointCount(); i++ )
        ss << m_points[i].x << " " << m_points[i].y << " "; // Format() << " ";

    return ss.str();
}
bool SHAPE_LINE_CHAIN::CheckClearance( const VECTOR2I& aP, const int aDist) const
{
    if( !PointCount() )
        return false;

    else if( PointCount() == 1 )
        return m_points[0] == aP;

    for( int i = 0; i < SegmentCount(); i++ )
    {
        const SEG s = CSegment( i );

        if( s.A == aP || s.B == aP )
            return true;

        if( s.Distance( aP ) <= aDist )
            return true;
    }

    return false;
}
Beispiel #11
0
ON_PointGrid& ON_PointGrid::operator=( const ON_PointGrid& src )
{
  if ( this != &src ) {
    ON_Geometry::operator=(src);
    m_point_count[0] = src.m_point_count[0];
    m_point_count[1] = src.m_point_count[1];
    m_point_stride0 = m_point_count[1];
    m_point.Reserve(PointCount());
    m_point.SetCount(PointCount());
    if ( PointCount() > 0 ) {
      // copy cv array
      if ( m_point_stride0 == src.m_point_stride0 ) {
        memcpy( m_point.Array(), src.m_point.Array(), PointCount()*sizeof(ON_3dPoint) );
      }
      else {
        int i, j;
        for ( i = 0; i < m_point_count[0]; i++ ) for ( j = 0; j < m_point_count[1]; j++ ) {
          m_point[i*m_point_stride0+j] = src[i][j];
        }
      }
    }
  }
  return *this;
}
int SHAPE_LINE_CHAIN::EdgeContainingPoint( const VECTOR2I& aPt, int aAccuracy ) const
{
    if( !PointCount() )
		return -1;

	else if( PointCount() == 1 )
    {
	    VECTOR2I dist = m_points[0] - aPt;
	    return ( hypot( dist.x, dist.y ) <= aAccuracy + 1 ) ? 0 : -1;
    }

    for( int i = 0; i < SegmentCount(); i++ )
    {
        const SEG s = CSegment( i );

        if( s.A == aPt || s.B == aPt )
            return i;

        if( s.Distance( aPt ) <= aAccuracy + 1 )
            return i;
    }

    return -1;
}
ClipperLib::Path SHAPE_LINE_CHAIN::convertToClipper( bool aRequiredOrientation ) const
{
    ClipperLib::Path c_path;

    for( int i = 0; i < PointCount(); i++ )
    {
        const VECTOR2I& vertex = CPoint( i );
        c_path.push_back( ClipperLib::IntPoint( vertex.x, vertex.y ) );
    }

    if( Orientation( c_path ) != aRequiredOrientation )
        ReversePath( c_path );

    return c_path;
}
const VECTOR2I SHAPE_LINE_CHAIN::NearestPoint( const SEG& aSeg, int& dist ) const
{
    int nearest = 0;

    dist = INT_MAX;
    for( int i = 0; i < PointCount(); i++ )
    {
        int d = aSeg.LineDistance( CPoint( i ) );

        if( d < dist )
        {
            dist = d;
            nearest = i;
        }
    }

    return CPoint( nearest );
}
Beispiel #15
0
static void VaryGlyphs(struct ttfinfo *info,int tupleIndex,int gnum,
	int *points, FILE *ttf ) {
    /* one annoying thing about gvar, is that the variations do not describe */
    /*  designs. well variations for [0,1] describes that design, but the */
    /*  design for [1,1] includes the variations [0,1], [1,0], and [1,1] */
    int pcnt, tc;
    int *xdeltas, *ydeltas;
    struct variations *v = info->variations;

    if ( info->chars[gnum]==NULL )	/* Apple doesn't support ttc so this */
return;					/*  can't happen */
    if ( points==NULL ) {
	LogError( _("Mismatched local and shared tuple flags.\n") );
return;
    }

    if ( points[0]==ALL_POINTS )
	pcnt = PointCount(info->chars[gnum])+4;
    else {
	for ( pcnt=0; points[pcnt]!=END_OF_POINTS; ++pcnt );
    }
    xdeltas = readpackeddeltas(ttf,pcnt);
    ydeltas = readpackeddeltas(ttf,pcnt);
    if ( xdeltas[0]!=BAD_DELTA && ydeltas[0]!=BAD_DELTA )
	for ( tc = 0; tc<v->tuple_count; ++tc ) {
	    if ( TuplesMatch(v,tc,tupleIndex))
		VaryGlyph(v->tuples[tc].chars[gnum],points,xdeltas,ydeltas,pcnt);
    } else {
	static int warned = false;
	if ( !warned )
	    LogError( _("Incorrect number of deltas in glyph %d (%s)\n"), gnum,
		    info->chars[gnum]->name!=NULL?info->chars[gnum]->name:"<Nameless>" );
	warned = true;
    }
    free(xdeltas);
    free(ydeltas);
}
SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify()
{
    std::vector<VECTOR2I> pts_unique;

    if( PointCount() < 2 )
    {
        return *this;
    }
    else if( PointCount() == 2 )
    {
        if( m_points[0] == m_points[1] )
            m_points.pop_back();

        return *this;
    }

    int i = 0;
    int np = PointCount();

    // stage 1: eliminate duplicate vertices
    while( i < np )
    {
        int j = i + 1;

        while( j < np && CPoint( i ) == CPoint( j ) )
            j++;

        pts_unique.push_back( CPoint( i ) );
        i = j;
    }

    m_points.clear();
    np = pts_unique.size();

    i = 0;

    // stage 1: eliminate collinear segments
    while( i < np - 2 )
    {
        const VECTOR2I p0 = pts_unique[i];
        const VECTOR2I p1 = pts_unique[i + 1];
        int n = i;

        while( n < np - 2 && SEG( p0, p1 ).LineDistance( pts_unique[n + 2] ) <= 1 )
            n++;

        m_points.push_back( p0 );

        if( n > i )
            i = n;

        if( n == np )
        {
            m_points.push_back( pts_unique[n - 1] );
            return *this;
        }

        i++;
    }

    if( np > 1 )
        m_points.push_back( pts_unique[np - 2] );

    m_points.push_back( pts_unique[np - 1] );

    return *this;
}