Skip to content

Commit

Permalink
Move code to draw arrow head from composer arrow to composer item
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.osgeo.org/qgis/trunk@13328 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mhugent committed Apr 19, 2010
1 parent 63ef719 commit 61ecac3
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 48 deletions.
6 changes: 6 additions & 0 deletions python/core/qgscomposeritem.sip
Expand Up @@ -181,6 +181,12 @@ class QgsComposerItem: QObject, QGraphicsRectItem
/**Draw background*/
virtual void drawBackground( QPainter* p );

/**Draws arrowhead*/
void drawArrowHead( QPainter* p, double x, double y, double angle, double arrowHeadWidth ) const;

/**Returns angle of the line from p1 to p2 (clockwise, starting at N)*/
double angle( const QPointF& p1, const QPointF& p2 ) const;

/**Returns the current (zoom level dependent) tolerance to decide if mouse position is close enough to the \
item border for resizing*/
double rectHandlerBorderTolerance() const;
Expand Down
50 changes: 4 additions & 46 deletions src/core/composer/qgscomposerarrow.cpp
Expand Up @@ -105,43 +105,15 @@ void QgsComposerArrow::setSceneRect( const QRectF& rectangle )

void QgsComposerArrow::drawHardcodedMarker( QPainter* p, MarkerType type )
{
double angle = arrowAngle();
//qWarning(QString::number(angle).toLocal8Bit().data());
double angleRad = angle / 180.0 * M_PI;
QPointF middlePoint = QPointF( mStopPoint.x() - transform().dx(), mStopPoint.y() - transform().dy() );

//rotate both arrow points
QPointF p1 = QPointF( -mArrowHeadWidth / 2.0, mArrowHeadWidth );
QPointF p2 = QPointF( mArrowHeadWidth / 2.0, mArrowHeadWidth );

QPointF p1Rotated, p2Rotated;
p1Rotated.setX( p1.x() * cos( angleRad ) + p1.y() * -sin( angleRad ) );
p1Rotated.setY( p1.x() * sin( angleRad ) + p1.y() * cos( angleRad ) );
p2Rotated.setX( p2.x() * cos( angleRad ) + p2.y() * -sin( angleRad ) );
p2Rotated.setY( p2.x() * sin( angleRad ) + p2.y() * cos( angleRad ) );

QPolygonF arrowHeadPoly;
arrowHeadPoly << middlePoint;
arrowHeadPoly << QPointF( middlePoint.x() + p1Rotated.x(), middlePoint.y() + p1Rotated.y() );
arrowHeadPoly << QPointF( middlePoint.x() + p2Rotated.x(), middlePoint.y() + p2Rotated.y() );

p->save();

QPen arrowPen = p->pen();
arrowPen.setJoinStyle( Qt::RoundJoin );
QBrush arrowBrush = p->brush();
arrowBrush.setColor( mArrowColor );
arrowBrush.setStyle( Qt::SolidPattern );
p->setPen( arrowPen );
p->setBrush( arrowBrush );
p->drawPolygon( arrowHeadPoly );

p->restore();
drawArrowHead( p, mStopPoint.x() - transform().dx(), mStopPoint.y() - transform().dy(), angle( mStartPoint, mStopPoint ), mArrowHeadWidth );
}

void QgsComposerArrow::drawSVGMarker( QPainter* p, MarkerType type, const QString& markerPath )
{
double angle = arrowAngle();
double ang = angle( mStartPoint, mStopPoint );

double arrowHeadHeight;
if ( type == StartMarker )
Expand Down Expand Up @@ -211,7 +183,7 @@ void QgsComposerArrow::drawSVGMarker( QPainter* p, MarkerType type, const QStrin
fixPoint.setX( 0 ); fixPoint.setY( -arrowHeadHeight / 2.0 );
}
QPointF rotatedFixPoint;
double angleRad = angle / 180 * M_PI;
double angleRad = ang / 180 * M_PI;
rotatedFixPoint.setX( fixPoint.x() * cos( angleRad ) + fixPoint.y() * -sin( angleRad ) );
rotatedFixPoint.setY( fixPoint.x() * sin( angleRad ) + fixPoint.y() * cos( angleRad ) );

Expand All @@ -221,7 +193,7 @@ void QgsComposerArrow::drawSVGMarker( QPainter* p, MarkerType type, const QStrin

p->save();
p->translate( canvasPoint.x() - rotatedFixPoint.x() , canvasPoint.y() - rotatedFixPoint.y() );
p->rotate( angle );
p->rotate( ang );
p->translate( -mArrowHeadWidth / 2.0, -arrowHeadHeight / 2.0 );

p->drawImage( QRectF( 0, 0, mArrowHeadWidth, arrowHeadHeight ), markerImage, QRectF( 0, 0, imageWidth, imageHeight ) );
Expand All @@ -230,20 +202,6 @@ void QgsComposerArrow::drawSVGMarker( QPainter* p, MarkerType type, const QStrin
return;
}

double QgsComposerArrow::arrowAngle() const
{
double xDiff = mStopPoint.x() - mStartPoint.x();
double yDiff = mStopPoint.y() - mStartPoint.y();
double length = sqrt( xDiff * xDiff + yDiff * yDiff );

double angle = acos(( -yDiff * length ) / ( length * length ) ) * 180 / M_PI;
if ( xDiff < 0 )
{
return ( 360 - angle );
}
return angle;
}

void QgsComposerArrow::setStartMarker( const QString& svgPath )
{
QSvgRenderer r;
Expand Down
2 changes: 0 additions & 2 deletions src/core/composer/qgscomposerarrow.h
Expand Up @@ -108,8 +108,6 @@ class CORE_EXPORT QgsComposerArrow: public QgsComposerItem
void drawHardcodedMarker( QPainter* p, MarkerType type );
/**Draws a user-defined marker (must be an svg file)*/
void drawSVGMarker( QPainter* p, MarkerType type, const QString& markerPath );
/**Calculates arrow angle (for marker rotation)*/
double arrowAngle() const;
/**Apply default graphics settings*/
void initGraphicsSettings();
};
Expand Down
55 changes: 55 additions & 0 deletions src/core/composer/qgscomposeritem.cpp
Expand Up @@ -721,6 +721,43 @@ void QgsComposerItem::drawText( QPainter* p, const QRectF& rect, const QString&
p->restore();
}

void QgsComposerItem::drawArrowHead( QPainter* p, double x, double y, double angle, double arrowHeadWidth ) const
{
if ( !p )
{
return;
}
double angleRad = angle / 180.0 * M_PI;
QPointF middlePoint( x, y );
//rotate both arrow points
QPointF p1 = QPointF( -arrowHeadWidth / 2.0, arrowHeadWidth );
QPointF p2 = QPointF( arrowHeadWidth / 2.0, arrowHeadWidth );

QPointF p1Rotated, p2Rotated;
p1Rotated.setX( p1.x() * cos( angleRad ) + p1.y() * -sin( angleRad ) );
p1Rotated.setY( p1.x() * sin( angleRad ) + p1.y() * cos( angleRad ) );
p2Rotated.setX( p2.x() * cos( angleRad ) + p2.y() * -sin( angleRad ) );
p2Rotated.setY( p2.x() * sin( angleRad ) + p2.y() * cos( angleRad ) );

QPolygonF arrowHeadPoly;
arrowHeadPoly << middlePoint;
arrowHeadPoly << QPointF( middlePoint.x() + p1Rotated.x(), middlePoint.y() + p1Rotated.y() );
arrowHeadPoly << QPointF( middlePoint.x() + p2Rotated.x(), middlePoint.y() + p2Rotated.y() );

p->save();

QPen arrowPen = p->pen();
arrowPen.setJoinStyle( Qt::RoundJoin );
QBrush arrowBrush = p->brush();
arrowBrush.setStyle( Qt::SolidPattern );
p->setPen( arrowPen );
p->setBrush( arrowBrush );
arrowBrush.setStyle( Qt::SolidPattern );
p->drawPolygon( arrowHeadPoly );

p->restore();
}

double QgsComposerItem::textWidthMillimeters( const QFont& font, const QString& text ) const
{
QFont metricsFont = scaledFontPixelSize( font );
Expand Down Expand Up @@ -748,6 +785,24 @@ QFont QgsComposerItem::scaledFontPixelSize( const QFont& font ) const
return scaledFont;
}

double QgsComposerItem::angle( const QPointF& p1, const QPointF& p2 ) const
{
double xDiff = p2.x() - p1.x();
double yDiff = p2.y() - p1.y();
double length = sqrt( xDiff * xDiff + yDiff * yDiff );
if ( length <= 0 )
{
return 0;
}

double angle = acos(( -yDiff * length ) / ( length * length ) ) * 180 / M_PI;
if ( xDiff < 0 )
{
return ( 360 - angle );
}
return angle;
}

double QgsComposerItem::horizontalViewScaleFactor() const
{
double result = -1;
Expand Down
6 changes: 6 additions & 0 deletions src/core/composer/qgscomposeritem.h
Expand Up @@ -233,6 +233,12 @@ class CORE_EXPORT QgsComposerItem: public QObject, public QGraphicsRectItem
/**Draw background*/
virtual void drawBackground( QPainter* p );

/**Draws arrowhead*/
void drawArrowHead( QPainter* p, double x, double y, double angle, double arrowHeadWidth ) const;

/**Returns angle of the line from p1 to p2 (clockwise, starting at N)*/
double angle( const QPointF& p1, const QPointF& p2 ) const;

/**Returns the current (zoom level dependent) tolerance to decide if mouse position is close enough to the \
item border for resizing*/
double rectHandlerBorderTolerance() const;
Expand Down

0 comments on commit 61ecac3

Please sign in to comment.