| 236 | | /* -------------------------------------------------------------------- */ |
|---|
| 237 | | /* Figure out the georeferenced extents. */ |
|---|
| 238 | | /* -------------------------------------------------------------------- */ |
|---|
| 239 | | double dfMinX, dfMaxX, dfMinY, dfMaxY; |
|---|
| 240 | | |
|---|
| 241 | | dfMinX = adfGeoTransform[0] + |
|---|
| 242 | | (nBlockXOff * nBlockXSize + 0.5) * adfGeoTransform[1]; |
|---|
| 243 | | dfMaxX = adfGeoTransform[0] + |
|---|
| 244 | | ((nBlockXOff+1) * nBlockXSize + 0.5) * adfGeoTransform[1]; |
|---|
| 245 | | dfMaxY = adfGeoTransform[3] + |
|---|
| 246 | | (nBlockYOff * nBlockYSize + 0.5) * adfGeoTransform[5]; |
|---|
| 247 | | dfMinY = adfGeoTransform[3] + |
|---|
| 248 | | ((nBlockYOff+1) * nBlockYSize + 0.5) * adfGeoTransform[5]; |
|---|
| 249 | | |
|---|
| 250 | | |
|---|
| 251 | | /* -------------------------------------------------------------------- */ |
|---|
| 252 | | /* Construct a simple GetCoverage request. */ |
|---|
| 253 | | /* -------------------------------------------------------------------- */ |
|---|
| 254 | | CPLString osRequest; |
|---|
| 255 | | |
|---|
| 256 | | osRequest.Printf( |
|---|
| 257 | | "%sSERVICE=WCS&VERSION=1.0.0&REQUEST=GetCoverage&COVERAGE=%s" |
|---|
| 258 | | "&FORMAT=%s&BBOX=%.15g,%.15g,%.15g,%.15g&WIDTH=%d&HEIGHT=%d&CRS=%s%s", |
|---|
| 259 | | CPLGetXMLValue( poODS->psService, "ServiceURL", "" ), |
|---|
| 260 | | CPLGetXMLValue( poODS->psService, "CoverageName", "" ), |
|---|
| 261 | | CPLGetXMLValue( poODS->psService, "PreferredFormat", "" ), |
|---|
| 262 | | dfMinX, dfMinY, dfMaxX, dfMaxY, |
|---|
| 263 | | nBlockXSize, nBlockYSize, |
|---|
| 264 | | poODS->osCRS.c_str(), |
|---|
| 265 | | CPLGetXMLValue( poODS->psService, "GetCoverageExtra", "" ) ); |
|---|
| 266 | | |
|---|
| 267 | | /* -------------------------------------------------------------------- */ |
|---|
| 268 | | /* Append band selector if we have one. */ |
|---|
| 269 | | /* -------------------------------------------------------------------- */ |
|---|
| 270 | | CPLString osBandIdentifier = poODS->osBandIdentifier; |
|---|
| 271 | | |
|---|
| 272 | | if( strlen(osBandIdentifier) ) |
|---|
| 273 | | { |
|---|
| 274 | | CPLString osBS; |
|---|
| 275 | | |
|---|
| 276 | | osBS.Printf( "&%s=%d", osBandIdentifier.c_str(), GetBand() ); |
|---|
| 277 | | osRequest += osBS; |
|---|
| 278 | | } |
|---|
| 279 | | |
|---|
| 280 | | /* -------------------------------------------------------------------- */ |
|---|
| 281 | | /* Fetch the result. */ |
|---|
| 282 | | /* -------------------------------------------------------------------- */ |
|---|
| 283 | | CPLString osTimeout = "TIMEOUT="; |
|---|
| 284 | | osTimeout += CPLGetXMLValue( poODS->psService, "Timeout", "30" ); |
|---|
| 285 | | char *apszOptions[] = { |
|---|
| 286 | | (char *) osTimeout.c_str(), |
|---|
| 287 | | NULL |
|---|
| 288 | | }; |
|---|
| 289 | | |
|---|
| 290 | | CPLErrorReset(); |
|---|
| 291 | | |
|---|
| 292 | | CPLHTTPResult *psResult = CPLHTTPFetch( osRequest, apszOptions ); |
|---|
| 293 | | |
|---|
| 294 | | if( poODS->ProcessError( psResult ) ) |
|---|
| 295 | | return CE_Failure; |
|---|
| | 232 | CPLErr eErr; |
|---|
| | 233 | CPLHTTPResult *psResult = NULL; |
|---|
| | 234 | |
|---|
| | 235 | eErr = poODS->GetCoverage( nBlockXOff * nBlockXSize * nResFactor, |
|---|
| | 236 | nBlockYOff * nBlockYSize * nResFactor, |
|---|
| | 237 | nBlockXSize * nResFactor, |
|---|
| | 238 | nBlockYSize * nResFactor, |
|---|
| | 239 | nBlockXSize, nBlockYSize, |
|---|
| | 240 | 1, &nBand, &psResult ); |
|---|
| | 241 | if( eErr != CE_None ) |
|---|
| | 242 | return eErr; |
|---|
| | 516 | /* Get the coverage. */ |
|---|
| | 517 | /* -------------------------------------------------------------------- */ |
|---|
| | 518 | CPLHTTPResult *psResult = NULL; |
|---|
| | 519 | CPLErr eErr = |
|---|
| | 520 | GetCoverage( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, |
|---|
| | 521 | nBandCount, panBandMap, &psResult ); |
|---|
| | 522 | |
|---|
| | 523 | if( eErr != CE_None ) |
|---|
| | 524 | return eErr; |
|---|
| | 525 | |
|---|
| | 526 | /* -------------------------------------------------------------------- */ |
|---|
| | 527 | /* Try and open result as a dataseat. */ |
|---|
| | 528 | /* -------------------------------------------------------------------- */ |
|---|
| | 529 | GDALDataset *poTileDS = GDALOpenResult( psResult ); |
|---|
| | 530 | |
|---|
| | 531 | if( poTileDS == NULL ) |
|---|
| | 532 | return CE_Failure; |
|---|
| | 533 | |
|---|
| | 534 | /* -------------------------------------------------------------------- */ |
|---|
| | 535 | /* Verify configuration. */ |
|---|
| | 536 | /* -------------------------------------------------------------------- */ |
|---|
| | 537 | if( poTileDS->GetRasterXSize() != nBufXSize |
|---|
| | 538 | || poTileDS->GetRasterYSize() != nBufYSize ) |
|---|
| | 539 | { |
|---|
| | 540 | CPLDebug( "WCS", "Got size=%dx%d instead of %dx%d.", |
|---|
| | 541 | poTileDS->GetRasterXSize(), poTileDS->GetRasterYSize(), |
|---|
| | 542 | nBufXSize, nBufYSize ); |
|---|
| | 543 | |
|---|
| | 544 | CPLError( CE_Failure, CPLE_AppDefined, |
|---|
| | 545 | "Returned tile does not match expected configuration." ); |
|---|
| | 546 | return CE_Failure; |
|---|
| | 547 | } |
|---|
| | 548 | |
|---|
| | 549 | if( (strlen(osBandIdentifier) && poTileDS->GetRasterCount() != nBandCount) |
|---|
| | 550 | || (!strlen(osBandIdentifier) && poTileDS->GetRasterCount() != |
|---|
| | 551 | GetRasterCount() ) ) |
|---|
| | 552 | { |
|---|
| | 553 | CPLError( CE_Failure, CPLE_AppDefined, |
|---|
| | 554 | "Returned tile does not match expected band count." ); |
|---|
| | 555 | return CE_Failure; |
|---|
| | 556 | } |
|---|
| | 557 | |
|---|
| | 558 | /* -------------------------------------------------------------------- */ |
|---|
| | 559 | /* Pull requested bands from the downloaded dataset. */ |
|---|
| | 560 | /* -------------------------------------------------------------------- */ |
|---|
| | 561 | int iBand; |
|---|
| | 562 | |
|---|
| | 563 | eErr = CE_None; |
|---|
| | 564 | |
|---|
| | 565 | for( iBand = 0; |
|---|
| | 566 | iBand < nBandCount && eErr == CE_None; |
|---|
| | 567 | iBand++ ) |
|---|
| | 568 | { |
|---|
| | 569 | GDALRasterBand *poTileBand; |
|---|
| | 570 | |
|---|
| | 571 | if( strlen(osBandIdentifier) ) |
|---|
| | 572 | poTileBand = poTileDS->GetRasterBand( iBand + 1 ); |
|---|
| | 573 | else |
|---|
| | 574 | poTileBand = poTileDS->GetRasterBand( panBandMap[iBand] ); |
|---|
| | 575 | |
|---|
| | 576 | eErr = poTileBand->RasterIO( GF_Read, |
|---|
| | 577 | 0, 0, nBufXSize, nBufYSize, |
|---|
| | 578 | ((GByte *) pData) + |
|---|
| | 579 | iBand * nBandSpace, nBufXSize, nBufYSize, |
|---|
| | 580 | eBufType, nPixelSpace, nLineSpace ); |
|---|
| | 581 | } |
|---|
| | 582 | |
|---|
| | 583 | /* -------------------------------------------------------------------- */ |
|---|
| | 584 | /* Cleanup */ |
|---|
| | 585 | /* -------------------------------------------------------------------- */ |
|---|
| | 586 | delete poTileDS; |
|---|
| | 587 | |
|---|
| | 588 | FlushMemoryResult(); |
|---|
| | 589 | |
|---|
| | 590 | return eErr; |
|---|
| | 591 | } |
|---|
| | 592 | |
|---|
| | 593 | /************************************************************************/ |
|---|
| | 594 | /* GetCoverage() */ |
|---|
| | 595 | /* */ |
|---|
| | 596 | /* Issue the appropriate version of request for a given window, */ |
|---|
| | 597 | /* buffer size and band list. */ |
|---|
| | 598 | /************************************************************************/ |
|---|
| | 599 | |
|---|
| | 600 | CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize, |
|---|
| | 601 | int nBufXSize, int nBufYSize, |
|---|
| | 602 | int nBandCount, int *panBandList, |
|---|
| | 603 | CPLHTTPResult **ppsResult ) |
|---|
| | 604 | |
|---|
| | 605 | { |
|---|
| | 606 | /* -------------------------------------------------------------------- */ |
|---|
| 579 | | osRequest.Printf( |
|---|
| 580 | | "%sSERVICE=WCS&VERSION=1.0.0&REQUEST=GetCoverage&COVERAGE=%s" |
|---|
| 581 | | "&FORMAT=%s&BBOX=%.15g,%.15g,%.15g,%.15g&WIDTH=%d&HEIGHT=%d&CRS=%s%s", |
|---|
| 582 | | CPLGetXMLValue( psService, "ServiceURL", "" ), |
|---|
| 583 | | CPLGetXMLValue( psService, "CoverageName", "" ), |
|---|
| 584 | | CPLGetXMLValue( psService, "PreferredFormat", "" ), |
|---|
| 585 | | dfMinX, dfMinY, dfMaxX, dfMaxY, |
|---|
| 586 | | nBufXSize, nBufYSize, |
|---|
| 587 | | osCRS.c_str(), |
|---|
| 588 | | CPLGetXMLValue( psService, "GetCoverageExtra", "" ) ); |
|---|
| 589 | | |
|---|
| 590 | | if( CPLGetXMLValue( psService, "Resample", NULL ) ) |
|---|
| 591 | | { |
|---|
| 592 | | osRequest += "&RESAMPLE="; |
|---|
| 593 | | osRequest += CPLGetXMLValue( psService, "Resample", "" ); |
|---|
| 594 | | } |
|---|
| 595 | | |
|---|
| 596 | | /* -------------------------------------------------------------------- */ |
|---|
| 597 | | /* Select our band list if we have a band identifier. */ |
|---|
| 598 | | /* -------------------------------------------------------------------- */ |
|---|
| 599 | | int iBand; |
|---|
| 600 | | |
|---|
| 601 | | if( strlen(osBandIdentifier) ) |
|---|
| 602 | | { |
|---|
| 603 | | osRequest += "&"; |
|---|
| 604 | | osRequest += osBandIdentifier; |
|---|
| 605 | | |
|---|
| 606 | | for( iBand = 0; iBand < nBandCount; iBand++ ) |
|---|
| 607 | | { |
|---|
| 608 | | char szItem[32]; |
|---|
| | 645 | if( nVersion == 100 ) |
|---|
| | 646 | { |
|---|
| | 647 | osRequest.Printf( |
|---|
| | 648 | "%sSERVICE=WCS&VERSION=1.0.0&REQUEST=GetCoverage&COVERAGE=%s" |
|---|
| | 649 | "&FORMAT=%s&BBOX=%.15g,%.15g,%.15g,%.15g&WIDTH=%d&HEIGHT=%d&CRS=%s%s", |
|---|
| | 650 | CPLGetXMLValue( psService, "ServiceURL", "" ), |
|---|
| | 651 | CPLGetXMLValue( psService, "CoverageName", "" ), |
|---|
| | 652 | CPLGetXMLValue( psService, "PreferredFormat", "" ), |
|---|
| | 653 | dfMinX, dfMinY, dfMaxX, dfMaxY, |
|---|
| | 654 | nBufXSize, nBufYSize, |
|---|
| | 655 | osCRS.c_str(), |
|---|
| | 656 | CPLGetXMLValue( psService, "GetCoverageExtra", "" ) ); |
|---|
| | 657 | |
|---|
| | 658 | if( bSelectingBands ) |
|---|
| | 659 | { |
|---|
| | 660 | osRequest += CPLString().Printf( "&%s=%s", |
|---|
| | 661 | osBandIdentifier.c_str(), |
|---|
| | 662 | osBandList.c_str() ); |
|---|
| | 663 | } |
|---|
| | 664 | } |
|---|
| | 665 | |
|---|
| | 666 | /* -------------------------------------------------------------------- */ |
|---|
| | 667 | /* Construct a "simple" GetCoverage request (WCS 1.1+). */ |
|---|
| | 668 | /* -------------------------------------------------------------------- */ |
|---|
| | 669 | else |
|---|
| | 670 | { |
|---|
| | 671 | CPLString osRangeSubset; |
|---|
| | 672 | |
|---|
| | 673 | osRangeSubset.Printf("&RangeSubset=%s", |
|---|
| | 674 | CPLGetXMLValue(psService,"FieldName","")); |
|---|
| | 675 | |
|---|
| | 676 | if( CPLGetXMLValue( psService, "Resample", NULL ) ) |
|---|
| | 677 | { |
|---|
| | 678 | osRangeSubset += ":"; |
|---|
| | 679 | osRangeSubset += CPLGetXMLValue( psService, "Resample", ""); |
|---|
| | 680 | } |
|---|
| | 681 | |
|---|
| | 682 | if( bSelectingBands ) |
|---|
| | 683 | { |
|---|
| | 684 | osRangeSubset += |
|---|
| | 685 | CPLString().Printf( "[%s[%s]]", |
|---|
| | 686 | osBandIdentifier.c_str(), |
|---|
| | 687 | osBandList.c_str() ); |
|---|
| | 688 | } |
|---|
| | 689 | |
|---|
| | 690 | dfMaxX -= adfGeoTransform[1]; |
|---|
| | 691 | dfMinY -= adfGeoTransform[5]; |
|---|
| | 692 | |
|---|
| | 693 | // Carefully adjust bounds for pixel centered values at new |
|---|
| | 694 | // sampling density. |
|---|
| | 695 | |
|---|
| | 696 | double dfXStep = adfGeoTransform[1]; |
|---|
| | 697 | double dfYStep = adfGeoTransform[5]; |
|---|
| | 698 | |
|---|
| | 699 | if( nBufXSize != nXSize || nBufYSize != nYSize ) |
|---|
| | 700 | { |
|---|
| | 701 | dfXStep = (nXSize/(double)nBufXSize) * adfGeoTransform[1]; |
|---|
| | 702 | dfYStep = (nYSize/(double)nBufYSize) * adfGeoTransform[5]; |
|---|
| 610 | | if( iBand == 0 ) |
|---|
| 611 | | osRequest += "="; |
|---|
| 612 | | else |
|---|
| 613 | | osRequest += ","; |
|---|
| 614 | | |
|---|
| 615 | | sprintf( szItem, "%d", panBandMap[iBand] ); |
|---|
| 616 | | osRequest += szItem; |
|---|
| | 704 | dfMinX = adfGeoTransform[0] + dfXStep * 0.5; |
|---|
| | 705 | dfMaxX = dfMinX + dfXStep * (nBufXSize-1); |
|---|
| | 706 | dfMaxY = adfGeoTransform[3] + dfYStep * 0.5; |
|---|
| | 707 | dfMinY = dfMaxY + dfYStep * (nBufYSize-1); |
|---|
| | 708 | } |
|---|
| | 709 | |
|---|
| | 710 | osRequest.Printf( |
|---|
| | 711 | "%sSERVICE=WCS&VERSION=%s&REQUEST=GetCoverage&IDENTIFIER=%s" |
|---|
| | 712 | "&FORMAT=%s&BOUNDINGBOX=%.15g,%.15g,%.15g,%.15g,%s%s%s", |
|---|
| | 713 | CPLGetXMLValue( psService, "ServiceURL", "" ), |
|---|
| | 714 | CPLGetXMLValue( psService, "Version", "" ), |
|---|
| | 715 | CPLGetXMLValue( psService, "CoverageName", "" ), |
|---|
| | 716 | CPLGetXMLValue( psService, "PreferredFormat", "" ), |
|---|
| | 717 | dfMinX, dfMinY, dfMaxX, dfMaxY, |
|---|
| | 718 | osCRS.c_str(), |
|---|
| | 719 | osRangeSubset.c_str(), |
|---|
| | 720 | CPLGetXMLValue( psService, "GetCoverageExtra", "" ) ); |
|---|
| | 721 | |
|---|
| | 722 | if( nBufXSize != nXSize || nBufYSize != nYSize ) |
|---|
| | 723 | { |
|---|
| | 724 | osRequest += CPLString().Printf( |
|---|
| | 725 | "&GridBaseCRS=%s" |
|---|
| | 726 | "&GridCS=%s" |
|---|
| | 727 | "&GridType=urn:ogc:def:method:WCS:1.1:2dGridIn2dCrs" |
|---|
| | 728 | "&GridOrigin=%.15g,%.15g" |
|---|
| | 729 | "&GridOffsets=%.15g,%.15g", |
|---|
| | 730 | osCRS.c_str(), |
|---|
| | 731 | osCRS.c_str(), |
|---|
| | 732 | dfMinX, dfMaxY, |
|---|
| | 733 | dfXStep, dfYStep ); |
|---|
| 636 | | |
|---|
| 637 | | /* -------------------------------------------------------------------- */ |
|---|
| 638 | | /* Try and open result as a dataseat. */ |
|---|
| 639 | | /* -------------------------------------------------------------------- */ |
|---|
| 640 | | GDALDataset *poTileDS = GDALOpenResult( psResult ); |
|---|
| 641 | | |
|---|
| 642 | | if( poTileDS == NULL ) |
|---|
| 643 | | return CE_Failure; |
|---|
| 644 | | |
|---|
| 645 | | /* -------------------------------------------------------------------- */ |
|---|
| 646 | | /* Verify configuration. */ |
|---|
| 647 | | /* -------------------------------------------------------------------- */ |
|---|
| 648 | | if( poTileDS->GetRasterXSize() != nBufXSize |
|---|
| 649 | | || poTileDS->GetRasterYSize() != nBufYSize ) |
|---|
| 650 | | { |
|---|
| 651 | | CPLError( CE_Failure, CPLE_AppDefined, |
|---|
| 652 | | "Returned tile does not match expected configuration." ); |
|---|
| 653 | | return CE_Failure; |
|---|
| 654 | | } |
|---|
| 655 | | |
|---|
| 656 | | if( (strlen(osBandIdentifier) && poTileDS->GetRasterCount() != nBandCount) |
|---|
| 657 | | || (!strlen(osBandIdentifier) && poTileDS->GetRasterCount() != |
|---|
| 658 | | GetRasterCount() ) ) |
|---|
| 659 | | { |
|---|
| 660 | | CPLError( CE_Failure, CPLE_AppDefined, |
|---|
| 661 | | "Returned tile does not match expected band count." ); |
|---|
| 662 | | return CE_Failure; |
|---|
| 663 | | } |
|---|
| 664 | | |
|---|
| 665 | | /* -------------------------------------------------------------------- */ |
|---|
| 666 | | /* Pull requested bands from the downloaded dataset. */ |
|---|
| 667 | | /* -------------------------------------------------------------------- */ |
|---|
| 668 | | CPLErr eErr = CE_None; |
|---|
| 669 | | |
|---|
| 670 | | for( iBand = 0; |
|---|
| 671 | | iBand < nBandCount && eErr == CE_None; |
|---|
| 672 | | iBand++ ) |
|---|
| 673 | | { |
|---|
| 674 | | GDALRasterBand *poTileBand; |
|---|
| 675 | | |
|---|
| 676 | | if( strlen(osBandIdentifier) ) |
|---|
| 677 | | poTileBand = poTileDS->GetRasterBand( iBand + 1 ); |
|---|
| 678 | | else |
|---|
| 679 | | poTileBand = poTileDS->GetRasterBand( panBandMap[iBand] ); |
|---|
| 680 | | |
|---|
| 681 | | eErr = poTileBand->RasterIO( GF_Read, |
|---|
| 682 | | 0, 0, nBufXSize, nBufYSize, |
|---|
| 683 | | ((GByte *) pData) + |
|---|
| 684 | | iBand * nBandSpace, nBufXSize, nBufYSize, |
|---|
| 685 | | eBufType, nPixelSpace, nLineSpace ); |
|---|
| 686 | | } |
|---|
| 687 | | |
|---|
| 688 | | /* -------------------------------------------------------------------- */ |
|---|
| 689 | | /* Cleanup */ |
|---|
| 690 | | /* -------------------------------------------------------------------- */ |
|---|
| 691 | | delete poTileDS; |
|---|
| 692 | | |
|---|
| 693 | | FlushMemoryResult(); |
|---|
| 694 | | |
|---|
| 695 | | return eErr; |
|---|
| | 753 | else |
|---|
| | 754 | return CE_None; |
|---|
| 713 | | osRequest.Printf( |
|---|
| 714 | | "%sSERVICE=WCS&VERSION=1.0.0&REQUEST=DescribeCoverage&COVERAGE=%s%s", |
|---|
| 715 | | CPLGetXMLValue( psService, "ServiceURL", "" ), |
|---|
| 716 | | CPLGetXMLValue( psService, "CoverageName", "" ), |
|---|
| 717 | | CPLGetXMLValue( psService, "DescribeCoverageExtra", "" ) ); |
|---|
| | 772 | if( nVersion == 100 ) |
|---|
| | 773 | osRequest.Printf( |
|---|
| | 774 | "%sSERVICE=WCS&REQUEST=DescribeCoverage&VERSION=%s&COVERAGE=%s%s", |
|---|
| | 775 | CPLGetXMLValue( psService, "ServiceURL", "" ), |
|---|
| | 776 | CPLGetXMLValue( psService, "Version", "1.0.0" ), |
|---|
| | 777 | CPLGetXMLValue( psService, "CoverageName", "" ), |
|---|
| | 778 | CPLGetXMLValue( psService, "DescribeCoverageExtra", "" ) ); |
|---|
| | 779 | else |
|---|
| | 780 | osRequest.Printf( |
|---|
| | 781 | "%sSERVICE=WCS&REQUEST=DescribeCoverage&VERSION=%s&IDENTIFIERS=%s%s", |
|---|
| | 782 | CPLGetXMLValue( psService, "ServiceURL", "" ), |
|---|
| | 783 | CPLGetXMLValue( psService, "Version", "1.0.0" ), |
|---|
| | 784 | CPLGetXMLValue( psService, "CoverageName", "" ), |
|---|
| | 785 | CPLGetXMLValue( psService, "DescribeCoverageExtra", "" ) ); |
|---|
| | 1072 | /* ParseBoundingBox() */ |
|---|
| | 1073 | /************************************************************************/ |
|---|
| | 1074 | |
|---|
| | 1075 | static int ParseBoundingBox( CPLXMLNode *psBoundingBox, CPLString &osCRS, |
|---|
| | 1076 | double &dfLowerX, double &dfLowerY, |
|---|
| | 1077 | double &dfUpperX, double &dfUpperY ) |
|---|
| | 1078 | |
|---|
| | 1079 | { |
|---|
| | 1080 | int nRet = TRUE; |
|---|
| | 1081 | |
|---|
| | 1082 | osCRS = CPLGetXMLValue( psBoundingBox, "crs", "" ); |
|---|
| | 1083 | |
|---|
| | 1084 | char **papszLC = CSLTokenizeStringComplex( |
|---|
| | 1085 | CPLGetXMLValue( psBoundingBox, "LowerCorner", ""), |
|---|
| | 1086 | " ", FALSE, FALSE ); |
|---|
| | 1087 | char **papszUC = CSLTokenizeStringComplex( |
|---|
| | 1088 | CPLGetXMLValue( psBoundingBox, "UpperCorner", ""), |
|---|
| | 1089 | " ", FALSE, FALSE ); |
|---|
| | 1090 | |
|---|
| | 1091 | if( CSLCount(papszLC) >= 2 && CSLCount(papszUC) >= 2 ) |
|---|
| | 1092 | { |
|---|
| | 1093 | dfLowerX = atof(papszLC[0]); |
|---|
| | 1094 | dfLowerY = atof(papszLC[1]); |
|---|
| | 1095 | dfUpperX = atof(papszUC[0]); |
|---|
| | 1096 | dfUpperY = atof(papszUC[1]); |
|---|
| | 1097 | } |
|---|
| | 1098 | else |
|---|
| | 1099 | nRet = FALSE; |
|---|
| | 1100 | |
|---|
| | 1101 | CSLDestroy( papszUC ); |
|---|
| | 1102 | CSLDestroy( papszLC ); |
|---|
| | 1103 | |
|---|
| | 1104 | return nRet; |
|---|
| | 1105 | } |
|---|
| | 1106 | |
|---|
| | 1107 | /************************************************************************/ |
|---|
| | 1108 | /* ExtractGridInfo() */ |
|---|
| | 1109 | /* */ |
|---|
| | 1110 | /* Collect info about grid from describe coverage for WCS 1.1 */ |
|---|
| | 1111 | /* and above. */ |
|---|
| | 1112 | /************************************************************************/ |
|---|
| | 1113 | |
|---|
| | 1114 | int WCSDataset::ExtractGridInfo() |
|---|
| | 1115 | |
|---|
| | 1116 | { |
|---|
| | 1117 | if( nVersion == 100 ) |
|---|
| | 1118 | return ExtractGridInfo100(); |
|---|
| | 1119 | |
|---|
| | 1120 | CPLXMLNode * psCO = CPLGetXMLNode( psService, "CoverageDescription" ); |
|---|
| | 1121 | |
|---|
| | 1122 | if( psCO == NULL ) |
|---|
| | 1123 | return FALSE; |
|---|
| | 1124 | |
|---|
| | 1125 | /* -------------------------------------------------------------------- */ |
|---|
| | 1126 | /* We need to strip off name spaces so it is easier to */ |
|---|
| | 1127 | /* searchfor plain gml names. */ |
|---|
| | 1128 | /* -------------------------------------------------------------------- */ |
|---|
| | 1129 | CPLStripXMLNamespace( psCO, NULL, TRUE ); |
|---|
| | 1130 | |
|---|
| | 1131 | /* -------------------------------------------------------------------- */ |
|---|
| | 1132 | /* Verify we have a SpatialDomain and GridCRS. */ |
|---|
| | 1133 | /* -------------------------------------------------------------------- */ |
|---|
| | 1134 | CPLXMLNode *psSD = |
|---|
| | 1135 | CPLGetXMLNode( psCO, "Domain.SpatialDomain" ); |
|---|
| | 1136 | CPLXMLNode *psGCRS = |
|---|
| | 1137 | CPLGetXMLNode( psSD, "GridCRS" ); |
|---|
| | 1138 | |
|---|
| | 1139 | if( psSD == NULL || psGCRS == NULL ) |
|---|
| | 1140 | { |
|---|
| | 1141 | CPLError( CE_Failure, CPLE_AppDefined, |
|---|
| | 1142 | "Unable to find GridCRS in CoverageDescription,\n" |
|---|
| | 1143 | "unable to process WCS Coverage." ); |
|---|
| | 1144 | return FALSE; |
|---|
| | 1145 | } |
|---|
| | 1146 | |
|---|
| | 1147 | /* -------------------------------------------------------------------- */ |
|---|
| | 1148 | /* Extract Geotransform from GridCRS. */ |
|---|
| | 1149 | /* -------------------------------------------------------------------- */ |
|---|
| | 1150 | const char *pszGridType = CPLGetXMLValue( psGCRS, "GridType", |
|---|
| | 1151 | "urn:ogc:def:method:WCS::2dSimpleGrid" ); |
|---|
| | 1152 | |
|---|
| | 1153 | char **papszOriginTokens = |
|---|
| | 1154 | CSLTokenizeStringComplex( CPLGetXMLValue( psGCRS, "GridOrigin", ""), |
|---|
| | 1155 | " ", FALSE, FALSE ); |
|---|
| | 1156 | char **papszOffsetTokens = |
|---|
| | 1157 | CSLTokenizeStringComplex( CPLGetXMLValue( psGCRS, "GridOffsets", ""), |
|---|
| | 1158 | " ", FALSE, FALSE ); |
|---|
| | 1159 | |
|---|
| | 1160 | if( strstr(pszGridType,":2dGridIn2dCrs") ) |
|---|
| | 1161 | { |
|---|
| | 1162 | if( CSLCount(papszOffsetTokens) == 4 |
|---|
| | 1163 | && CSLCount(papszOriginTokens) == 2 ) |
|---|
| | 1164 | { |
|---|
| | 1165 | adfGeoTransform[0] = atof(papszOriginTokens[0]); |
|---|
| | 1166 | adfGeoTransform[1] = atof(papszOffsetTokens[0]); |
|---|
| | 1167 | adfGeoTransform[2] = atof(papszOffsetTokens[1]); |
|---|
| | 1168 | adfGeoTransform[3] = atof(papszOriginTokens[1]); |
|---|
| | 1169 | adfGeoTransform[4] = atof(papszOffsetTokens[2]); |
|---|
| | 1170 | adfGeoTransform[5] = atof(papszOffsetTokens[3]); |
|---|
| | 1171 | } |
|---|
| | 1172 | else |
|---|
| | 1173 | { |
|---|
| | 1174 | CPLError( CE_Failure, CPLE_AppDefined, |
|---|
| | 1175 | "2dGridIn2dCrs does not have expected GridOrigin or\n" |
|---|
| | 1176 | "GridOffsets values - unable to process WCS coverage."); |
|---|
| | 1177 | return FALSE; |
|---|
| | 1178 | } |
|---|
| | 1179 | } |
|---|
| | 1180 | |
|---|
| | 1181 | else if( strstr(pszGridType,":2dGridIn3dCrs") ) |
|---|
| | 1182 | { |
|---|
| | 1183 | if( CSLCount(papszOffsetTokens) == 6 |
|---|
| | 1184 | && CSLCount(papszOriginTokens) == 3 ) |
|---|
| | 1185 | { |
|---|
| | 1186 | adfGeoTransform[0] = atof(papszOriginTokens[0]); |
|---|
| | 1187 | adfGeoTransform[1] = atof(papszOffsetTokens[0]); |
|---|
| | 1188 | adfGeoTransform[2] = atof(papszOffsetTokens[1]); |
|---|
| | 1189 | adfGeoTransform[3] = atof(papszOriginTokens[1]); |
|---|
| | 1190 | adfGeoTransform[4] = atof(papszOffsetTokens[3]); |
|---|
| | 1191 | adfGeoTransform[5] = atof(papszOffsetTokens[4]); |
|---|
| | 1192 | } |
|---|
| | 1193 | else |
|---|
| | 1194 | { |
|---|
| | 1195 | CPLError( CE_Failure, CPLE_AppDefined, |
|---|
| | 1196 | "2dGridIn3dCrs does not have expected GridOrigin or\n" |
|---|
| | 1197 | "GridOffsets values - unable to process WCS coverage."); |
|---|
| | 1198 | return FALSE; |
|---|
| | 1199 | } |
|---|
| | 1200 | } |
|---|
| | 1201 | |
|---|
| | 1202 | else if( strstr(pszGridType,":2dSimpleGrid") ) |
|---|
| | 1203 | { |
|---|
| | 1204 | if( CSLCount(papszOffsetTokens) == 2 |
|---|
| | 1205 | && CSLCount(papszOriginTokens) == 2 ) |
|---|
| | 1206 | { |
|---|
| | 1207 | adfGeoTransform[0] = atof(papszOriginTokens[0]); |
|---|
| | 1208 | adfGeoTransform[1] = atof(papszOffsetTokens[0]); |
|---|
| | 1209 | adfGeoTransform[2] = 0.0; |
|---|
| | 1210 | adfGeoTransform[3] = atof(papszOriginTokens[1]); |
|---|
| | 1211 | adfGeoTransform[4] = 0.0; |
|---|
| | 1212 | adfGeoTransform[5] = atof(papszOffsetTokens[1]); |
|---|
| | 1213 | } |
|---|
| | 1214 | else |
|---|
| | 1215 | { |
|---|
| | 1216 | CPLError( CE_Failure, CPLE_AppDefined, |
|---|
| | 1217 | "2dSimpleGrid does not have expected GridOrigin or\n" |
|---|
| | 1218 | "GridOffsets values - unable to process WCS coverage."); |
|---|
| | 1219 | return FALSE; |
|---|
| | 1220 | } |
|---|
| | 1221 | } |
|---|
| | 1222 | |
|---|
| | 1223 | else |
|---|
| | 1224 | { |
|---|
| | 1225 | CPLError( CE_Failure, CPLE_AppDefined, |
|---|
| | 1226 | "Unrecognised GridCRS.GridType value '%s',\n" |
|---|
| | 1227 | "unable to process WCS coverage.", |
|---|
| | 1228 | pszGridType ); |
|---|
| | 1229 | return FALSE; |
|---|
| | 1230 | } |
|---|
| | 1231 | |
|---|
| | 1232 | CSLDestroy( papszOffsetTokens ); |
|---|
| | 1233 | CSLDestroy( papszOriginTokens ); |
|---|
| | 1234 | |
|---|
| | 1235 | // GridOrigin is center of pixel ... offset half pixel to adjust. |
|---|
| | 1236 | |
|---|
| | 1237 | adfGeoTransform[0] -= (adfGeoTransform[1]+adfGeoTransform[2]) * 0.5; |
|---|
| | 1238 | adfGeoTransform[3] -= (adfGeoTransform[4]+adfGeoTransform[5]) * 0.5; |
|---|
| | 1239 | |
|---|
| | 1240 | /* -------------------------------------------------------------------- */ |
|---|
| | 1241 | /* Establish our coordinate system. */ |
|---|
| | 1242 | /* -------------------------------------------------------------------- */ |
|---|
| | 1243 | osCRS = CPLGetXMLValue( psGCRS, "GridBaseCRS", "" ); |
|---|
| | 1244 | |
|---|
| | 1245 | if( strlen(osCRS) == 0 ) |
|---|
| | 1246 | { |
|---|
| | 1247 | CPLError( CE_Failure, CPLE_AppDefined, |
|---|
| | 1248 | "Unable to find GridCRS.GridBaseCRS" ); |
|---|
| | 1249 | return FALSE; |
|---|
| | 1250 | } |
|---|
| | 1251 | else if( strstr(osCRS,":imageCRS") ) |
|---|
| | 1252 | { |
|---|
| | 1253 | // raw image. |
|---|
| | 1254 | } |
|---|
| | 1255 | else |
|---|
| | 1256 | { |
|---|
| | 1257 | OGRSpatialReference oSRS; |
|---|
| | 1258 | if( oSRS.importFromURN( osCRS ) == OGRERR_NONE ) |
|---|
| | 1259 | { |
|---|
| | 1260 | CPLFree( pszProjection ); |
|---|
| | 1261 | oSRS.exportToWkt( &pszProjection ); |
|---|
| | 1262 | } |
|---|
| | 1263 | else |
|---|
| | 1264 | { |
|---|
| | 1265 | CPLError( CE_Failure, CPLE_AppDefined, |
|---|
| | 1266 | "Unable to interprete GridBaseCRS '%s'.", |
|---|
| | 1267 | osCRS.c_str() ); |
|---|
| | 1268 | return FALSE; |
|---|
| | 1269 | } |
|---|
| | 1270 | } |
|---|
| | 1271 | |
|---|
| | 1272 | /* -------------------------------------------------------------------- */ |
|---|
| | 1273 | /* Search for an ImageCRS for raster size. */ |
|---|
| | 1274 | /* -------------------------------------------------------------------- */ |
|---|
| | 1275 | CPLXMLNode *psNode; |
|---|
| | 1276 | |
|---|
| | 1277 | nRasterXSize = -1; |
|---|
| | 1278 | nRasterYSize = -1; |
|---|
| | 1279 | for( psNode = psSD->psChild; |
|---|
| | 1280 | psNode != NULL && nRasterXSize == -1; |
|---|
| | 1281 | psNode = psNode->psNext ) |
|---|
| | 1282 | { |
|---|
| | 1283 | if( psNode->eType != CXT_Element |
|---|
| | 1284 | || !EQUAL(psNode->pszVal |
|---|