26
26
#include < QFileInfo>
27
27
#include < QRegExp>
28
28
#include < QTextStream>
29
+ #include < QFile>
29
30
30
31
#include " qgsapplication.h"
31
32
#include " qgscrscache.h"
@@ -1509,9 +1510,119 @@ QString QgsCoordinateReferenceSystem::quotedValue( QString value )
1509
1510
return value.prepend ( " '" ).append ( " '" );
1510
1511
}
1511
1512
1513
+ // adapted from gdal/ogr/ogr_srs_dict.cpp
1514
+ bool QgsCoordinateReferenceSystem::loadWkts ( QHash<int , QString> &wkts, const char *filename )
1515
+ {
1516
+ qDebug ( " Loading %s" , filename );
1517
+ const char *pszFilename = CPLFindFile ( " gdal" , filename );
1518
+ if ( !pszFilename )
1519
+ return false ;
1520
+
1521
+ QFile csv ( pszFilename );
1522
+ if ( !csv.open ( QIODevice::ReadOnly ) )
1523
+ return false ;
1524
+
1525
+ QTextStream lines ( &csv );
1526
+
1527
+ for ( ;; )
1528
+ {
1529
+ QString line = lines.readLine ();
1530
+ if ( line.isNull () )
1531
+ break ;
1532
+
1533
+ if ( line.startsWith ( ' #' ) )
1534
+ {
1535
+ continue ;
1536
+ }
1537
+ else if ( line.startsWith ( " include " ) )
1538
+ {
1539
+ if ( !loadWkts ( wkts, line.mid ( 8 ).toUtf8 () ) )
1540
+ break ;
1541
+ }
1542
+ else
1543
+ {
1544
+ int pos = line.indexOf ( " ," );
1545
+ if ( pos < 0 )
1546
+ return false ;
1547
+
1548
+ bool ok;
1549
+ int epsg = line.left ( pos ).toInt ( &ok );
1550
+ if ( !ok )
1551
+ return false ;
1552
+
1553
+ wkts.insert ( epsg, line.mid ( pos + 1 ) );
1554
+ }
1555
+ }
1556
+
1557
+ csv.close ();
1558
+
1559
+ return true ;
1560
+ }
1561
+
1562
+ bool QgsCoordinateReferenceSystem::loadIDs ( QHash<int , QString> &wkts )
1563
+ {
1564
+ OGRSpatialReferenceH crs = OSRNewSpatialReference ( NULL );
1565
+
1566
+ foreach ( QString csv, QStringList () << " gcs.csv" << " pcs.csv" << " vertcs.csv" << " compdcs.csv" << " geoccs.csv" )
1567
+ {
1568
+ QString filename = CPLFindFile ( " gdal" , csv.toUtf8 () );
1569
+
1570
+ QFile f ( filename );
1571
+ if ( !f.open ( QIODevice::ReadOnly ) )
1572
+ continue ;
1573
+
1574
+ QTextStream lines ( &f );
1575
+ int l = 0 , n = 0 ;
1576
+
1577
+ lines.readLine ();
1578
+ for ( ;; )
1579
+ {
1580
+ l++;
1581
+ QString line = lines.readLine ();
1582
+ if ( line.isNull () )
1583
+ break ;
1584
+
1585
+ int pos = line.indexOf ( " ," );
1586
+ if ( pos < 0 )
1587
+ continue ;
1588
+
1589
+ bool ok;
1590
+ int epsg = line.left ( pos ).toInt ( &ok );
1591
+ if ( !ok )
1592
+ continue ;
1593
+
1594
+ if ( OSRImportFromEPSG ( crs, epsg ) != OGRERR_NONE )
1595
+ {
1596
+ qDebug ( " EPSG %d: not imported" , epsg );
1597
+ continue ;
1598
+ }
1599
+
1600
+ char *wkt = 0 ;
1601
+ if ( OSRExportToWkt ( crs, &wkt ) != OGRERR_NONE )
1602
+ {
1603
+ qWarning ( " EPSG %d: not exported to WKT" , epsg );
1604
+ continue ;
1605
+ }
1606
+
1607
+ wkts.insert ( epsg, wkt );
1608
+ n++;
1609
+
1610
+ OGRFree ( wkt );
1611
+ }
1612
+
1613
+ f.close ();
1614
+
1615
+ qDebug ( " Loaded %d/%d from %s" , n, l, filename.toUtf8 ().constData () );
1616
+ }
1617
+
1618
+ OSRDestroySpatialReference ( crs );
1619
+
1620
+ return true ;
1621
+ }
1622
+
1512
1623
int QgsCoordinateReferenceSystem::syncDb ()
1513
1624
{
1514
- int updated = 0 , errors = 0 ;
1625
+ int inserted = 0 , updated = 0 , deleted = 0 , errors = 0 ;
1515
1626
1516
1627
sqlite3 *database;
1517
1628
if ( sqlite3_open ( QgsApplication::srsDbFilePath ().toUtf8 ().constData (), &database ) != SQLITE_OK )
@@ -1524,54 +1635,154 @@ int QgsCoordinateReferenceSystem::syncDb()
1524
1635
{
1525
1636
qCritical ( " Could not begin transaction: %s [%s]\n " , QgsApplication::srsDbFilePath ().toLocal8Bit ().constData (), sqlite3_errmsg ( database ) );
1526
1637
return -1 ;
1638
+
1527
1639
}
1528
1640
1641
+ sqlite3_exec ( database, " UPDATE tbl_srs SET srid=141001 WHERE srid=41001 AND auth_name='OSGEO' AND auth_id='41001'" , 0 , 0 , 0 );
1642
+
1643
+ OGRSpatialReferenceH crs = OSRNewSpatialReference ( NULL );
1529
1644
const char *tail;
1530
1645
sqlite3_stmt *select;
1531
- QString sql = " select auth_name,auth_id,parameters from tbl_srs WHERE auth_name IS NOT NULL AND auth_id IS NOT NULL order by deprecated" ;
1532
- if ( sqlite3_prepare ( database, sql.toAscii (), sql.size (), &select, &tail ) != SQLITE_OK )
1533
- {
1534
- qCritical ( " Could not prepare: %s [%s]\n " , sql.toAscii ().constData (), sqlite3_errmsg ( database ) );
1535
- sqlite3_close ( database );
1536
- return -1 ;
1537
- }
1646
+ char *errMsg = NULL ;
1538
1647
1539
- OGRSpatialReferenceH crs = OSRNewSpatialReference ( NULL );
1648
+ QString sql;
1649
+ QHash<int , QString> wkts;
1650
+ loadIDs ( wkts );
1651
+ loadWkts ( wkts, " epsg.wkt" );
1540
1652
1541
- while ( sqlite3_step ( select ) == SQLITE_ROW )
1653
+ qDebug ( " %d WKTs loaded" , wkts.count () );
1654
+
1655
+ for ( QHash<int , QString>::const_iterator it = wkts.constBegin (); it != wkts.constEnd (); ++it )
1542
1656
{
1543
- const char *auth_name = ( const char * ) sqlite3_column_text ( select, 0 );
1544
- const char *auth_id = ( const char * ) sqlite3_column_text ( select, 1 );
1545
- const char *params = ( const char * ) sqlite3_column_text ( select, 2 );
1657
+ QByteArray ba ( it.value ().toUtf8 () );
1658
+ char *psz = ba.data ();
1659
+ OGRErr ogrErr = OSRImportFromWkt ( crs, &psz );
1660
+ if ( ogrErr != OGRERR_NONE )
1661
+ {
1662
+ continue ;
1663
+ }
1546
1664
1547
- QString proj4;
1665
+ if ( OSRExportToProj4 ( crs, &psz ) != OGRERR_NONE )
1666
+ continue ;
1667
+
1668
+ QString proj4 ( psz );
1669
+ proj4 = proj4.trimmed ();
1548
1670
1549
- if ( QString ( auth_name ).compare ( " epsg" , Qt::CaseInsensitive ) == 0 )
1671
+ CPLFree ( psz );
1672
+
1673
+ if ( proj4.isEmpty () )
1550
1674
{
1551
- OGRErr ogrErr = OSRSetFromUserInput ( crs, QString ( " epsg:%1" ).arg ( auth_id ).toAscii () );
1675
+ continue ;
1676
+ }
1677
+
1678
+ sql = QString ( " SELECT parameters FROM tbl_srs WHERE auth_name='EPSG' AND auth_id='%1'" ).arg ( it.key () );
1679
+ if ( sqlite3_prepare ( database, sql.toAscii (), sql.size (), &select, &tail ) != SQLITE_OK )
1680
+ {
1681
+ qCritical ( " Could not prepare: %s [%s]\n " , sql.toAscii ().constData (), sqlite3_errmsg ( database ) );
1682
+ continue ;
1683
+ }
1684
+
1685
+ QString srsProj4;
1686
+ if ( sqlite3_step ( select ) == SQLITE_ROW )
1687
+ {
1688
+ srsProj4 = ( const char * ) sqlite3_column_text ( select, 0 );
1689
+ }
1552
1690
1553
- if ( ogrErr == OGRERR_NONE )
1691
+ sqlite3_finalize ( select );
1692
+
1693
+ if ( !srsProj4.isEmpty () )
1694
+ {
1695
+ if ( proj4 != srsProj4 )
1554
1696
{
1555
- char *output = 0 ;
1697
+ errMsg = NULL ;
1698
+ sql = QString ( " UPDATE tbl_srs SET parameters=%1 WHERE auth_name='EPSG' AND auth_id=%2" ).arg ( quotedValue ( proj4 ) ).arg ( it.key () );
1556
1699
1557
- if ( OSRExportToProj4 ( crs, &output ) == OGRERR_NONE )
1700
+ if ( sqlite3_exec ( database, sql. toUtf8 (), 0 , 0 , &errMsg ) != SQLITE_OK )
1558
1701
{
1559
- proj4 = output;
1560
- proj4 = proj4.trimmed ();
1702
+ qCritical ( " Could not execute: %s [%s/%s]\n " ,
1703
+ sql.toLocal8Bit ().constData (),
1704
+ sqlite3_errmsg ( database ),
1705
+ errMsg ? errMsg : " (unknown error)" );
1706
+ errors++;
1561
1707
}
1562
1708
else
1563
1709
{
1564
- QgsDebugMsg ( QString ( " could not retrieve proj.4 string for epsg:%1 from OGR" ).arg ( auth_id ) );
1710
+ updated++;
1711
+ QgsDebugMsgLevel ( QString ( " SQL: %1\n OLD:%2\n NEW:%3" ).arg ( sql ).arg ( srsProj4 ).arg ( proj4 ), 3 );
1565
1712
}
1713
+ }
1714
+ }
1715
+ else
1716
+ {
1717
+ QRegExp projRegExp ( " \\ +proj=(\\ S+)" );
1718
+ if ( projRegExp.indexIn ( proj4 ) < 0 )
1719
+ {
1720
+ QgsDebugMsg ( QString ( " EPSG %1: no +proj argument found [%2]" ).arg ( it.key () ).arg ( proj4 ) );
1721
+ continue ;
1722
+ }
1566
1723
1567
- if ( output )
1568
- CPLFree ( output );
1724
+ QRegExp ellipseRegExp ( " \\ +ellps=(\\ S+)" );
1725
+ QString ellps;
1726
+ if ( ellipseRegExp.indexIn ( proj4 ) >= 0 )
1727
+ {
1728
+ ellps = ellipseRegExp.cap ( 1 );
1729
+ }
1730
+
1731
+ QString name ( OSRIsGeographic ( crs ) ? OSRGetAttrValue ( crs, " GEOCS" , 0 ) : OSRGetAttrValue ( crs, " PROJCS" , 0 ) );
1732
+ if ( name.isEmpty () )
1733
+ name = QObject::tr ( " Imported from GDAL" );
1734
+
1735
+ sql = QString ( " INSERT INTO tbl_srs(description,projection_acronym,ellipsoid_acronym,parameters,srid,auth_name,auth_id,is_geo,deprecated) VALUES (%1,%2,%3,%4,%5,'EPSG',%5,%6,0)" )
1736
+ .arg ( quotedValue ( name ) )
1737
+ .arg ( quotedValue ( projRegExp.cap ( 1 ) ) )
1738
+ .arg ( quotedValue ( ellps ) )
1739
+ .arg ( quotedValue ( proj4 ) )
1740
+ .arg ( it.key () )
1741
+ .arg ( OSRIsGeographic ( crs ) );
1742
+
1743
+ errMsg = NULL ;
1744
+ if ( sqlite3_exec ( database, sql.toUtf8 (), 0 , 0 , &errMsg ) == SQLITE_OK )
1745
+ {
1746
+ inserted++;
1747
+ }
1748
+ else
1749
+ {
1750
+ qCritical ( " Could not execute: %s [%s/%s]\n " ,
1751
+ sql.toLocal8Bit ().constData (),
1752
+ sqlite3_errmsg ( database ),
1753
+ errMsg ? errMsg : " (unknown error)" );
1754
+ errors++;
1755
+
1756
+ if ( errMsg )
1757
+ sqlite3_free ( errMsg );
1569
1758
}
1570
1759
}
1760
+ }
1761
+
1762
+ sql = " DELETE FROM tbl_srs WHERE auth_name='EPSG' AND NOT auth_id IN (" ;
1763
+ QString delim;
1764
+ foreach ( int i, wkts.keys () )
1765
+ {
1766
+ sql += delim + QString::number ( i );
1767
+ delim = " ," ;
1768
+ }
1769
+ sql += " )" ;
1770
+
1771
+ if ( sqlite3_exec ( database, sql.toUtf8 (), 0 , 0 , 0 ) == SQLITE_OK )
1772
+ {
1773
+ deleted = sqlite3_changes ( database );
1774
+ }
1775
+
1571
1776
#if !defined(PJ_VERSION) || PJ_VERSION!=470
1572
- // 4.7.0 has a bug that crashes after 16 consecutive pj_init_plus with different strings
1573
- else
1777
+ QString sql = QString ( " select auth_name,auth_id,parameters from tbl_srs WHERE auth_name<>'EPSG' WHERE NOT deprecated" );
1778
+ if ( sqlite3_prepare ( database, sql.toAscii (), sql.size (), &select, &tail ) == SQLITE_OK )
1779
+ {
1780
+ while ( sqlite3_step ( select ) == SQLITE_ROW )
1574
1781
{
1782
+ const char *auth_name = ( const char * ) sqlite3_column_text ( select, 0 );
1783
+ const char *auth_id = ( const char * ) sqlite3_column_text ( select, 1 );
1784
+ const char *params = ( const char * ) sqlite3_column_text ( select, 2 );
1785
+
1575
1786
QString input = QString ( " +init=%1:%2" ).arg ( QString ( auth_name ).toLower () ).arg ( auth_id );
1576
1787
projPJ pj = pj_init_plus ( input.toAscii () );
1577
1788
if ( !pj )
@@ -1607,44 +1818,11 @@ int QgsCoordinateReferenceSystem::syncDb()
1607
1818
1608
1819
pj_free ( pj );
1609
1820
}
1610
- #endif
1611
-
1612
- if ( proj4.isEmpty () )
1613
- {
1614
- continue ;
1615
- }
1616
-
1617
- if ( proj4 != params )
1618
- {
1619
- char *errMsg = NULL ;
1620
- sql = QString ( " UPDATE tbl_srs SET parameters=%1 WHERE auth_name=%2 AND auth_id=%3" )
1621
- .arg ( quotedValue ( proj4 ) )
1622
- .arg ( quotedValue ( auth_name ) )
1623
- .arg ( quotedValue ( auth_id ) );
1624
-
1625
- if ( sqlite3_exec ( database, sql.toUtf8 (), 0 , 0 , &errMsg ) != SQLITE_OK )
1626
- {
1627
- qCritical ( " Could not execute: %s [%s/%s]\n " ,
1628
- sql.toLocal8Bit ().constData (),
1629
- sqlite3_errmsg ( database ),
1630
- errMsg ? errMsg : " (unknown error)" );
1631
- errors++;
1632
- }
1633
- else
1634
- {
1635
- updated++;
1636
- QgsDebugMsgLevel ( QString ( " SQL: %1\n OLD:%2\n NEW:%3" ).arg ( sql ).arg ( params ).arg ( proj4 ), 3 );
1637
- }
1638
-
1639
- if ( errMsg )
1640
- sqlite3_free ( errMsg );
1641
- }
1642
1821
}
1822
+ #endif
1643
1823
1644
1824
OSRDestroySpatialReference ( crs );
1645
1825
1646
- sqlite3_finalize ( select );
1647
-
1648
1826
if ( sqlite3_exec ( database, " COMMIT" , 0 , 0 , 0 ) != SQLITE_OK )
1649
1827
{
1650
1828
qCritical ( " Could not commit transaction: %s [%s]\n " , QgsApplication::srsDbFilePath ().toLocal8Bit ().constData (), sqlite3_errmsg ( database ) );
@@ -1653,8 +1831,10 @@ int QgsCoordinateReferenceSystem::syncDb()
1653
1831
1654
1832
sqlite3_close ( database );
1655
1833
1834
+ qWarning ( " CRS update (inserted:%d updated:%d deleted:%d errors:%d)" , inserted, updated, deleted, errors );
1835
+
1656
1836
if ( errors > 0 )
1657
1837
return -errors;
1658
1838
else
1659
- return updated;
1839
+ return updated + inserted ;
1660
1840
}
0 commit comments