www.pudn.com > dstile-0.2.rar > Tiler.cpp


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#include 
#include "syskit.h"
#include "giskit.h"
#include 
#include 
#include 
#include 
#include 
#include 

Tiler::Tiler() :
    m_needCloseSrc(false),
    m_needEndTiling(false),
    m_tileAccessor(0),
    m_tileProcessor(0),
    m_cSTrans(0),
    m_warper(0),
    m_overviews(0),
    m_tile(0),
    m_memDrv(0),
    m_src(0),
    m_srcFileName(),

    m_srcSRS(),
    m_vSrcGT(false),
    m_srcGT(),
    m_dstSRS(),
    m_ex0(0.0),
    m_ey0(0.0),
    m_ex1(0.0),
    m_ey1(0.0),
    m_tsx(0),
    m_tsy(0),
    m_tBands(3),
    m_tDataType(GDT_Byte),
    m_l0tx(1),
    m_l0ty(1)
{
    m_memDrv = GetGDALDriverManager()->GetDriverByName("MEM");
}

Tiler::~Tiler() {
    if (m_needEndTiling) EndTiling();
    if (m_needCloseSrc) CloseSrc();
}

void Tiler::OpenSrc(const string& srcFileName) {
    if (m_needCloseSrc) CloseSrc();
    m_needCloseSrc = true;

    m_srcFileName = srcFileName;
    m_src = reinterpret_cast(GDALOpen(srcFileName.c_str(), GA_ReadOnly));
    if (!m_src) throw Exception("Tiler::OpenSrc failed: unable to open '%s'.", srcFileName.c_str());
	
    if (m_src->GetProjectionRef()) m_srcSRS = m_src->GetProjectionRef();
    if (m_src->GetGeoTransform(m_srcGT.m_mat) == CE_None) m_vSrcGT = true;
}
    
void Tiler::CloseSrc() {
    if (m_src) {
	GDALClose(m_src);
	m_src = 0;
    }
    m_srcFileName.clear();
    m_needCloseSrc = false;
}

void Tiler::BeginTiling() {
    m_needEndTiling = true;
    m_cSTrans->Create(m_srcSRS, m_dstSRS, 0.2);
    m_cSTrans->SetSrcGT(m_srcGT);
    m_tile = m_memDrv->Create("", m_tsx, m_tsy, m_tBands, m_tDataType, 0);
    if (!m_tile) throw Exception("Tiler::BeginTiling failed: unable to create in-memory image.");
    m_warper->Create(m_src, m_tile, *m_cSTrans);
}

void Tiler::EndTiling() {
    if (m_needEndTiling) {
	m_warper->Destroy();
	if (m_tile) {
	    delete m_tile;
	    m_tile = 0;
	}
	m_cSTrans->Destroy();
	m_needEndTiling = false;
    }
}

double Tiler::EstimateLevel() {
    GeoT gt;
    int sx, sy;
    double lx, ly;

    m_cSTrans->SetDstGT(GeoT::Identity());

    GDALSuggestedWarpOutput(m_src, m_cSTrans->GetCSTransFunc(), m_cSTrans->GetCSTransArg(), gt.m_mat, &sx, &sy);

    lx = log(fabs(gt.m_mat[1] * m_tsx * m_l0tx / (m_ex1 - m_ex0))) / log(0.5);
    ly = log(fabs(gt.m_mat[5] * m_tsy * m_l0ty / (m_ey1 - m_ey0))) / log(0.5);
    return (lx + ly) * 0.5;
}

void Tiler::Tile(int level) {
    GeoT gt;
    int sx, sy;
    int x0, y0, x1, y1;
    double rx, ry;
    int x, y;
    int n, nn;
    double a, b;
    GDALDataset *prevTile;
    FileLock fl;

    if (level < 0) level = 0;
    m_cSTrans->SetDstGT(GeoT::Identity());

    GDALSuggestedWarpOutput(m_src, m_cSTrans->GetCSTransFunc(), m_cSTrans->GetCSTransArg(), gt.m_mat, &sx, &sy);
	
    rx = (m_ex1 - m_ex0) / (m_l0tx * pow(2.0, level));
    ry = (m_ey1 - m_ey0) / (m_l0ty * pow(2.0, level));
	
    x0 = static_cast(floor((gt.m_mat[0] - m_ex0) / rx));
    y0 = static_cast(floor((gt.m_mat[3] - m_ey0) / ry));
    x1 = static_cast(ceil((gt.m_mat[0] + gt.m_mat[1] * sx - m_ex0) / rx));
    y1 = static_cast(ceil((gt.m_mat[3] + gt.m_mat[5] * sy - m_ey0) / ry));
    nn = (x1 - x0) * (y1 - y0);
	
    printf("%s", m_srcFileName.c_str());
    n = 0;
    GDALTermProgress(0.0, "", 0);
    for (y = y0; y < y1; ++y) for (x = x0; x < x1; ++x) {
        ++n;
        GDALTermProgress((1.0 * n) / nn, "", 0);
        for (int i = 1; i <= m_tBands; ++i) m_tile->GetRasterBand(i)->Fill(0.0);
        m_cSTrans->SetDstGT(GeoT(m_ex0 + x * rx, m_ey0 + y * ry, rx / m_tsx, ry / m_tsy));
        m_warper->ChunkAndWarpImage(0, 0, m_tsx, m_tsy);
	
	if (!m_tileProcessor->IsNull(m_tile)) {
	    string loc = m_tileAccessor->LocateTile(level, x, y);
	    fl.Open(loc);
	    fl.LockExclusive();
	    if (fl.GetSize()) prevTile = m_tileAccessor->Read(level, x, y);
	    else prevTile = 0;
	    try {
		if (prevTile) m_tileProcessor->Combine(m_tile, prevTile, m_tile);
		m_tileAccessor->Write(level, x, y, m_tile);
		fl.Unlock();
		fl.Close();
	    }
	    catch (...) {
		if (prevTile) delete prevTile;
		throw;
	    }
    	    if (prevTile) delete prevTile;
	    if (m_overviews) m_overviews->Insert(level, x, y);
	}
	
    }
}