-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
git-svn-id: http://svn.osgeo.org/qgis/trunk@13437 c8812cc2-4d05-0410-92ff-de0c093fc19c
- Loading branch information
mmassing
committed
May 7, 2010
1 parent
a9f345f
commit 94ec3d0
Showing
2 changed files
with
258 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
#include "qgsresidualplotitem.h" | ||
#include "qgsgeorefdatapoint.h" | ||
#include <QPainter> | ||
#include <cfloat> | ||
#ifndef Q_OS_MACX | ||
#include <cmath> | ||
#else | ||
#include <math.h> | ||
#endif | ||
|
||
QgsResidualPlotItem::QgsResidualPlotItem( QgsComposition* c ): QgsComposerItem( c ), mConvertScaleToMapUnits( false ), mPixelToMapUnits( 1.0 ) | ||
{ | ||
|
||
} | ||
|
||
QgsResidualPlotItem::~QgsResidualPlotItem() | ||
{ | ||
|
||
} | ||
|
||
void QgsResidualPlotItem::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget ) | ||
{ | ||
if ( mGCPList.size() < 1 || !painter ) | ||
{ | ||
return; | ||
} | ||
|
||
double widthMM = rect().width(); | ||
double heightMM = rect().height(); | ||
|
||
QPen enabledPen( QColor( 0, 0, 255, 255 ) ); | ||
enabledPen.setWidthF( 0.4 ); | ||
QPen disabledPen( QColor( 0, 0, 255, 127 ) ); | ||
disabledPen.setWidthF( 0.3 ); | ||
QBrush enabledBrush( QColor( 255, 0, 0, 255 ) ); | ||
QBrush disabledBrush( QColor( 255, 0, 0, 127 ) ); | ||
|
||
//draw all points and collect minimal mm/pixel ratio | ||
double minMMPixelRatio = DBL_MAX; | ||
double mmPixelRatio = 1; | ||
|
||
painter->setRenderHint( QPainter::Antialiasing, true ); | ||
|
||
QgsGCPList::const_iterator gcpIt = mGCPList.constBegin(); | ||
for ( ; gcpIt != mGCPList.constEnd(); ++gcpIt ) | ||
{ | ||
QgsPoint gcpCoords = ( *gcpIt )->pixelCoords(); | ||
double gcpItemMMX = ( gcpCoords.x() - mExtent.xMinimum() ) / mExtent.width() * widthMM; | ||
double gcpItemMMY = ( 1 - ( gcpCoords.y() - mExtent.yMinimum() ) / mExtent.height() ) * heightMM; | ||
|
||
if (( *gcpIt )->isEnabled() ) | ||
{ | ||
painter->setPen( enabledPen ); | ||
painter->setBrush( enabledBrush ); | ||
} | ||
else | ||
{ | ||
painter->setPen( disabledPen ); | ||
painter->setBrush( disabledBrush ); | ||
} | ||
painter->drawRect( QRectF( gcpItemMMX - 1, gcpItemMMY - 1, 2, 2 ) ); | ||
drawText( painter, gcpItemMMX + 2, gcpItemMMY + 2, QString::number(( *gcpIt )->id() ), QFont() ); | ||
|
||
mmPixelRatio = maxMMToPixelRatioForGCP( *gcpIt, gcpItemMMX, gcpItemMMY ); | ||
if ( mmPixelRatio < minMMPixelRatio ) | ||
{ | ||
minMMPixelRatio = mmPixelRatio; | ||
} | ||
} | ||
|
||
//draw residual arrows | ||
gcpIt = mGCPList.constBegin(); | ||
for ( ; gcpIt != mGCPList.constEnd(); ++gcpIt ) | ||
{ | ||
QgsPoint gcpCoords = ( *gcpIt )->pixelCoords(); | ||
double gcpItemMMX = ( gcpCoords.x() - mExtent.xMinimum() ) / mExtent.width() * widthMM; | ||
double gcpItemMMY = ( 1 - ( gcpCoords.y() - mExtent.yMinimum() ) / mExtent.height() ) * heightMM; | ||
if (( *gcpIt )->isEnabled() ) | ||
{ | ||
painter->setPen( enabledPen ); | ||
} | ||
else | ||
{ | ||
painter->setPen( disabledPen ); | ||
} | ||
|
||
QPointF p1( gcpItemMMX, gcpItemMMY ); | ||
QPointF p2( gcpItemMMX + ( *gcpIt )->residual().x() * minMMPixelRatio, gcpItemMMY + ( *gcpIt )->residual().y() * minMMPixelRatio ); | ||
painter->drawLine( p1, p2 ); | ||
painter->setBrush( QBrush( painter->pen().color() ) ); | ||
drawArrowHead( painter, p2.x(), p2.y(), angle( p1, p2 ), 1 ); | ||
} | ||
|
||
//draw scale bar | ||
double initialScaleBarWidth = rect().width() / 5; | ||
int nUnits; | ||
double scaleBarWidth; | ||
if ( mConvertScaleToMapUnits ) //map units | ||
{ | ||
nUnits = initialScaleBarWidth / minMMPixelRatio * mPixelToMapUnits; | ||
scaleBarWidth = nUnits * minMMPixelRatio / mPixelToMapUnits; | ||
} | ||
else //pixels | ||
{ | ||
nUnits = initialScaleBarWidth / minMMPixelRatio; | ||
scaleBarWidth = nUnits * minMMPixelRatio; | ||
} | ||
|
||
painter->setPen( QColor( 0, 0, 0 ) ); | ||
painter->drawLine( QPointF( 5, rect().height() - 5 ), QPointF( 5 + scaleBarWidth, rect().height() - 5 ) ); | ||
painter->drawLine( QPointF( 5, rect().height() - 5 ), QPointF( 5, rect().height() - 7 ) ); | ||
painter->drawLine( QPointF( 5 + scaleBarWidth, rect().height() - 5 ), QPointF( 5 + scaleBarWidth, rect().height() - 7 ) ); | ||
QFont scaleBarFont; | ||
if ( mConvertScaleToMapUnits ) | ||
{ | ||
drawText( painter, 5, rect().height() - 4 + fontAscentMillimeters( scaleBarFont ), QString( "%1 map units" ).arg( nUnits ), QFont() ); | ||
} | ||
else | ||
{ | ||
drawText( painter, 5, rect().height() - 4 + fontAscentMillimeters( scaleBarFont ), QString( "%1 pixels" ).arg( nUnits ), QFont() ); | ||
} | ||
|
||
drawFrame( painter ); | ||
if ( isSelected() ) | ||
{ | ||
drawSelectionBoxes( painter ); | ||
} | ||
} | ||
|
||
double QgsResidualPlotItem::maxMMToPixelRatioForGCP( const QgsGeorefDataPoint* p, double pixelXMM, double pixelYMM ) | ||
{ | ||
if ( !p ) | ||
{ | ||
return 0; | ||
} | ||
|
||
//calculate intersections with upper / lower frame edge depending on the residual y sign | ||
double upDownDist = DBL_MAX; //distance to frame intersection with lower or upper frame | ||
double leftRightDist = DBL_MAX; //distance to frame intersection with left or right frame | ||
|
||
QPointF residual = p->residual(); | ||
QLineF residualLine( pixelXMM, pixelYMM, pixelXMM + residual.x(), pixelYMM + residual.y() ); | ||
QPointF intersectionPoint; | ||
double dx, dy; | ||
|
||
if ( residual.y() > 0 ) | ||
{ | ||
QLineF lowerFrameLine( 0, rect().height(), rect().width(), rect().height() ); | ||
if ( residualLine.intersect( lowerFrameLine, &intersectionPoint ) != QLineF::NoIntersection ) | ||
{ | ||
upDownDist = dist( QPointF( pixelXMM, pixelYMM ) , intersectionPoint ); | ||
} | ||
} | ||
else if ( residual.y() < 0 ) | ||
{ | ||
QLineF upperFrameLine( 0, 0, mExtent.xMaximum(), 0 ); | ||
if ( residualLine.intersect( upperFrameLine, &intersectionPoint ) != QLineF::NoIntersection ) | ||
{ | ||
upDownDist = dist( QPointF( pixelXMM, pixelYMM ) , intersectionPoint ); | ||
} | ||
} | ||
|
||
//calculate intersection with left / right frame edge depending on the residual x sign | ||
if ( residual.x() > 0 ) | ||
{ | ||
QLineF rightFrameLine( rect().width(), 0, rect().width(), rect().height() ); | ||
if ( residualLine.intersect( rightFrameLine, &intersectionPoint ) != QLineF::NoIntersection ) | ||
{ | ||
leftRightDist = dist( QPointF( pixelXMM, pixelYMM ) , intersectionPoint ); | ||
} | ||
} | ||
else if ( residual.x() < 0 ) | ||
{ | ||
QLineF leftFrameLine( 0, 0 , 0, rect().height() ); | ||
if ( residualLine.intersect( leftFrameLine, &intersectionPoint ) != QLineF::NoIntersection ) | ||
{ | ||
leftRightDist = dist( QPointF( pixelXMM, pixelYMM ) , intersectionPoint ); | ||
} | ||
} | ||
|
||
double resTot = sqrt( residual.x() * residual.x() + residual.y() * residual.y() ); | ||
if ( leftRightDist <= upDownDist ) | ||
{ | ||
return leftRightDist / resTot; | ||
} | ||
else | ||
{ | ||
return upDownDist / resTot; | ||
} | ||
} | ||
|
||
bool QgsResidualPlotItem::writeXML( QDomElement& elem, QDomDocument & doc ) const | ||
{ | ||
return false; | ||
} | ||
|
||
bool QgsResidualPlotItem::readXML( const QDomElement& itemElem, const QDomDocument& doc ) | ||
{ | ||
return false; | ||
} | ||
|
||
double QgsResidualPlotItem::dist( const QPointF& p1, const QPointF& p2 ) const | ||
{ | ||
double dx = p2.x() - p1.x(); | ||
double dy = p2.y() - p1.y(); | ||
return sqrt( dx * dx + dy * dy ); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#ifndef QGSRESIDUALPLOTITEM_H | ||
#define QGSRESIDUALPLOTITEM_H | ||
|
||
#include "qgscomposeritem.h" | ||
#include "qgsgcplist.h" | ||
#include "qgsrectangle.h" | ||
|
||
/**A composer item to visualise the distribution of georeference residuals. For the visualisation, \ | ||
the length of the residual arrows are scaled*/ | ||
class QgsResidualPlotItem: public QgsComposerItem | ||
{ | ||
public: | ||
QgsResidualPlotItem( QgsComposition* c ); | ||
~QgsResidualPlotItem(); | ||
|
||
/** \brief Reimplementation of QCanvasItem::paint*/ | ||
virtual void paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget ); | ||
|
||
void setGCPList( const QgsGCPList& list ) { mGCPList = list; } | ||
QgsGCPList GCPList() const { return mGCPList; } | ||
|
||
void setExtent( const QgsRectangle& rect ) { mExtent = rect;} | ||
QgsRectangle extent() const { return mExtent; } | ||
|
||
void setPixelToMapUnits( double d ) { mPixelToMapUnits = d; } | ||
double pixelToMapUnits() const { return mPixelToMapUnits; } | ||
|
||
void setConvertScaleToMapUnits( bool convert ) { mConvertScaleToMapUnits = convert; } | ||
bool convertScaleToMapUnits() const { return mConvertScaleToMapUnits; } | ||
|
||
virtual bool writeXML( QDomElement& elem, QDomDocument & doc ) const; | ||
virtual bool readXML( const QDomElement& itemElem, const QDomDocument& doc ); | ||
|
||
private: | ||
//gcp list | ||
QgsGCPList mGCPList; | ||
|
||
QgsRectangle mExtent; | ||
/**True if the scale bar units should be converted to map units. This can be done for transformation where the scaling in all directions is the same (helmert)*/ | ||
bool mConvertScaleToMapUnits; | ||
/**Scale factor from pixels to map units*/ | ||
double mPixelToMapUnits; | ||
|
||
/**Calculates maximal possible mm to pixel ratio such that the residual arrow is still inside the frame*/ | ||
double maxMMToPixelRatioForGCP( const QgsGeorefDataPoint* p, double pixelXMM, double pixelYMM ); | ||
|
||
/**Returns distance between two points*/ | ||
double dist( const QPointF& p1, const QPointF& p2 ) const; | ||
}; | ||
|
||
#endif // QGSRESIDUALPLOTITEM_H |