void QgsMeasureDialog::mouseMove( QgsPoint &point )
{
  QSettings settings;
  int decimalPlaces = settings.value( "/qgis/measure/decimalplaces", "3" ).toInt();

  // Create QgsDistance Area for customization ProjectionEnabled setting
  QgsDistanceArea myDa;
  configureDistanceArea( myDa );

  // show current distance/area while moving the point
  // by creating a temporary copy of point array
  // and adding moving point at the end
  if ( mMeasureArea && mTool->points().size() > 1 )
  {
    QList<QgsPoint> tmpPoints = mTool->points();
    tmpPoints.append( point );
    double area = myDa.measurePolygon( tmpPoints );
    editTotal->setText( formatArea( area, decimalPlaces ) );
  }
  else if ( !mMeasureArea && mTool->points().size() > 0 )
  {
    QgsPoint p1( mTool->points().last() ), p2( point );

    double d = myDa.measureLine( p1, p2 );
    editTotal->setText( formatDistance( mTotal + d, decimalPlaces ) );
    QGis::UnitType myDisplayUnits;
    // Ignore units
    convertMeasurement( d, myDisplayUnits, false );
    QTreeWidgetItem *item = mTable->topLevelItem( mTable->topLevelItemCount() - 1 );
    item->setText( 0, QLocale::system().toString( d, 'f', decimalPlaces ) );
  }
}
Example #2
0
void GlobePlugin::syncExtent()
{
  QgsMapCanvas* mapCanvas = mQGisIface->mapCanvas();
  QgsMapRenderer* mapRenderer = mapCanvas->mapRenderer();
  QgsRectangle extent = mapCanvas->extent();

  osgEarth::Util::EarthManipulator* manip = dynamic_cast<osgEarth::Util::EarthManipulator*>( mOsgViewer->getCameraManipulator() );
  //rotate earth to north and perpendicular to camera
  manip->setRotation( osg::Quat() );

  QgsDistanceArea dist;

  dist.setSourceCrs( mapRenderer->destinationCrs().srsid() );
  dist.setEllipsoidalMode( mapRenderer->hasCrsTransformEnabled() );
  dist.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );

  QgsPoint ll = QgsPoint( extent.xMinimum(), extent.yMinimum() );
  QgsPoint ul = QgsPoint( extent.xMinimum(), extent.yMaximum() );
  double height = dist.measureLine( ll, ul );

  //camera viewing angle
  double viewAngle = 30;
  //camera distance
  double distance = height / tan( viewAngle * osg::PI / 180 ); //c = b*cotan(B(rad))

  OE_NOTICE << "map extent: " << height << " camera distance: " << distance << std::endl;

  osgEarth::Util::Viewpoint viewpoint( osg::Vec3d( extent.center().x(), extent.center().y(), 0.0 ), 0.0, -90.0, distance );
  manip->setViewpoint( viewpoint, 4.0 );
}
Example #3
0
double QgsComposerScaleBar::mapWidth() const
{
  if ( !mComposerMap )
  {
    return 0.0;
  }

  QgsRectangle composerMapRect = *( mComposerMap->currentMapExtent() );
  if ( mUnits == MapUnits )
  {
    return composerMapRect.width();
  }
  else
  {
    QgsDistanceArea da;
    da.setEllipsoidalMode( mComposition->mapSettings().hasCrsTransformEnabled() );
    da.setSourceCrs( mComposition->mapSettings().destinationCrs().srsid() );
    da.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", "WGS84" ) );

    double measure = da.measureLine( QgsPoint( composerMapRect.xMinimum(), composerMapRect.yMinimum() ), QgsPoint( composerMapRect.xMaximum(), composerMapRect.yMinimum() ) );
    if ( mUnits == QgsComposerScaleBar::Feet )
    {
      measure /= QGis::fromUnitToUnitFactor( QGis::Feet, QGis::Meters );
    }
    else if ( mUnits == QgsComposerScaleBar::NauticalMiles )
    {
      measure /= QGis::fromUnitToUnitFactor( QGis::NauticalMiles, QGis::Meters );
    }
    return measure;
  }
}
Example #4
0
double QgsComposerScaleBar::mapWidth() const
{
  if ( !mComposerMap )
  {
    return 0.0;
  }

  QgsRectangle composerMapRect = mComposerMap->extent();
  if ( mUnits == MapUnits )
  {
    return composerMapRect.width();
  }
  else
  {
    QgsDistanceArea da;
    da.setEllipsoidalMode( mComposerMap->mapRenderer()->hasCrsTransformEnabled() );
    da.setSourceCrs( mComposerMap->mapRenderer()->destinationCrs().srsid() );
    da.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", "WGS84" ) );

    double measure = da.measureLine( QgsPoint( composerMapRect.xMinimum(), composerMapRect.yMinimum() ), QgsPoint( composerMapRect.xMaximum(), composerMapRect.yMinimum() ) );
    if ( mUnits == Feet )
    {
      measure /= 0.3048;
    }
    return measure;
  }
}
double QgsComposerScaleBar::mapDiagonal() const
{
  if ( !mComposerMap )
  {
    return 0.0;
  }

  QgsRectangle composerMapRect = mComposerMap->extent();
  if ( mUnits == MapUnits )
  {
    return sqrt( composerMapRect.width() * composerMapRect.width() + composerMapRect.height() * composerMapRect.height() );
  }
  else
  {
    QgsDistanceArea da;
    da.setProjectionsEnabled( true );
    da.setSourceCrs( mComposerMap->mapRenderer()->destinationCrs().srsid() );
    QSettings s;
    da.setEllipsoid( s.value( "/qgis/measure/ellipsoid", "WGS84" ).toString() );
    double measure = da.measureLine( QgsPoint( composerMapRect.xMinimum(), composerMapRect.yMaximum() ), QgsPoint( composerMapRect.xMaximum(), composerMapRect.yMinimum() ) );
    if ( mUnits == Feet )
    {
      measure /= 0.3048;
    }
    return measure;
  }
}
double QgsLayoutItemScaleBar::mapWidth() const
{
  if ( !mMap )
  {
    return 0.0;
  }

  QgsRectangle mapExtent = mMap->extent();
  if ( mSettings.units() == QgsUnitTypes::DistanceUnknownUnit )
  {
    return mapExtent.width();
  }
  else
  {
    QgsDistanceArea da;
    da.setSourceCrs( mMap->crs(), mLayout->project()->transformContext() );
    da.setEllipsoid( mLayout->project()->ellipsoid() );

    QgsUnitTypes::DistanceUnit units = da.lengthUnits();
    double measure = da.measureLine( QgsPointXY( mapExtent.xMinimum(), mapExtent.yMinimum() ),
                                     QgsPointXY( mapExtent.xMaximum(), mapExtent.yMinimum() ) );
    measure /= QgsUnitTypes::fromUnitToUnitFactor( mSettings.units(), units );
    return measure;
  }
}
Example #7
0
void GlobePlugin::syncExtent()
{
  osgEarth::Util::EarthManipulator* manip = dynamic_cast<osgEarth::Util::EarthManipulator*>( mOsgViewer->getCameraManipulator() );
  //rotate earth to north and perpendicular to camera
  manip->setRotation( osg::Quat() );

  //get mapCanvas->extent().height() in meters
  QgsRectangle extent = mQGisIface->mapCanvas()->extent();
  QgsDistanceArea dist;
  dist.setEllipsoidalMode( true );
  //dist.setProjectionsEnabled( true );
  QgsPoint ll = QgsPoint( extent.xMinimum(), extent.yMinimum() );
  QgsPoint ul = QgsPoint( extent.xMinimum(), extent.yMaximum() );
  double height = dist.measureLine( ll, ul );

  //camera viewing angle
  double viewAngle = 30;
  //camera distance
  double distance = height / tan( viewAngle * osg::PI / 180 ); //c = b*cotan(B(rad))

  OE_NOTICE << "map extent: " << height << " camera distance: " << distance << std::endl;

  osgEarth::Util::Viewpoint viewpoint( osg::Vec3d( extent.center().x(), extent.center().y(), 0.0 ), 0.0, -90.0, distance );
  manip->setViewpoint( viewpoint, 4.0 );
}
Example #8
0
double Heatmap::mapUnitsOf( double meters, QgsCoordinateReferenceSystem layerCrs )
{
  // Worker to transform metres input to mapunits
  QgsDistanceArea da;
  da.setSourceCrs( layerCrs.srsid() );
  da.setEllipsoid( layerCrs.ellipsoidAcronym() );
  if ( da.geographic() )
  {
    da.setEllipsoidalMode( true );
  }
  return meters / da.measureLine( QgsPoint( 0.0, 0.0 ), QgsPoint( 0.0, 1.0 ) );
}
Example #9
0
void TestQgsDistanceArea::basic()
{
    QgsPoint p1( 1.0, 3.0 ), p2( -2.0, -1.0 );
    QgsDistanceArea daA;
    double resultA, resultB, resultC;

    daA.setEllipsoid( GEO_NONE );
    resultA = daA.measureLine( p1, p2 );
    QCOMPARE( resultA, 5.0 );

    // Now, on an ellipsoid. Always less?
    daA.setSourceCrs( 3006 );
    daA.setEllipsoid( "WGS84" );
    daA.setEllipsoidalMode( true );
    resultA = daA.measureLine( p1, p2 );
    QVERIFY( resultA < 5.0 );

    // Test copy constructor
    QgsDistanceArea daB( daA );
    resultB = daB.measureLine( p1, p2 );
    QCOMPARE( resultA, resultB );

    // Different Ellipsoid
    daB.setEllipsoid( "WGS72" );
    resultB = daB.measureLine( p1, p2 );
    QVERIFY( ! qFuzzyCompare( resultA, resultB ) );

    // Test assignment
    QSharedPointer<QgsDistanceArea> daC( new QgsDistanceArea );
    *daC = daB;
    resultC = daC->measureLine( p1, p2 );
    QCOMPARE( resultB, resultC );

    // Use parameter setting of ellipsoid radii (from WGS72 )
    daA.setEllipsoid( 6378135.0, 6378135.0 - ( 6378135.0 / 298.26 ) );
    resultA = daA.measureLine( p1, p2 );
    QCOMPARE( resultA, resultB );
}
Example #10
0
void TestQgsDistanceArea::measureUnits()
{
    //test regression #13610
    QgsDistanceArea calc;
    calc.setEllipsoidalMode( false );
    calc.setEllipsoid( "NONE" );
    calc.setSourceCrs( 254L );
    QGis::UnitType units;
    QgsPoint p1( 1341683.9854275715, 408256.9562717728 );
    QgsPoint p2( 1349321.7807031618, 408256.9562717728 );

    double result = calc.measureLine( p1, p2, units );
    //no OTF, result will be in CRS unit (feet)
    QCOMPARE( units, QGis::Feet );
    QVERIFY( qgsDoubleNear( result, 7637.7952755903825, 0.001 ) );

    calc.setEllipsoidalMode( true );
    calc.setEllipsoid( "WGS84" );
    result = calc.measureLine( p1, p2, units );
    //OTF, result will be in meters
    QCOMPARE( units, QGis::Meters );
    QVERIFY( qgsDoubleNear( result, 2328.0988253106957, 0.001 ) );
}
Example #11
0
double HeatmapGui::mapUnitsOf( double dist, const QgsCoordinateReferenceSystem& layerCrs ) const
{
  // converter function to transform layer input to mapunits
  // so that bounding box can be updated
  QgsDistanceArea da;
  da.setSourceCrs( layerCrs.srsid() );
  da.setEllipsoid( layerCrs.ellipsoidAcronym() );
  if ( da.geographic() )
  {
    da.setEllipsoidalMode( true );
  }
  double unitDistance = da.measureLine( QgsPoint( 0.0, 0.0 ), QgsPoint( 0.0, 1.0 ) );
  QgsDebugMsg( QString( "Converted %1 layer to %2 map units" ).arg( dist ).arg( dist / unitDistance ) );
  return  dist / unitDistance;
}
Example #12
0
void TestQgsDistanceArea::test_distances()
{
    // Read the file of Geod data
    // Column 0 (first) is latitude point 1
    // Column 1 is longitude point 1
    // Column 3 is latitude point 2
    // Column 4 is longitude point 3
    // Column 6 is the resulting distance in meters on the WGS84 ellipsoid
    // Note: lat is north/south, so the QgsPoint should be ( long, lat )
    // See http://geographiclib.sourceforge.net/html/geodesic.html#testgeod

    // Set up DA
    QgsDistanceArea myDa;
    myDa.setSourceAuthId( "EPSG:4030" );
    myDa.setEllipsoidalMode( true );
    myDa.setEllipsoid( "WGS84" );

    QString myFileName = QString( TEST_DATA_DIR ) + "/GeodTest-nano.dat";

    QFile myFile( myFileName );
    if ( ! myFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
    {
        QFAIL( "Couldn't open file" );
        return;
    }
    QTextStream in( & myFile );
    while ( !in.atEnd() )
    {
        QString line = in.readLine();
        // Some test points (antipodal) does not converge with the chosen algorithm!
        // See calcaulator at http://www.movable-type.co.uk/scripts/latlong-vincenty.html
        // These are commented out.
        if ( line[0] != '#' )
        {
            QStringList myLineList = line.split( ' ' ); // Split fields on space.
            // Create points
            QgsPoint p1( myLineList[1].toDouble(), myLineList[0].toDouble() );
            QgsPoint p2( myLineList[4].toDouble(), myLineList[3].toDouble() );
            double result = myDa.measureLine( p1, p2 );
            // QgsDebugMsg( QString( "Distance from %1 to %2 is %3" ).arg( p1.toString( 15 ) ).arg( p2.toString( 15 ) ).arg( result, 0, 'g', 15 ) );
            // QgsDebugMsg( QString( "Distance should be %1" ).arg( myLineList[6] ) );
            // Check result is less than 0.5mm from expected.
            QVERIFY( qAbs( result -  myLineList[6].toDouble() ) < 0.0005 );
        }
    }

}
Example #13
0
void GlobePlugin::syncExtent()
{
  QgsMapCanvas* mapCanvas = mQGisIface->mapCanvas();
  const QgsMapSettings &mapSettings = mapCanvas->mapSettings();
  QgsRectangle extent = mapCanvas->extent();

  long epsgGlobe = 4326;
  QgsCoordinateReferenceSystem globeCrs;
  globeCrs.createFromOgcWmsCrs( QString( "EPSG:%1" ).arg( epsgGlobe ) );

  // transform extent to WGS84
  if ( mapSettings.destinationCrs().authid().compare( QString( "EPSG:%1" ).arg( epsgGlobe ), Qt::CaseInsensitive ) != 0 )
  {
    QgsCoordinateReferenceSystem srcCRS( mapSettings.destinationCrs() );
    QgsCoordinateTransform* coordTransform = new QgsCoordinateTransform( srcCRS, globeCrs );
    extent = coordTransform->transformBoundingBox( extent );
    delete coordTransform;
  }

  osgEarth::Util::EarthManipulator* manip = dynamic_cast<osgEarth::Util::EarthManipulator*>( mOsgViewer->getCameraManipulator() );
  //rotate earth to north and perpendicular to camera
  manip->setRotation( osg::Quat() );

  QgsDistanceArea dist;

  dist.setSourceCrs( globeCrs );
  dist.setEllipsoidalMode( true );
  dist.setEllipsoid( "WGS84" );

  QgsPoint ll = QgsPoint( extent.xMinimum(), extent.yMinimum() );
  QgsPoint ul = QgsPoint( extent.xMinimum(), extent.yMaximum() );
  double height = dist.measureLine( ll, ul );

  //camera viewing angle
  double viewAngle = 30;
  //camera distance
  double distance = height / tan( viewAngle * osg::PI / 180 ); //c = b*cotan(B(rad))

  OE_NOTICE << "map extent: " << height << " camera distance: " << distance << std::endl;

  osgEarth::Util::Viewpoint viewpoint( osg::Vec3d( extent.center().x(), extent.center().y(), 0.0 ), 0.0, -90.0, distance );
  manip->setViewpoint( viewpoint, 4.0 );
}
Example #14
0
double QgsComposerScaleBar::mapWidth() const
{
  if ( !mComposerMap )
  {
    return 0.0;
  }

  QgsRectangle composerMapRect = *( mComposerMap->currentMapExtent() );
  if ( mUnits == MapUnits )
  {
    return composerMapRect.width();
  }
  else
  {
    QgsDistanceArea da;
    da.setEllipsoidalMode( mComposition->mapSettings().hasCrsTransformEnabled() );
    da.setSourceCrs( mComposition->mapSettings().destinationCrs().srsid() );
    da.setEllipsoid( mComposition->project()->ellipsoid() );

    QgsUnitTypes::DistanceUnit units = QgsUnitTypes::DistanceMeters;
    double measure = da.measureLine( QgsPoint( composerMapRect.xMinimum(), composerMapRect.yMinimum() ),
                                     QgsPoint( composerMapRect.xMaximum(), composerMapRect.yMinimum() ),
                                     units );
    switch ( mUnits )
    {
      case QgsComposerScaleBar::Feet:
        measure /= QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceFeet, units );
        break;
      case QgsComposerScaleBar::NauticalMiles:
        measure /= QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceNauticalMiles, units );
        break;
      case QgsComposerScaleBar::Meters:
        measure /= QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceMeters, units );
        break;
      case QgsComposerScaleBar::MapUnits:
        //avoid warning
        break;
    }
    return measure;
  }
}
void QgsBullsEyeWidget::createLayer( QString layerName )
{
  if ( layerName.isEmpty() )
  {
    layerName = QInputDialog::getText( this, tr( "Layer Name" ), tr( "Enter name of new layer:" ) );
  }
  if ( !layerName.isEmpty() )
  {
    QgsDistanceArea da;
    da.setEllipsoid( "WGS84" );
    da.setEllipsoidalMode( true );
    da.setSourceCrs( mCanvas->mapSettings().destinationCrs() );
    QgsRectangle extent = mCanvas->extent();
    double extentHeight = da.measureLine( QgsPoint( extent.center().x(), extent.yMinimum() ), QgsPoint( extent.center().x(), extent.yMaximum() ) );
    double interval = 0.5 * extentHeight * QGis::fromUnitToUnitFactor( QGis::Meters, QGis::NauticalMiles ) / 6; // Half height divided by nr rings+1, in nm
    QgsBullsEyeLayer* bullEyeLayer = new QgsBullsEyeLayer( layerName );
    bullEyeLayer->setup( mCanvas->extent().center(), mCanvas->mapSettings().destinationCrs(), 5, interval, 45 );
    QgsMapLayerRegistry::instance()->addMapLayer( bullEyeLayer );
    mLayerTreeView->setCurrentLayer( bullEyeLayer );
  }
}
void QgsMeasureDialog::addPoint( QgsPoint &point )
{
  QSettings settings;
  int decimalPlaces = settings.value( "/qgis/measure/decimalplaces", "3" ).toInt();

  // Create QgsDistance Area for customization ProjectionEnabled setting
  QgsDistanceArea myDa;
  configureDistanceArea( myDa );

  int numPoints = mTool->points().size();
  if ( mMeasureArea && numPoints > 2 )
  {
    double area = myDa.measurePolygon( mTool->points() );
    editTotal->setText( formatArea( area, decimalPlaces ) );
  }
  else if ( !mMeasureArea && numPoints > 1 )
  {
    int last = numPoints - 2;

    QgsPoint p1 = mTool->points()[last], p2 = mTool->points()[last+1];

    double d = myDa.measureLine( p1, p2 );

    mTotal += d;
    editTotal->setText( formatDistance( mTotal, decimalPlaces ) );

    QGis::UnitType myDisplayUnits;
    // Ignore units
    convertMeasurement( d, myDisplayUnits, false );

    QTreeWidgetItem *item = mTable->topLevelItem( mTable->topLevelItemCount() - 1 );
    item->setText( 0, QLocale::system().toString( d, 'f', decimalPlaces ) );

    item = new QTreeWidgetItem( QStringList( QLocale::system().toString( 0.0, 'f', decimalPlaces ) ) );
    item->setTextAlignment( 0, Qt::AlignRight );
    mTable->addTopLevelItem( item );
    mTable->scrollToItem( item );
  }
}
Example #17
0
bool QgsTransectSample::otherTransectWithinDistance( QgsGeometry* geom, double minDistLayerUnit, double minDistance, QgsSpatialIndex& sIndex,
    const QMap< QgsFeatureId, QgsGeometry* >& lineFeatureMap, QgsDistanceArea& da )
{
  if ( !geom )
  {
    return false;
  }

  QgsGeometry* buffer = geom->buffer( minDistLayerUnit, 8 );
  if ( !buffer )
  {
    return false;
  }
  QgsRectangle rect = buffer->boundingBox();
  QList<QgsFeatureId> lineIdList = sIndex.intersects( rect );

  QList<QgsFeatureId>::const_iterator lineIdIt = lineIdList.constBegin();
  for ( ; lineIdIt != lineIdList.constEnd(); ++lineIdIt )
  {
    const QMap< QgsFeatureId, QgsGeometry* >::const_iterator idMapIt = lineFeatureMap.find( *lineIdIt );
    if ( idMapIt != lineFeatureMap.constEnd() )
    {
      double dist = 0;
      QgsPoint pt1, pt2;
      closestSegmentPoints( *geom, *( idMapIt.value() ), dist, pt1, pt2 );
      dist = da.measureLine( pt1, pt2 ); //convert degrees to meters if necessary

      if ( dist < minDistance )
      {
        delete buffer;
        return true;
      }
    }
  }

  delete buffer;
  return false;
}
void QgsMapToolViewshed::drawFinished()
{
  QString layerid = QgsProject::instance()->readEntry( "Heightmap", "layer" );
  QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerid );
  if ( !layer || layer->type() != QgsMapLayer::RasterLayer )
  {
    QgisApp::instance()->messageBar()->pushMessage( tr( "No heightmap is defined in the project." ), tr( "Right-click a raster layer in the layer tree and select it to be used as heightmap." ), QgsMessageBar::INFO, 10 );
    reset();
    return;
  }

  QgsCoordinateReferenceSystem canvasCrs = canvas()->mapSettings().destinationCrs();
  double curRadius;
  QgsPoint center;
  double trash;
  getPart( 0, center, curRadius, trash, trash );

  QGis::UnitType measureUnit = canvasCrs.mapUnits();
  QgsDistanceArea().convertMeasurement( curRadius, measureUnit, QGis::Meters, false );

  QgsViewshedDialog viewshedDialog( curRadius );
  connect( &viewshedDialog, SIGNAL( radiusChanged( double ) ), this, SLOT( adjustRadius( double ) ) );
  if ( viewshedDialog.exec() == QDialog::Rejected )
  {
    reset();
    return;
  }

  QString outputFileName = QString( "viewshed_%1,%2.tif" ).arg( center.x() ).arg( center.y() );
  QString outputFile = QgsTemporaryFile::createNewFile( outputFileName );

  QVector<QgsPoint> filterRegion;
  QgsPolygon poly = QgsGeometry( getRubberBand()->geometry()->clone() ).asPolygon();
  if ( !poly.isEmpty() )
  {
    filterRegion = poly.front();
  }
  getPart( 0, center, curRadius, trash, trash );

  if ( mCanvas->mapSettings().mapUnits() == QGis::Degrees )
  {
    // Need to compute radius in meters
    QgsDistanceArea da;
    da.setSourceCrs( mCanvas->mapSettings().destinationCrs() );
    da.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
    da.setEllipsoidalMode( mCanvas->mapSettings().hasCrsTransformEnabled() );
    curRadius = da.measureLine( center, QgsPoint( center.x() + curRadius, center.y() ) );
    QGis::UnitType measureUnits = mCanvas->mapSettings().mapUnits();
    da.convertMeasurement( curRadius, measureUnits, QGis::Meters, false );
  }

  double heightConv = QGis::fromUnitToUnitFactor( QgsCoordinateFormat::instance()->getHeightDisplayUnit(), QGis::Meters );

  QProgressDialog p( tr( "Calculating viewshed..." ), tr( "Abort" ), 0, 0 );
  p.setWindowTitle( tr( "Viewshed" ) );
  p.setWindowModality( Qt::ApplicationModal );
  bool displayVisible = viewshedDialog.getDisplayMode() == QgsViewshedDialog::DisplayVisibleArea;
  int accuracyFactor = viewshedDialog.getAccuracyFactor();
  QApplication::setOverrideCursor( Qt::WaitCursor );
  bool success = QgsViewshed::computeViewshed( layer->source(), outputFile, "GTiff", center, canvasCrs, viewshedDialog.getObserverHeight() * heightConv, viewshedDialog.getTargetHeight() * heightConv, viewshedDialog.getHeightRelativeToGround(), curRadius, QGis::Meters, filterRegion, displayVisible, accuracyFactor, &p );
  QApplication::restoreOverrideCursor();
  if ( success )
  {
    QgsRasterLayer* layer = new QgsRasterLayer( outputFile, tr( "Viewshed [%1]" ).arg( center.toString() ) );
    QgsColorRampShader* rampShader = new QgsColorRampShader();
    if ( displayVisible )
    {
      QList<QgsColorRampShader::ColorRampItem> colorRampItems = QList<QgsColorRampShader::ColorRampItem>()
          << QgsColorRampShader::ColorRampItem( 0, QColor( 0, 0, 0, 0 ), "" )
          << QgsColorRampShader::ColorRampItem( 255, QColor( 0, 255, 0 ), tr( "Visible" ) );
      rampShader->setColorRampItemList( colorRampItems );
    }
    else
    {
      QList<QgsColorRampShader::ColorRampItem> colorRampItems = QList<QgsColorRampShader::ColorRampItem>()
          << QgsColorRampShader::ColorRampItem( 0, QColor( 0, 0, 0, 0 ), "" )
          << QgsColorRampShader::ColorRampItem( 0, QColor( 255, 0, 0 ), tr( "Invisible" ) );
      rampShader->setColorRampItemList( colorRampItems );
    }
    QgsRasterShader* shader = new QgsRasterShader();
    shader->setRasterShaderFunction( rampShader );
    QgsSingleBandPseudoColorRenderer* renderer = new QgsSingleBandPseudoColorRenderer( 0, 1, shader );
    layer->setRenderer( renderer );
    QgsMapLayerRegistry::instance()->addMapLayer( layer );
    QgsPinAnnotationItem* pin = new QgsPinAnnotationItem( canvas() );
    pin->setMapPosition( center, canvasCrs );
    pin->setItemFlags( pin->itemFlags() | QgsAnnotationItem::ItemMapPositionLocked );
    QgisApp::instance()->itemCouplingManager()->addCoupling( layer, pin );
  }
  else
  {
    QMessageBox::critical( 0, tr( "Error" ), tr( "Failed to compute viewshed." ) );
  }
  reset();
}
void QgsMeasureDialog::changeProjectionEnabledState()
{
  // store value
  QSettings settings;
  if ( mcbProjectionEnabled->isChecked() )
    settings.setValue( "/qgis/measure/projectionEnabled", 2 );
  else
    settings.setValue( "/qgis/measure/projectionEnabled", 0 );

  // clear interface
  mTable->clear();
  QTreeWidgetItem* item = new QTreeWidgetItem( QStringList( QString::number( 0, 'f', 1 ) ) );
  item->setTextAlignment( 0, Qt::AlignRight );
  mTable->addTopLevelItem( item );
  mTotal = 0;
  updateUi();

  int decimalPlaces = settings.value( "/qgis/measure/decimalplaces", "3" ).toInt();

  // create DistanceArea
  QgsDistanceArea myDa;
  configureDistanceArea( myDa );

  if ( mMeasureArea )
  {
    double area = 0.0;
    if ( mTool->points().size() > 1 )
    {
      area = myDa.measurePolygon( mTool->points() );
    }
    editTotal->setText( formatArea( area, decimalPlaces ) );
  }
  else
  {
    QList<QgsPoint>::const_iterator it;
    bool b = true; // first point

    QgsPoint p1, p2;

    for ( it = mTool->points().constBegin(); it != mTool->points().constEnd(); ++it )
    {
      p2 = *it;
      if ( !b )
      {
        double d  = myDa.measureLine( p1, p2 );
        mTotal += d;
        editTotal->setText( formatDistance( mTotal, decimalPlaces ) );
        QGis::UnitType myDisplayUnits;

        convertMeasurement( d, myDisplayUnits, false );

        QTreeWidgetItem *item = mTable->topLevelItem( mTable->topLevelItemCount() - 1 );
        item->setText( 0, QLocale::system().toString( d, 'f', decimalPlaces ) );
        item = new QTreeWidgetItem( QStringList( QLocale::system().toString( 0.0, 'f', decimalPlaces ) ) );
        item->setTextAlignment( 0, Qt::AlignRight );
        mTable->addTopLevelItem( item );
        mTable->scrollToItem( item );
      }
      p1 = p2;
      b = false;
    }
  }
}
void RgLineVectorLayerDirector::makeGraph( RgGraphBuilder *builder, const QVector< QgsPoint >& additionalPoints,
    QVector< QgsPoint >& tiedPoint ) const
{
  QgsVectorLayer *vl = myLayer();

  if ( vl == NULL )
    return;

  int featureCount = ( int ) vl->featureCount() * 2;
  int step = 0;

  QgsCoordinateTransform ct;
  QgsDistanceArea da;
  ct.setSourceCrs( vl->crs() );

  if ( builder->coordinateTransformEnabled() )
  {
    ct.setDestCRS( builder->destinationCrs() );
    da.setProjectionsEnabled( true );
    //
    //da.setSourceCrs( builder->destinationCrs().srsid() );
    //
  }
  else
  {
    ct.setDestCRS( vl->crs() );
    da.setProjectionsEnabled( false );
  }

  tiedPoint = QVector< QgsPoint >( additionalPoints.size(), QgsPoint( 0.0, 0.0 ) );
  TiePointInfo tmpInfo;
  tmpInfo.mLength = infinity();

  QVector< TiePointInfo > pointLengthMap( additionalPoints.size(), tmpInfo );
  QVector< TiePointInfo >::iterator pointLengthIt;

  // begin: tie points to the graph
  QgsAttributeList la;
  vl->select( la );
  QgsFeature feature;
  while ( vl->nextFeature( feature ) )
  {
    QgsMultiPolyline mpl;
    if ( feature.geometry()->wkbType() == QGis::WKBLineString )
    {
      mpl.push_back( feature.geometry()->asPolyline() );
    }else if ( feature.geometry()->wkbType() == QGis::WKBMultiLineString )
    {
      mpl = feature.geometry()->asMultiPolyline();
    }

    QgsMultiPolyline::iterator mplIt;
    for ( mplIt = mpl.begin(); mplIt != mpl.end(); ++mplIt )
    {
      QgsPoint pt1, pt2;
      bool isFirstPoint = true;
      QgsPolyline::iterator pointIt;
      for ( pointIt = mplIt->begin(); pointIt != mplIt->end(); ++pointIt )
      {
        pt2 = builder->addVertex( ct.transform( *pointIt ) );
        if ( !isFirstPoint )
        {
          int i = 0;
          for ( i = 0; i != additionalPoints.size(); ++i )
          {
            TiePointInfo info;
            if ( pt1 == pt2 )
            {
              info.mLength = additionalPoints[ i ].sqrDist( pt1 );
              info.mTiedPoint = pt1;
            }
            else
            {
              info.mLength = additionalPoints[ i ].sqrDistToSegment( pt1.x(), pt1.y(), pt2.x(), pt2.y(), info.mTiedPoint );
            }
            if ( pointLengthMap[ i ].mLength > info.mLength )
            {
              info.mTiedPoint = builder->addVertex( info.mTiedPoint );
              info.mFirstPoint = pt1;
              info.mLastPoint = pt2;

              pointLengthMap[ i ] = info;
              tiedPoint[ i ] = info.mTiedPoint;
            }
          }
        }
        pt1 = pt2;
        isFirstPoint = false;
      }
    }
    emit buildProgress( ++step, featureCount );
  }
  // end: tie points to graph

  if ( mDirectionFieldId != -1 )
  {
    la.push_back( mDirectionFieldId );
  }
  if ( mSpeedFieldId != -1 )
  {
    la.push_back( mSpeedFieldId );
  }

  SpeedUnit su = SpeedUnit::byName( mSpeedUnitName );

  // begin graph construction
  vl->select( la );
  while ( vl->nextFeature( feature ) )
  {
    QgsAttributeMap attr = feature.attributeMap();
    int directionType = mDefaultDirection;
    QgsAttributeMap::const_iterator it;
    // What direction have feature?
    for ( it = attr.constBegin(); it != attr.constEnd(); ++it )
    {
      if ( it.key() != mDirectionFieldId )
      {
        continue;
      }
      QString str = it.value().toString();
      if ( str == mBothDirectionValue )
      {
        directionType = 3;
      }
      else if ( str == mDirectDirectionValue )
      {
        directionType = 1;
      }
      else if ( str == mReverseDirectionValue )
      {
        directionType = 2;
      }
    }
    // What speed have feature?
    double speed = 0.0;
    for ( it = attr.constBegin(); it != attr.constEnd(); ++it )
    {
      if ( it.key() != mSpeedFieldId )
      {
        continue;
      }
      speed = it.value().toDouble();
    }
    if ( speed <= 0.0 )
    {
      speed = mDefaultSpeed;
    }

    // begin features segments and add arc to the Graph;
    QgsMultiPolyline mpl;
    if ( feature.geometry()->wkbType() == QGis::WKBLineString )
    {
      mpl.push_back( feature.geometry()->asPolyline() );
    }else if ( feature.geometry()->wkbType() == QGis::WKBMultiLineString )
    {
      mpl = feature.geometry()->asMultiPolyline();
    }
    QgsMultiPolyline::iterator mplIt;
    for ( mplIt = mpl.begin(); mplIt != mpl.end(); ++mplIt )
    {
      QgsPoint pt1, pt2;
      bool isFirstPoint = true;
      QgsPolyline::iterator pointIt;
      for ( pointIt = mplIt->begin(); pointIt != mplIt->end(); ++pointIt )
      {
        pt2 = builder->addVertex( ct.transform( *pointIt ) );

        std::map< double, QgsPoint > pointsOnArc;
        pointsOnArc[ 0.0 ] = pt1;
        pointsOnArc[ pt1.sqrDist( pt2 )] = pt2;

        for ( pointLengthIt = pointLengthMap.begin(); pointLengthIt != pointLengthMap.end(); ++pointLengthIt )
        {
          if ( pointLengthIt->mFirstPoint == pt1 && pointLengthIt->mLastPoint == pt2 )
          {
            QgsPoint tiedPoint = pointLengthIt->mTiedPoint;
            pointsOnArc[ pt1.sqrDist( tiedPoint )] = tiedPoint;
          }
        }

        if ( !isFirstPoint )
        {
          std::map< double, QgsPoint >::iterator pointsIt;
          QgsPoint pt1;
          QgsPoint pt2;
          bool isFirstPoint = true;
          for ( pointsIt = pointsOnArc.begin(); pointsIt != pointsOnArc.end(); ++pointsIt )
          {
            pt2 = pointsIt->second;
            if ( !isFirstPoint )
            {
              double cost = da.measureLine( pt1, pt2 );
              if ( directionType == 1 ||
                   directionType == 3 )
              {
                builder->addArc( pt1, pt2, cost, speed*su.multipler(), feature.id() );
              }
              if ( directionType == 2 ||
                   directionType == 3 )
              {
                builder->addArc( pt2, pt1, cost, speed*su.multipler(), feature.id() );
              }
            }
            pt1 = pt2;
            isFirstPoint = false;
          }
        } // if ( !isFirstPoint )
        pt1 = pt2;
        isFirstPoint = false;
      }
    } // for (it = pl.begin(); it != pl.end(); ++it)
    emit buildProgress( ++step, featureCount );
  } // while( vl->nextFeature(feature) )
} // makeGraph( RgGraphBuilder *builder, const QgsRectangle& rt )