Skip to content

Commit

Permalink
Improve dxf export for svg symbols
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed Dec 19, 2013
1 parent 99c6875 commit 521426c
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 27 deletions.
187 changes: 166 additions & 21 deletions src/core/dxf/qgsdxfpaintengine.cpp
Expand Up @@ -62,6 +62,10 @@ void QgsDxfPaintEngine::updateState( const QPaintEngineState& state )
{
mPen = state.pen();
}
if ( state.state() & QPaintEngine::DirtyBrush )
{
mBrush = state.brush();
}
}

void QgsDxfPaintEngine::drawPolygon( const QPointF* points, int pointCount, PolygonDrawMode mode )
Expand All @@ -79,7 +83,7 @@ void QgsDxfPaintEngine::drawPolygon( const QPointF* points, int pointCount, Poly
}

bool closed = ( pointCount > 3 && points[0] == points[pointCount - 1] );
mDxf->writePolyline( polyline, mLayer, "CONTINUOUS", currentPenColor(), currentWidth(), closed );
mDxf->writePolyline( polyline, mLayer, "CONTINUOUS", currentColor(), currentWidth(), closed );
}

void QgsDxfPaintEngine::drawRects( const QRectF* rects, int rectCount )
Expand All @@ -99,7 +103,7 @@ void QgsDxfPaintEngine::drawRects( const QRectF* rects, int rectCount )
QgsPoint pt2 = toDxfCoordinates( QPointF( right, bottom ) );
QgsPoint pt3 = toDxfCoordinates( QPointF( left, top ) );
QgsPoint pt4 = toDxfCoordinates( QPointF( right, top ) );
mDxf->writeSolid( mLayer, currentPenColor(), pt1, pt2, pt3, pt4 );
mDxf->writeSolid( mLayer, currentColor(), pt1, pt2, pt3, pt4 );
}
}

Expand All @@ -110,58 +114,60 @@ void QgsDxfPaintEngine::drawEllipse( const QRectF& rect )
//a circle
if ( qgsDoubleNear( rect.width(), rect.height() ) )
{
mDxf->writeCircle( mLayer, currentPenColor(), toDxfCoordinates( midPoint ), rect.width() / 2.0 );
mDxf->writeCircle( mLayer, currentColor(), toDxfCoordinates( midPoint ), rect.width() / 2.0 );
}

//todo: create polyline for real ellises
}

void QgsDxfPaintEngine::drawPath( const QPainterPath& path )
{
/*QList<QPolygonF> polygonList = path.toFillPolygons();
QList<QPolygonF>::const_iterator pIt = polygonList.constBegin();
for ( ; pIt != polygonList.constEnd(); ++pIt )
{
drawPolygon( pIt->constData(), pIt->size(), pIt->isClosed() ? QPaintEngine::OddEvenMode : QPaintEngine::PolylineMode );
}*/

int pathLength = path.elementCount();
for ( int i = 0; i < pathLength; ++i )
{
const QPainterPath::Element& pathElem = path.elementAt( i );
if ( pathElem.isMoveTo() )
if ( pathElem.type == QPainterPath::MoveToElement )
{
moveTo( pathElem.x, pathElem.y );
}
else if ( pathElem.isLineTo() )
else if ( pathElem.type == QPainterPath::LineToElement )
{
lineTo( pathElem.x, pathElem.y );
}
else if ( pathElem.isCurveTo() )
else if ( pathElem.type == QPainterPath::CurveToElement )
{
curveTo( pathElem.x, pathElem.y );
}
else if ( pathElem.type == QPainterPath::CurveToDataElement )
{
mCurrentCurve.append( QPointF( pathElem.x, pathElem.y ) );
}
}
endCurve();
endPolygon();
}

void QgsDxfPaintEngine::moveTo( double dx, double dy )
{
if ( mCurrentPolygon.size() < 0 )
{
endPolygon();
}
endCurve();
endPolygon();
mCurrentPolygon.append( QPointF( dx, dy ) );
}

void QgsDxfPaintEngine::lineTo( double dx, double dy )
{
endCurve();
mCurrentPolygon.append( QPointF( dx, dy ) );
}

void QgsDxfPaintEngine::curveTo( double dx, double dy )
{
mCurrentPolygon.append( QPointF( dx, dy ) ); //todo...
endCurve();
if ( mCurrentPolygon.size() > 0 )
{
mCurrentCurve.append( mCurrentPolygon.last() );
}
mCurrentCurve.append( QPointF( dx, dy ) );
}

void QgsDxfPaintEngine::endPolygon()
Expand All @@ -173,6 +179,35 @@ void QgsDxfPaintEngine::endPolygon()
mCurrentPolygon.clear();
}

void QgsDxfPaintEngine::endCurve()
{
if ( mCurrentCurve.size() < 1 )
{
return;
}
if ( mCurrentPolygon.size() < 1 )
{
mCurrentCurve.clear();
return;
}
//mCurrentCurve.prepend( mCurrentPolygon.last() );

if ( mCurrentCurve.size() >= 3 )
{
double t = 0.05;
for ( int i = 1; i < 20; ++i ) //approximate curve with 20 segments
{
mCurrentPolygon.append( bezierPoint( mCurrentCurve, t ) );
t += 0.05;
}
}
else if ( mCurrentCurve.size() == 2 )
{
mCurrentPolygon.append( mCurrentCurve.at( 1 ) );
}
mCurrentCurve.clear();
}

void QgsDxfPaintEngine::drawLines( const QLineF* lines, int lineCount )
{
if ( !mDxf || !mPaintDevice || !lines )
Expand All @@ -184,7 +219,7 @@ void QgsDxfPaintEngine::drawLines( const QLineF* lines, int lineCount )
{
QgsPoint pt1 = toDxfCoordinates( lines[i].p1() );
QgsPoint pt2 = toDxfCoordinates( lines[i].p2() );
mDxf->writeLine( pt1, pt2, mLayer, "CONTINUOUS", currentPenColor(), currentWidth() );
mDxf->writeLine( pt1, pt2, mLayer, "CONTINUOUS", currentColor(), currentWidth() );
}
}

Expand All @@ -199,14 +234,19 @@ QgsPoint QgsDxfPaintEngine::toDxfCoordinates( const QPointF& pt ) const
return QgsPoint( dxfPt.x(), dxfPt.y() );
}

int QgsDxfPaintEngine::currentPenColor() const
int QgsDxfPaintEngine::currentColor() const
{
if ( !mDxf )
{
return 0;
}

return mDxf->closestColorMatch( mPen.color().rgb() );
QColor c = mPen.color();
if ( mPen.style() == Qt::NoPen )
{
c = mBrush.color();
}
return mDxf->closestColorMatch( c.rgb() );
}

double QgsDxfPaintEngine::currentWidth() const
Expand All @@ -218,3 +258,108 @@ double QgsDxfPaintEngine::currentWidth() const

return mPen.widthF() * mPaintDevice->widthScaleFactor();
}

QPointF QgsDxfPaintEngine::bezierPoint( const QList<QPointF>& controlPolygon, double t )
{
/*if ( p && mControlPoly )
{
p->setX( 0 );
p->setY( 0 );
p->setZ( 0 );
for ( int n = 1; n <= int( mControlPoly->count() ); n++ )
{
double bernst = MathUtils::calcBernsteinPoly( mControlPoly->count() - 1, n - 1, t );
p->setX( p->getX() + ( *mControlPoly )[n-1]->getX()*bernst );
p->setY( p->getY() + ( *mControlPoly )[n-1]->getY()*bernst );
p->setZ( p->getZ() + ( *mControlPoly )[n-1]->getZ()*bernst );
}
}
else
{
QgsDebugMsg( "warning: null pointer" );
}*/

double x = 0;
double y = 0;
int cPolySize = controlPolygon.size();
double bPoly = 0;

QList<QPointF>::const_iterator it = controlPolygon.constBegin();
int i = 0;
for ( ; it != controlPolygon.constEnd(); ++it )
{
bPoly = bernsteinPoly( cPolySize - 1, i, t );
x += ( it->x() * bPoly );
y += ( it->y() * bPoly );
++i;
}

return QPointF( x, y );
}

double QgsDxfPaintEngine::bernsteinPoly( int n, int i, double t )
{
if ( i < 0 )
{
return 0;
}

return lower( n, i )*power( t, i )*power(( 1 - t ), ( n - i ) );
}

int QgsDxfPaintEngine::lower( int n, int i )
{
if ( i >= 0 && i <= n )
{
return faculty( n ) / ( faculty( i )*faculty( n - i ) );
}
else
{
return 0;
}
}

double QgsDxfPaintEngine::power( double a, int b )
{
if ( b == 0 )
{
return 1;
}
double tmp = a;
for ( int i = 2; i <= qAbs(( double )b ); i++ )
{

a *= tmp;
}
if ( b > 0 )
{
return a;
}
else
{
return ( 1.0 / a );
}
}

int QgsDxfPaintEngine::faculty( int n )
{
if ( n < 0 )//Is faculty also defined for negative integers?
{
return 0;
}
int i;
int result = n;

if ( n == 0 || n == 1 )
{
return 1;
}//faculty of 0 is 1!

for ( i = n - 1; i >= 2; i-- )
{
result *= i;
}
return result;
}
22 changes: 16 additions & 6 deletions src/core/dxf/qgsdxfpaintengine.h
Expand Up @@ -48,25 +48,35 @@ class CORE_EXPORT QgsDxfPaintEngine: public QPaintEngine

void setShift( const QPointF& shift ) { mShift = shift; }

void moveTo( double dx, double dy );
void lineTo( double dx, double dy );
void curveTo( double dx, double dy );
void endPolygon();

private:
const QgsDxfPaintDevice* mPaintDevice;
QgsDxfExport* mDxf;

//painter state information
QTransform mTransform;
QPen mPen;
QBrush mBrush;
QString mLayer;
QPointF mShift;
QPolygonF mCurrentPolygon;
QList<QPointF> mCurrentCurve;

QgsPoint toDxfCoordinates( const QPointF& pt ) const;
int currentPenColor() const;
int currentColor() const;
double currentWidth() const;

void moveTo( double dx, double dy );
void lineTo( double dx, double dy );
void curveTo( double dx, double dy );
void endPolygon();
void endCurve();

//utils for bezier curve calculation
static QPointF bezierPoint( const QList<QPointF>& controlPolygon, double t );
static double bernsteinPoly( int n, int i, double t );
static int lower( int n, int i );
static double power( double a, int b );
static int faculty( int n );
};

#endif // QGSDXFPAINTENGINE_H

0 comments on commit 521426c

Please sign in to comment.