<commit_before>#include "bdtopo_parser.h"
#include "utils/csv.h"
#include "utils/functions.h"

#include <boost/lexical_cast.hpp>

#include <unordered_map>

namespace navimake{ namespace connectors{

namespace nt = navitia::type;
//namespace ns = navitia::streetnetwork;
namespace ns = navitia::georef;

BDTopoParser::BDTopoParser(const std::string& path): path(path){}

void BDTopoParser::load_city(navimake::Data& data){

    CsvReader reader(path + "/commune.txt");
    std::map<std::string, int> cols;

    std::vector<std::string> row = reader.next();
    for(size_t i=0; i < row.size(); i++){
        cols[row[i]] = i;
    }

    size_t name = cols["nom"];
    size_t insee = cols["code_insee"];

    for(row = reader.next(); !reader.eof() ;row = reader.next()){
        if(row.size() < 2)
            continue;
        navimake::types::City* city = new navimake::types::City();
        city->external_code = row[insee];
        city->name = row[name];
        data.cities.push_back(city);
    }

}

void BDTopoParser::load_georef(ns::GeoRef & geo_ref){
    using namespace navitia::georef;

    CsvReader reader(path + "/route_adresse.txt");
    std::map<std::string, int> cols;

    std::vector<std::string> row = reader.next();
    for(size_t i=0; i < row.size(); i++){
        boost::to_lower(row[i]);
        cols[row[i]] = i;
    }

    size_t type = cols["typ_adres"];
    size_t nom = cols["nom_rue_d"];
    size_t x1 = cols["x_debut"];
    size_t y1 = cols["y_debut"];
    size_t x2 = cols["x_fin"];
    size_t y2 = cols["y_fin"];
    size_t l = cols["longueur"];
    size_t insee = cols["inseecom_g"];
    size_t n_deb_d = cols["bornedeb_d"];
    size_t n_deb_g = cols["bornedeb_g"];
    size_t n_fin_d = cols["bornefin_d"];
    size_t n_fin_g = cols["bornefin_g"];

    navitia::type::Projection proj_lambert2e ("Lambert 2 étendu", "+init=epsg:27572", false);

    std::unordered_map<std::string, vertex_t> vertex_map;
    std::unordered_map<std::string, Way> way_map;
    std::unordered_map<int, HouseNumber> house_number_left_map;
    std::unordered_map<int, HouseNumber> house_number_right_map;

    for(row = reader.next(); !reader.eof() ;row = reader.next()){
        vertex_t source, target;
        HouseNumber hn_deb_d;
        HouseNumber hn_fin_d;
        HouseNumber hn_deb_g;
        HouseNumber hn_fin_g;

        auto it = vertex_map.find(row[x1] + row[y1]);
        if(it == vertex_map.end()){
            Vertex v;
            try{
                v.coord = navitia::type::GeographicalCoord(str_to_double(row[x1]),
                                                           str_to_double(row[y1]),
                                                           proj_lambert2e);

            } catch(...){
                std::cout << "coord : " << row[x1] << ";" << row[y1] << std::endl;
            }

            source = vertex_map[row[x1] + row[y1]] = boost::add_vertex(v, geo_ref.graph);
        }
        else source = vertex_map[row[x1] + row[y1]];

        it = vertex_map.find(row[x2] + row[y2]);
        if(it == vertex_map.end()){
            Vertex v;
            try{
                v.coord = navitia::type::GeographicalCoord(boost::lexical_cast<double>(row[x2]),
                                                           boost::lexical_cast<double>(row[y2]),
                                                           proj_lambert2e);

            } catch(...){
                std::cout << "coord : " << row[x2] << ";" << row[y2] << std::endl;
            }
            target = vertex_map[row[x2] + row[y2]] = boost::add_vertex(v, geo_ref.graph);
        }
        else target = vertex_map[row[x2] + row[y2]];

        Edge e1, e2;
        try{
            e1.length = e2.length = str_to_double(row[l]);
        }catch(...){
            std::cout << "longueur :( " << row[l] << std::endl;
        }

        boost::add_edge(source, target, e1, geo_ref.graph);
        boost::add_edge(target, source, e2, geo_ref.graph);

        hn_deb_d.number = str_to_int(row[n_deb_d]);

        hn_fin_d.number = str_to_int(row[n_fin_d]);

        hn_deb_g.number = str_to_int(row[n_deb_g]);

        hn_fin_g.number = str_to_int(row[n_fin_g]);

        hn_deb_d.coord = hn_deb_g.coord = navitia::type::GeographicalCoord(str_to_double(row[x1]),
                                                                   str_to_double(row[y1]),
                                                                   proj_lambert2e);
        hn_fin_d.coord = hn_fin_g.coord = navitia::type::GeographicalCoord(str_to_double(row[x2]),
                                                                   str_to_double(row[y2]),
                                                                   proj_lambert2e);

        std::string way_key;
        if(row[insee].substr(0,2) == "75")
            way_key = row[nom] + "75056";
        else
            way_key = row[nom] + row[insee];
        auto way_it = way_map.find(way_key);
        if(way_it == way_map.end()){
            way_map[way_key].name = row[nom];
            way_map[way_key].city = row[insee];
            way_map[way_key].way_type = row[type];
        }

         //hn_deb_d
        //std::string hn_key = row[x1] + row[y1] + row[n_deb_d];
        auto hn = house_number_right_map.find(hn_deb_d.number);
        if ((hn == house_number_right_map.end()) && (hn_deb_d.number > 0)){
            way_map[way_key].house_number_right.push_back(hn_deb_d);
            house_number_right_map[hn_deb_d.number]= hn_deb_d;
        }

        //hn_deb_g
        //hn_key = row[x1] + row[y1] + row[n_deb_g];
        hn = house_number_left_map.find(hn_deb_g.number);
        if ((hn == house_number_left_map.end()) && (hn_deb_g.number > 0)){
            way_map[way_key].house_number_left.push_back(hn_deb_g);
            house_number_left_map[hn_deb_g.number]= hn_deb_g;
        }

        //hn_fin_d
        //hn_key = row[x2] + row[y2] + row[n_fin_d];
        hn = house_number_right_map.find(hn_fin_d.number);
        if ((hn == house_number_right_map.end()) && (hn_fin_d.number > 0)){
            way_map[way_key].house_number_right.push_back(hn_fin_d);
            house_number_right_map[hn_fin_d.number]= hn_fin_d;
        }

        //hn_fin_g
        //hn_key = row[x2] + row[y2] + row[n_fin_g];
        hn = house_number_left_map.find(hn_fin_g.number);
        if ((hn == house_number_left_map.end()) && (hn_fin_g.number > 0)){
            way_map[way_key].house_number_left.push_back(hn_fin_g);
            house_number_left_map[hn_fin_g.number]= hn_fin_g;
        }

        way_map[way_key].edges.push_back(std::make_pair(source, target));
        way_map[way_key].edges.push_back(std::make_pair(target, source));
    }

    unsigned int idx=0;

    for(auto way : way_map){
        way.second.sort_house_number();
        geo_ref.ways.push_back(way.second);
        geo_ref.ways.back().idx = idx;
        BOOST_FOREACH(auto node_pair, geo_ref.ways.back().edges){
            edge_t e = boost::edge(node_pair.first, node_pair.second, geo_ref.graph).first;
            geo_ref.graph[e].way_idx = idx;
        }
        idx++;
    }
}

}} //fermeture des namespaces
<commit_msg>BD_Topo Parser :  suppression de la projection l2e vers wgs84<commit_after>#include "bdtopo_parser.h"
#include "utils/csv.h"
#include "utils/functions.h"

#include <boost/lexical_cast.hpp>

#include <unordered_map>

namespace navimake{ namespace connectors{

namespace nt = navitia::type;
//namespace ns = navitia::streetnetwork;
namespace ns = navitia::georef;

BDTopoParser::BDTopoParser(const std::string& path): path(path){}

void BDTopoParser::load_city(navimake::Data& data){

    CsvReader reader(path + "/commune.txt");
    std::map<std::string, int> cols;

    std::vector<std::string> row = reader.next();
    for(size_t i=0; i < row.size(); i++){
        cols[row[i]] = i;
    }

    size_t name = cols["nom"];
    size_t insee = cols["code_insee"];

    for(row = reader.next(); !reader.eof() ;row = reader.next()){
        if(row.size() < 2)
            continue;
        navimake::types::City* city = new navimake::types::City();
        city->external_code = row[insee];
        city->name = row[name];
        data.cities.push_back(city);
    }

}

void BDTopoParser::load_georef(ns::GeoRef & geo_ref){
    using namespace navitia::georef;

    CsvReader reader(path + "/route_adresse.txt");
    std::map<std::string, int> cols;

    std::vector<std::string> row = reader.next();
    for(size_t i=0; i < row.size(); i++){
        boost::to_lower(row[i]);
        cols[row[i]] = i;
    }

    size_t type = cols["typ_adres"];
    size_t nom = cols["nom_rue_d"];
    size_t x1 = cols["x_debut"];
    size_t y1 = cols["y_debut"];
    size_t x2 = cols["x_fin"];
    size_t y2 = cols["y_fin"];
    size_t l = cols["longueur"];
    size_t insee = cols["inseecom_g"];
    size_t n_deb_d = cols["bornedeb_d"];
    size_t n_deb_g = cols["bornedeb_g"];
    size_t n_fin_d = cols["bornefin_d"];
    size_t n_fin_g = cols["bornefin_g"];

    std::unordered_map<std::string, vertex_t> vertex_map;
    std::unordered_map<std::string, Way> way_map;
    std::unordered_map<int, HouseNumber> house_number_left_map;
    std::unordered_map<int, HouseNumber> house_number_right_map;

    for(row = reader.next(); !reader.eof() ;row = reader.next()){
        vertex_t source, target;
        HouseNumber hn_deb_d;
        HouseNumber hn_fin_d;
        HouseNumber hn_deb_g;
        HouseNumber hn_fin_g;

        auto it = vertex_map.find(row[x1] + row[y1]);
        if(it == vertex_map.end()){
            Vertex v;
            try{
                v.coord = navitia::type::GeographicalCoord(str_to_double(row[x1]),
                                                           str_to_double(row[y1]));

            } catch(...){
                std::cout << "coord : " << row[x1] << ";" << row[y1] << std::endl;
            }

            source = vertex_map[row[x1] + row[y1]] = boost::add_vertex(v, geo_ref.graph);
        }
        else source = vertex_map[row[x1] + row[y1]];

        it = vertex_map.find(row[x2] + row[y2]);
        if(it == vertex_map.end()){
            Vertex v;
            try{
                v.coord = navitia::type::GeographicalCoord(boost::lexical_cast<double>(row[x2]),
                                                           boost::lexical_cast<double>(row[y2]));

            } catch(...){
                std::cout << "coord : " << row[x2] << ";" << row[y2] << std::endl;
            }
            target = vertex_map[row[x2] + row[y2]] = boost::add_vertex(v, geo_ref.graph);
        }
        else target = vertex_map[row[x2] + row[y2]];

        Edge e1, e2;
        try{
            e1.length = e2.length = str_to_double(row[l]);
        }catch(...){
            std::cout << "longueur :( " << row[l] << std::endl;
        }

        boost::add_edge(source, target, e1, geo_ref.graph);
        boost::add_edge(target, source, e2, geo_ref.graph);

        hn_deb_d.number = str_to_int(row[n_deb_d]);

        hn_fin_d.number = str_to_int(row[n_fin_d]);

        hn_deb_g.number = str_to_int(row[n_deb_g]);

        hn_fin_g.number = str_to_int(row[n_fin_g]);

        hn_deb_d.coord = hn_deb_g.coord = navitia::type::GeographicalCoord(str_to_double(row[x1]),
                                                                   str_to_double(row[y1]));
        hn_fin_d.coord = hn_fin_g.coord = navitia::type::GeographicalCoord(str_to_double(row[x2]),
                                                                   str_to_double(row[y2]));

        std::string way_key;
        if(row[insee].substr(0,2) == "75")
            way_key = row[nom] + "75056";
        else
            way_key = row[nom] + row[insee];
        auto way_it = way_map.find(way_key);
        if(way_it == way_map.end()){
            way_map[way_key].name = row[nom];
            way_map[way_key].city = row[insee];
            way_map[way_key].way_type = row[type];
        }

         //hn_deb_d
        //std::string hn_key = row[x1] + row[y1] + row[n_deb_d];
        auto hn = house_number_right_map.find(hn_deb_d.number);
        if ((hn == house_number_right_map.end()) && (hn_deb_d.number > 0)){
            way_map[way_key].house_number_right.push_back(hn_deb_d);
            house_number_right_map[hn_deb_d.number]= hn_deb_d;
        }

        //hn_deb_g
        //hn_key = row[x1] + row[y1] + row[n_deb_g];
        hn = house_number_left_map.find(hn_deb_g.number);
        if ((hn == house_number_left_map.end()) && (hn_deb_g.number > 0)){
            way_map[way_key].house_number_left.push_back(hn_deb_g);
            house_number_left_map[hn_deb_g.number]= hn_deb_g;
        }

        //hn_fin_d
        //hn_key = row[x2] + row[y2] + row[n_fin_d];
        hn = house_number_right_map.find(hn_fin_d.number);
        if ((hn == house_number_right_map.end()) && (hn_fin_d.number > 0)){
            way_map[way_key].house_number_right.push_back(hn_fin_d);
            house_number_right_map[hn_fin_d.number]= hn_fin_d;
        }

        //hn_fin_g
        //hn_key = row[x2] + row[y2] + row[n_fin_g];
        hn = house_number_left_map.find(hn_fin_g.number);
        if ((hn == house_number_left_map.end()) && (hn_fin_g.number > 0)){
            way_map[way_key].house_number_left.push_back(hn_fin_g);
            house_number_left_map[hn_fin_g.number]= hn_fin_g;
        }

        way_map[way_key].edges.push_back(std::make_pair(source, target));
        way_map[way_key].edges.push_back(std::make_pair(target, source));
    }

    unsigned int idx=0;

    for(auto way : way_map){
        way.second.sort_house_number();
        geo_ref.ways.push_back(way.second);
        geo_ref.ways.back().idx = idx;
        BOOST_FOREACH(auto node_pair, geo_ref.ways.back().edges){
            edge_t e = boost::edge(node_pair.first, node_pair.second, geo_ref.graph).first;
            geo_ref.graph[e].way_idx = idx;
        }
        idx++;
    }
}

}} //fermeture des namespaces
<|endoftext|>


<commit_before>#include "stdafx.h"

TexMan texMan;

#if 0
#include "shader_utils.h"
#include "tga_utils.h"
static bool LoadTextureTGA(const char* name, GLuint* tex)
{
	TGAImage img;
	if (!LoadTGAImageFromFile(name, &img))
	{
		return false;
	}

	*tex = LoadTextureFromTGAImage(img);
	return *tex != 0;
}
#endif

#ifdef _MSC_VER
using std::min;
using std::max;
#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")

static GLuint LoadTextureViaGdiplus(const char* name)
{
	Gdiplus::GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR gdiplusToken;
	Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
	WCHAR wc[MAX_PATH];
	MultiByteToWideChar(CP_ACP, 0, name, -1, wc, dimof(wc));
	Gdiplus::Bitmap* image = new Gdiplus::Bitmap(wc);
	int w = (int)image->GetWidth();
	int h = (int)image->GetHeight();
	std::vector<uint32_t> col;
	for (int y = 0; y < h; y++) {
		for (int x = 0; x < w; x++) {
			Gdiplus::Color c;
			image->GetPixel(x, y, &c);
			col.push_back((c.GetA() << 24) + (c.GetB() << 16) + (c.GetG() << 8) + c.GetR());
		}
	}
	delete image;
	Gdiplus::GdiplusShutdown(gdiplusToken);

	GLuint texture;
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, &col[0]);
	glGenerateMipmap(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, 0);
	return texture;
}
#endif

struct DDSHeader {
	uint32_t h3[3];
	uint32_t h, w;
	uint32_t h2[2];
	uint32_t mipCnt;
	uint32_t h13[13];
	uint32_t fourcc, bitsPerPixel, rMask, gMask, bMask, aMask;
};

static void bitScanForward(uint32_t* result, uint32_t mask)
{
	//	DWORD dwd;
	//	_BitScanForward(&dwd, mask);
	//	*result = dwd;

	for (int i = 0; i < 32; i++) {
		if (mask & (1 << i)) {
			*result = i;
			return;
		}
	}
	*result = 0;
}

static GLuint CreateTextureFromRowDDS(const void* img, int size)
{
	const DDSHeader* hdr = (DDSHeader*)img;
	int w = (int)hdr->w;
	int h = (int)hdr->h;
	const uint32_t* im = (uint32_t*)img + 128 / 4;
	std::vector<uint32_t> col;
	uint32_t rShift, gShift, bShift, aShift;
	bitScanForward(&rShift, hdr->rMask);
	bitScanForward(&gShift, hdr->gMask);
	bitScanForward(&bShift, hdr->bMask);
	bitScanForward(&aShift, hdr->aMask);
	for (int y = 0; y < h; y++) {
		for (int x = 0; x < w; x++) {
			uint32_t c = *im++;
			col.push_back(
				((hdr->aMask & c) >> aShift << 24) +
				((hdr->bMask & c) >> bShift << 16) +
				((hdr->gMask & c) >> gShift << 8) +
				((hdr->rMask & c) >> rShift));
		}
	}

	GLuint texture;
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, &col[0]);
	glGenerateMipmap(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, 0);
	return texture;
}

static GLuint LoadDDSTexture(const char* name)
{
	int size;
	GLuint texture = 0;
	void* img = LoadFile(name, &size);
	if (!img) {
		aflog("LoadDDSTexture failed! %s", name);
		return 0;
	}
	const DDSHeader* hdr = (DDSHeader*)img;

	GLenum format;
	int blockSize = 16;
	switch (hdr->fourcc) {
	case 0x31545844: //'1TXD':
		format = 0x83F1;	// GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
		blockSize = 8;
		break;
		//	case 0x33545844; //'3TXD':
		//		format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
		//		break;
		//	case 0x35545844; //'5TXD':
		//		format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
		//		break;
	default:
		texture = CreateTextureFromRowDDS(img, size);
		goto END;
	}

	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	{
		int texSize = blockSize * ((hdr->w + 3) / 4) * ((hdr->h + 3) / 4);
		glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, hdr->w, hdr->h, 0, texSize, (char*)img + 128);
	}
	glBindTexture(GL_TEXTURE_2D, 0);

END:
	free(img);
	return texture;
}

#ifndef _MSC_VER
static GLuint LoadTextureJava(const char* name)
{
	jclass myview = jniEnv->FindClass(boundJavaClass);
	jmethodID method = method = jniEnv->GetStaticMethodID(myview, "loadTexture", "(Ljava/lang/String;)I");
	if (method == 0) {
		return 0;
	}
	return jniEnv->CallStaticIntMethod(myview, method, jniEnv->NewStringUTF(name));
}

static GLuint LoadTexture(const char* name)
{
	int len = strlen(name);
	if (len > 4 && !stricmp(name + len - 4, ".dds")) {
		return LoadDDSTexture(name);
	} else {
		return LoadTextureJava(name);
	}
}
#endif

#ifdef _MSC_VER
static GLuint LoadTexture(const char* name)
{
	int len = strlen(name);
	if (len > 4 && !stricmp(name + len - 4, ".dds")) {
		return LoadDDSTexture(name);
	} else {
		return LoadTextureViaGdiplus(name);
	}
}
#endif

static GLuint CreateWhiteTexture()
{
	uint32_t col = 0xffffffff;
	GLuint texture;
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &col);
	glBindTexture(GL_TEXTURE_2D, 0);
	return texture;
}

static GLuint CreateDynamicTexture(int w, int h)
{
	GLuint texture;
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
	glBindTexture(GL_TEXTURE_2D, 0);
	return texture;
}

TexMan::TMID TexMan::CreateDynamicTexture(const char* name, int w, int h)
{
	auto it = nameToId.find(name);
	if (it != nameToId.end())
	{
		return it->second;
	}
	return nameToId[name] = ::CreateDynamicTexture(w, h);
}

TexMan::TMID TexMan::Create(const char *name)
{
	NameToId::iterator it = nameToId.find(name);
	if (it != nameToId.end())
	{
		return it->second;
	}
	return nameToId[name] = LoadTexture(name);
}

TexMan::TMID TexMan::CreateWhiteTexture()
{
	const std::string name = "$WHITE";
	NameToId::iterator it = nameToId.find(name);
	if (it != nameToId.end())
	{
		return it->second;
	}
	return nameToId[name] = ::CreateWhiteTexture();
}

void TexMan::Destroy()
{
	for (NameToId::iterator it = nameToId.begin(); it != nameToId.end(); ++it)
	{
		GLuint id[1] = { it->second };
		glDeleteTextures(1, id);
	}
	nameToId.clear();
}

void TexMan::Write(TMID id, const void* buf, int w, int h)
{
	glBindTexture(GL_TEXTURE_2D, id);
	glTexSubImage2D(
		GL_TEXTURE_2D,
		0,
		0,
		0,
		w,
		h,
		GL_RGBA,
		GL_UNSIGNED_BYTE,
		buf
		);
	glBindTexture(GL_TEXTURE_2D, 0);
}
<commit_msg>improve LoadTextureViaGdiplus's speed<commit_after>#include "stdafx.h"

TexMan texMan;

#if 0
#include "shader_utils.h"
#include "tga_utils.h"
static bool LoadTextureTGA(const char* name, GLuint* tex)
{
	TGAImage img;
	if (!LoadTGAImageFromFile(name, &img))
	{
		return false;
	}

	*tex = LoadTextureFromTGAImage(img);
	return *tex != 0;
}
#endif

#ifdef _MSC_VER
using std::min;
using std::max;
#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")

static GLuint LoadTextureViaGdiplus(const char* name)
{
	Gdiplus::GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR gdiplusToken;
	Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
	WCHAR wc[MAX_PATH];
	MultiByteToWideChar(CP_ACP, 0, name, -1, wc, dimof(wc));
	Gdiplus::Bitmap* image = new Gdiplus::Bitmap(wc);

	int w = (int)image->GetWidth();
	int h = (int)image->GetHeight();
	Gdiplus::Rect rc(0, 0, w, h);

	Gdiplus::BitmapData* bitmapData = new Gdiplus::BitmapData;
	image->LockBits(&rc, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, bitmapData);

	std::vector<uint32_t> col;
	col.resize(w * h);
	for (int y = 0; y < h; y++) {
		memcpy(&col[y * w], (char*)bitmapData->Scan0 + bitmapData->Stride * y, w * 4);
		for (int x = 0; x < w; x++) {
			uint32_t& c = col[y * w + x];
			c = (c & 0xff00ff00) | ((c & 0xff) << 16) | ((c & 0xff0000) >> 16);
		}
	}
	image->UnlockBits(bitmapData);
	delete bitmapData;
	delete image;
	Gdiplus::GdiplusShutdown(gdiplusToken);

	GLuint texture;
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, &col[0]);
	glGenerateMipmap(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, 0);
	return texture;
}
#endif

struct DDSHeader {
	uint32_t h3[3];
	uint32_t h, w;
	uint32_t h2[2];
	uint32_t mipCnt;
	uint32_t h13[13];
	uint32_t fourcc, bitsPerPixel, rMask, gMask, bMask, aMask;
};

static void bitScanForward(uint32_t* result, uint32_t mask)
{
	//	DWORD dwd;
	//	_BitScanForward(&dwd, mask);
	//	*result = dwd;

	for (int i = 0; i < 32; i++) {
		if (mask & (1 << i)) {
			*result = i;
			return;
		}
	}
	*result = 0;
}

static GLuint CreateTextureFromRowDDS(const void* img, int size)
{
	const DDSHeader* hdr = (DDSHeader*)img;
	int w = (int)hdr->w;
	int h = (int)hdr->h;
	const uint32_t* im = (uint32_t*)img + 128 / 4;
	std::vector<uint32_t> col;
	uint32_t rShift, gShift, bShift, aShift;
	bitScanForward(&rShift, hdr->rMask);
	bitScanForward(&gShift, hdr->gMask);
	bitScanForward(&bShift, hdr->bMask);
	bitScanForward(&aShift, hdr->aMask);
	for (int y = 0; y < h; y++) {
		for (int x = 0; x < w; x++) {
			uint32_t c = *im++;
			col.push_back(
				((hdr->aMask & c) >> aShift << 24) +
				((hdr->bMask & c) >> bShift << 16) +
				((hdr->gMask & c) >> gShift << 8) +
				((hdr->rMask & c) >> rShift));
		}
	}

	GLuint texture;
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, &col[0]);
	glGenerateMipmap(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, 0);
	return texture;
}

static GLuint LoadDDSTexture(const char* name)
{
	int size;
	GLuint texture = 0;
	void* img = LoadFile(name, &size);
	if (!img) {
		aflog("LoadDDSTexture failed! %s", name);
		return 0;
	}
	const DDSHeader* hdr = (DDSHeader*)img;

	GLenum format;
	int blockSize = 16;
	switch (hdr->fourcc) {
	case 0x31545844: //'1TXD':
		format = 0x83F1;	// GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
		blockSize = 8;
		break;
		//	case 0x33545844; //'3TXD':
		//		format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
		//		break;
		//	case 0x35545844; //'5TXD':
		//		format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
		//		break;
	default:
		texture = CreateTextureFromRowDDS(img, size);
		goto END;
	}

	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	{
		int texSize = blockSize * ((hdr->w + 3) / 4) * ((hdr->h + 3) / 4);
		glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, hdr->w, hdr->h, 0, texSize, (char*)img + 128);
	}
	glBindTexture(GL_TEXTURE_2D, 0);

END:
	free(img);
	return texture;
}

#ifndef _MSC_VER
static GLuint LoadTextureJava(const char* name)
{
	jclass myview = jniEnv->FindClass(boundJavaClass);
	jmethodID method = method = jniEnv->GetStaticMethodID(myview, "loadTexture", "(Ljava/lang/String;)I");
	if (method == 0) {
		return 0;
	}
	return jniEnv->CallStaticIntMethod(myview, method, jniEnv->NewStringUTF(name));
}

static GLuint LoadTexture(const char* name)
{
	int len = strlen(name);
	if (len > 4 && !stricmp(name + len - 4, ".dds")) {
		return LoadDDSTexture(name);
	} else {
		return LoadTextureJava(name);
	}
}
#endif

#ifdef _MSC_VER
static GLuint LoadTexture(const char* name)
{
	int len = strlen(name);
	if (len > 4 && !stricmp(name + len - 4, ".dds")) {
		return LoadDDSTexture(name);
	} else {
		return LoadTextureViaGdiplus(name);
	}
}
#endif

static GLuint CreateWhiteTexture()
{
	uint32_t col = 0xffffffff;
	GLuint texture;
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &col);
	glBindTexture(GL_TEXTURE_2D, 0);
	return texture;
}

static GLuint CreateDynamicTexture(int w, int h)
{
	GLuint texture;
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
	glBindTexture(GL_TEXTURE_2D, 0);
	return texture;
}

TexMan::TMID TexMan::CreateDynamicTexture(const char* name, int w, int h)
{
	auto it = nameToId.find(name);
	if (it != nameToId.end())
	{
		return it->second;
	}
	return nameToId[name] = ::CreateDynamicTexture(w, h);
}

TexMan::TMID TexMan::Create(const char *name)
{
	NameToId::iterator it = nameToId.find(name);
	if (it != nameToId.end())
	{
		return it->second;
	}
	return nameToId[name] = LoadTexture(name);
}

TexMan::TMID TexMan::CreateWhiteTexture()
{
	const std::string name = "$WHITE";
	NameToId::iterator it = nameToId.find(name);
	if (it != nameToId.end())
	{
		return it->second;
	}
	return nameToId[name] = ::CreateWhiteTexture();
}

void TexMan::Destroy()
{
	for (NameToId::iterator it = nameToId.begin(); it != nameToId.end(); ++it)
	{
		GLuint id[1] = { it->second };
		glDeleteTextures(1, id);
	}
	nameToId.clear();
}

void TexMan::Write(TMID id, const void* buf, int w, int h)
{
	glBindTexture(GL_TEXTURE_2D, id);
	glTexSubImage2D(
		GL_TEXTURE_2D,
		0,
		0,
		0,
		w,
		h,
		GL_RGBA,
		GL_UNSIGNED_BYTE,
		buf
		);
	glBindTexture(GL_TEXTURE_2D, 0);
}
<|endoftext|>


<commit_before>#include "Common.hpp"
#include "DagData.hpp"
#include "StateData.hpp"
#include "ScanData.hpp"
#include "MemoryMappedFile.hpp"

#include <stdio.h>
#include <stdlib.h>

using namespace t2;

static void DumpDag(const DagData* data)
{
  int node_count = data->m_NodeCount;
  printf("magic number: 0x%08x\n", data->m_MagicNumber);
  printf("node count: %u\n", node_count);
  for (int i = 0; i < node_count; ++i)
  {
    printf("node %d:\n", i);
    char digest_str[41];
    DigestToString(digest_str, data->m_NodeGuids[i]);

    const NodeData& node = data->m_NodeData[i];

    printf("  guid: %s\n", digest_str);
    printf("  action: %s\n", node.m_Action.Get());
    printf("  preaction: %s\n", node.m_PreAction.Get() ? node.m_PreAction.Get() : "(null)");
    printf("  annotation: %s\n", node.m_Annotation.Get());
    printf("  pass index: %u\n", node.m_PassIndex);

    printf("  dependencies:");
    for (int32_t dep : node.m_Dependencies)
      printf(" %u", dep);
    printf("\n");

    printf("  backlinks:");
    for (int32_t link : node.m_BackLinks)
      printf(" %u", link);
    printf("\n");

    printf("  inputs:\n");
    for (const char* path : node.m_InputFiles)
      printf("    %s\n", path);

    printf("  outputs:\n");
    for (const char* path : node.m_OutputFiles)
      printf("    %s\n", path);

    printf("  aux_outputs:\n");
    for (const char* path : node.m_AuxOutputFiles)
      printf("    %s\n", path);

    if (const ScannerData* s = node.m_Scanner)
    {
      printf("  scanner:\n");
      switch (s->m_ScannerType)
      {
        case ScannerType::kCpp:
          printf("    type: cpp\n");
          break;
        case ScannerType::kGeneric:
          printf("    type: generic\n");
          break;
        default:
          printf("    type: garbage!\n");
          break;
      }

      printf("    include paths:\n");
      for (const char* path : s->m_IncludePaths)
      {
        printf("      %s\n", path);
      }
      DigestToString(digest_str, s->m_ScannerGuid);
      printf("    scanner guid: %s\n", digest_str);

      if (ScannerType::kGeneric == s->m_ScannerType)
      {
        const GenericScannerData* gs = static_cast<const GenericScannerData*>(s);
        printf("    flags:");
        if (GenericScannerData::kFlagRequireWhitespace & gs->m_Flags)
          printf(" RequireWhitespace");
        if (GenericScannerData::kFlagUseSeparators & gs->m_Flags)
          printf(" UseSeparators");
        if (GenericScannerData::kFlagBareMeansSystem & gs->m_Flags)
          printf(" BareMeansSystem");
        printf("\n");

        printf("    keywords:\n");
        for (const KeywordData& kw : gs->m_Keywords)
        {
          printf("      \"%s\" (%d bytes) follow: %s\n",
              kw.m_String.Get(), kw.m_StringLength, kw.m_ShouldFollow ? "yes" : "no");
        }
      }
    }

    printf("\n");
  }

  printf("\npass count: %u\n", data->m_Passes.GetCount());
  for (const PassData& pass : data->m_Passes)
  {
    printf("  pass: %s\n", pass.m_PassName.Get());
  }

  printf("\nconfig count: %u\n", data->m_ConfigCount);
  for (int i = 0; i < data->m_ConfigCount; ++i)
  {
    printf("  %d: name=\"%s\" hash=0x%08x\n", i, data->m_ConfigNames[i].Get(), data->m_ConfigNameHashes[i]);
  }

  printf("\nvariant count: %u\n", data->m_VariantCount);
  for (int i = 0; i < data->m_VariantCount; ++i)
  {
    printf("  %d: name=\"%s\" hash=0x%08x\n", i, data->m_VariantNames[i].Get(), data->m_VariantNameHashes[i]);
  }

  printf("\nsubvariant count: %u\n", data->m_SubVariantCount);
  for (int i = 0; i < data->m_SubVariantCount; ++i)
  {
    printf("  %d: name=\"%s\" hash=0x%08x\n", i, data->m_SubVariantNames[i].Get(), data->m_SubVariantNameHashes[i]);
  }

  printf("\ndefault config index: %d\n", data->m_DefaultConfigIndex);
  printf("default variant index: %d\n", data->m_DefaultVariantIndex);
  printf("default subvariant index: %d\n", data->m_DefaultSubVariantIndex);

  printf("\nbuild tuples:\n");
  for (const BuildTupleData& tuple : data->m_BuildTuples)
  {
    printf("config index    : %d\n", tuple.m_ConfigIndex);
    printf("variant index   : %d\n", tuple.m_VariantIndex);
    printf("subvariant index: %d\n", tuple.m_SubVariantIndex);
    printf("always nodes    :");
    for (int node : tuple.m_AlwaysNodes)
      printf(" %d", node);
    printf("\n");
    printf("default nodes   :");
    for (int node : tuple.m_DefaultNodes)
      printf(" %d", node);
    printf("\n");
    printf("named nodes:\n");
    for (const NamedNodeData& nn : tuple.m_NamedNodes)
      printf("  %s - node %d\n", nn.m_Name.Get(), nn.m_NodeIndex);
    printf("\n");
  }
}

static void DumpState(const StateData* data)
{
  int node_count = data->m_NodeCount;
  printf("magic number: 0x%08x\n", data->m_MagicNumber);
  printf("node count: %u\n", node_count);
  for (int i = 0; i < node_count; ++i)
  {
    printf("node %d:\n", i);
    char digest_str[41];

    const NodeStateData& node = data->m_NodeStates[i];

    DigestToString(digest_str, data->m_NodeGuids[i]);
    printf("  guid: %s\n", digest_str);
    printf("  build result: %d\n", node.m_BuildResult);
    DigestToString(digest_str, node.m_InputSignature);
    printf("  input_signature: %s\n", digest_str);
    printf("  outputs:\n");
    for (const char* path : node.m_OutputFiles)
      printf("    %s\n", path);
    printf("  aux outputs:\n");
    for (const char* path : node.m_AuxOutputFiles)
      printf("    %s\n", path);
    printf("\n");
  }
}

static void DumpScanCache(const ScanData* data)
{
  int entry_count = data->m_EntryCount;
  printf("magic number: 0x%08x\n", data->m_MagicNumber);
  printf("entry count: %d\n", entry_count);
  for (int i = 0; i < entry_count; ++i)
  {
    printf("entry %d:\n", i);
    char digest_str[41];

    const ScanCacheEntry& entry = data->m_Data[i];

    DigestToString(digest_str, data->m_Keys[i]);
    printf("  guid: %s\n", digest_str);
    printf("  access time stamp: %llu\n", (long long unsigned int) data->m_AccessTimes[i]);
    printf("  file time stamp: %llu\n", (long long unsigned int) entry.m_FileTimestamp);
    printf("  included files:\n");
    for (const char* path : entry.m_IncludedFiles)
      printf("    %s\n", path);
  }
}

int main(int argc, char* argv[])
{
  MemoryMappedFile f;

  const char* fn = argc >=2 ? argv[1] : ".tundra2.dag";

  MmapFileInit(&f);
  MmapFileMap(&f, fn);

  if (MmapFileValid(&f))
  {
    const char* suffix = strrchr(fn, '.');

    if (0 == strcmp(suffix, ".dag"))
    {
      const DagData* data = (const DagData*) f.m_Address;
      if (data->m_MagicNumber == DagData::MagicNumber)
      {
        DumpDag(data);
      }
      else
      {
        fprintf(stderr, "%s: bad magic number\n", fn);
      }
    }
    else if (0 == strcmp(suffix, ".state"))
    {
      const StateData* data = (const StateData*) f.m_Address;
      if (data->m_MagicNumber == StateData::MagicNumber)
      {
        DumpState(data);
      }
      else
      {
        fprintf(stderr, "%s: bad magic number\n", fn);
      }
    }
    else if (0 == strcmp(suffix, ".scancache"))
    {
      const ScanData* data = (const ScanData*) f.m_Address;
      if (data->m_MagicNumber == ScanData::MagicNumber)
      {
        DumpScanCache(data);
      }
      else
      {
        fprintf(stderr, "%s: bad magic number\n", fn);
      }
    }
    else
    {
      fprintf(stderr, "%s: unknown file type\n", fn);
    }
  }
  else
  {
    fprintf(stderr, "%s: couldn't mmap file\n", fn);
  }

  MmapFileUnmap(&f);
  return 0;
}
<commit_msg>t2-inspect: Dump env vars too.<commit_after>#include "Common.hpp"
#include "DagData.hpp"
#include "StateData.hpp"
#include "ScanData.hpp"
#include "MemoryMappedFile.hpp"

#include <stdio.h>
#include <stdlib.h>

using namespace t2;

static void DumpDag(const DagData* data)
{
  int node_count = data->m_NodeCount;
  printf("magic number: 0x%08x\n", data->m_MagicNumber);
  printf("node count: %u\n", node_count);
  for (int i = 0; i < node_count; ++i)
  {
    printf("node %d:\n", i);
    char digest_str[41];
    DigestToString(digest_str, data->m_NodeGuids[i]);

    const NodeData& node = data->m_NodeData[i];

    printf("  guid: %s\n", digest_str);
    printf("  action: %s\n", node.m_Action.Get());
    printf("  preaction: %s\n", node.m_PreAction.Get() ? node.m_PreAction.Get() : "(null)");
    printf("  annotation: %s\n", node.m_Annotation.Get());
    printf("  pass index: %u\n", node.m_PassIndex);

    printf("  dependencies:");
    for (int32_t dep : node.m_Dependencies)
      printf(" %u", dep);
    printf("\n");

    printf("  backlinks:");
    for (int32_t link : node.m_BackLinks)
      printf(" %u", link);
    printf("\n");

    printf("  inputs:\n");
    for (const char* path : node.m_InputFiles)
      printf("    %s\n", path);

    printf("  outputs:\n");
    for (const char* path : node.m_OutputFiles)
      printf("    %s\n", path);

    printf("  aux_outputs:\n");
    for (const char* path : node.m_AuxOutputFiles)
      printf("    %s\n", path);

    printf("  environment:\n");
    for (const EnvVarData& env : node.m_EnvVars)
    {
      printf("    %s = %s\n", env.m_Name.Get(), env.m_Value.Get());
    }

    if (const ScannerData* s = node.m_Scanner)
    {
      printf("  scanner:\n");
      switch (s->m_ScannerType)
      {
        case ScannerType::kCpp:
          printf("    type: cpp\n");
          break;
        case ScannerType::kGeneric:
          printf("    type: generic\n");
          break;
        default:
          printf("    type: garbage!\n");
          break;
      }

      printf("    include paths:\n");
      for (const char* path : s->m_IncludePaths)
      {
        printf("      %s\n", path);
      }
      DigestToString(digest_str, s->m_ScannerGuid);
      printf("    scanner guid: %s\n", digest_str);

      if (ScannerType::kGeneric == s->m_ScannerType)
      {
        const GenericScannerData* gs = static_cast<const GenericScannerData*>(s);
        printf("    flags:");
        if (GenericScannerData::kFlagRequireWhitespace & gs->m_Flags)
          printf(" RequireWhitespace");
        if (GenericScannerData::kFlagUseSeparators & gs->m_Flags)
          printf(" UseSeparators");
        if (GenericScannerData::kFlagBareMeansSystem & gs->m_Flags)
          printf(" BareMeansSystem");
        printf("\n");

        printf("    keywords:\n");
        for (const KeywordData& kw : gs->m_Keywords)
        {
          printf("      \"%s\" (%d bytes) follow: %s\n",
              kw.m_String.Get(), kw.m_StringLength, kw.m_ShouldFollow ? "yes" : "no");
        }
      }
    }

    printf("\n");
  }

  printf("\npass count: %u\n", data->m_Passes.GetCount());
  for (const PassData& pass : data->m_Passes)
  {
    printf("  pass: %s\n", pass.m_PassName.Get());
  }

  printf("\nconfig count: %u\n", data->m_ConfigCount);
  for (int i = 0; i < data->m_ConfigCount; ++i)
  {
    printf("  %d: name=\"%s\" hash=0x%08x\n", i, data->m_ConfigNames[i].Get(), data->m_ConfigNameHashes[i]);
  }

  printf("\nvariant count: %u\n", data->m_VariantCount);
  for (int i = 0; i < data->m_VariantCount; ++i)
  {
    printf("  %d: name=\"%s\" hash=0x%08x\n", i, data->m_VariantNames[i].Get(), data->m_VariantNameHashes[i]);
  }

  printf("\nsubvariant count: %u\n", data->m_SubVariantCount);
  for (int i = 0; i < data->m_SubVariantCount; ++i)
  {
    printf("  %d: name=\"%s\" hash=0x%08x\n", i, data->m_SubVariantNames[i].Get(), data->m_SubVariantNameHashes[i]);
  }

  printf("\ndefault config index: %d\n", data->m_DefaultConfigIndex);
  printf("default variant index: %d\n", data->m_DefaultVariantIndex);
  printf("default subvariant index: %d\n", data->m_DefaultSubVariantIndex);

  printf("\nbuild tuples:\n");
  for (const BuildTupleData& tuple : data->m_BuildTuples)
  {
    printf("config index    : %d\n", tuple.m_ConfigIndex);
    printf("variant index   : %d\n", tuple.m_VariantIndex);
    printf("subvariant index: %d\n", tuple.m_SubVariantIndex);
    printf("always nodes    :");
    for (int node : tuple.m_AlwaysNodes)
      printf(" %d", node);
    printf("\n");
    printf("default nodes   :");
    for (int node : tuple.m_DefaultNodes)
      printf(" %d", node);
    printf("\n");
    printf("named nodes:\n");
    for (const NamedNodeData& nn : tuple.m_NamedNodes)
      printf("  %s - node %d\n", nn.m_Name.Get(), nn.m_NodeIndex);
    printf("\n");
  }
}

static void DumpState(const StateData* data)
{
  int node_count = data->m_NodeCount;
  printf("magic number: 0x%08x\n", data->m_MagicNumber);
  printf("node count: %u\n", node_count);
  for (int i = 0; i < node_count; ++i)
  {
    printf("node %d:\n", i);
    char digest_str[41];

    const NodeStateData& node = data->m_NodeStates[i];

    DigestToString(digest_str, data->m_NodeGuids[i]);
    printf("  guid: %s\n", digest_str);
    printf("  build result: %d\n", node.m_BuildResult);
    DigestToString(digest_str, node.m_InputSignature);
    printf("  input_signature: %s\n", digest_str);
    printf("  outputs:\n");
    for (const char* path : node.m_OutputFiles)
      printf("    %s\n", path);
    printf("  aux outputs:\n");
    for (const char* path : node.m_AuxOutputFiles)
      printf("    %s\n", path);
    printf("\n");
  }
}

static void DumpScanCache(const ScanData* data)
{
  int entry_count = data->m_EntryCount;
  printf("magic number: 0x%08x\n", data->m_MagicNumber);
  printf("entry count: %d\n", entry_count);
  for (int i = 0; i < entry_count; ++i)
  {
    printf("entry %d:\n", i);
    char digest_str[41];

    const ScanCacheEntry& entry = data->m_Data[i];

    DigestToString(digest_str, data->m_Keys[i]);
    printf("  guid: %s\n", digest_str);
    printf("  access time stamp: %llu\n", (long long unsigned int) data->m_AccessTimes[i]);
    printf("  file time stamp: %llu\n", (long long unsigned int) entry.m_FileTimestamp);
    printf("  included files:\n");
    for (const char* path : entry.m_IncludedFiles)
      printf("    %s\n", path);
  }
}

int main(int argc, char* argv[])
{
  MemoryMappedFile f;

  const char* fn = argc >=2 ? argv[1] : ".tundra2.dag";

  MmapFileInit(&f);
  MmapFileMap(&f, fn);

  if (MmapFileValid(&f))
  {
    const char* suffix = strrchr(fn, '.');

    if (0 == strcmp(suffix, ".dag"))
    {
      const DagData* data = (const DagData*) f.m_Address;
      if (data->m_MagicNumber == DagData::MagicNumber)
      {
        DumpDag(data);
      }
      else
      {
        fprintf(stderr, "%s: bad magic number\n", fn);
      }
    }
    else if (0 == strcmp(suffix, ".state"))
    {
      const StateData* data = (const StateData*) f.m_Address;
      if (data->m_MagicNumber == StateData::MagicNumber)
      {
        DumpState(data);
      }
      else
      {
        fprintf(stderr, "%s: bad magic number\n", fn);
      }
    }
    else if (0 == strcmp(suffix, ".scancache"))
    {
      const ScanData* data = (const ScanData*) f.m_Address;
      if (data->m_MagicNumber == ScanData::MagicNumber)
      {
        DumpScanCache(data);
      }
      else
      {
        fprintf(stderr, "%s: bad magic number\n", fn);
      }
    }
    else
    {
      fprintf(stderr, "%s: unknown file type\n", fn);
    }
  }
  else
  {
    fprintf(stderr, "%s: couldn't mmap file\n", fn);
  }

  MmapFileUnmap(&f);
  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "Glue.hxx"
#include "Client.hxx"
#include "http_response.hxx"
#include "http_address.hxx"
#include "header_writer.hxx"
#include "stock/GetHandler.hxx"
#include "stock/Item.hxx"
#include "strmap.hxx"
#include "lease.hxx"
#include "tcp_stock.hxx"
#include "tcp_balancer.hxx"
#include "abort_close.hxx"
#include "istream/istream.hxx"
#include "istream/UnusedHoldPtr.hxx"
#include "net/SocketDescriptor.hxx"
#include "net/SocketAddress.hxx"
#include "pool.hxx"
#include "util/Cancellable.hxx"

#include "util/Compiler.h"

#include <string.h>
#include <sys/socket.h>

struct AjpRequest final : Cancellable, StockGetHandler, Lease {
    struct pool &pool;
    EventLoop &event_loop;

    StockItem *stock_item;

    const char *const protocol;
    const char *const remote_addr;
    const char *const remote_host;
    const char *const server_name;
    const unsigned server_port;
    const bool is_ssl;

    const http_method_t method;
    const char *const uri;
    StringMap headers;
    UnusedHoldIstreamPtr body;

    HttpResponseHandler &handler;
    CancellablePointer &cancel_ptr;

    AjpRequest(struct pool &_pool, EventLoop &_event_loop,
               const char *_protocol, const char *_remote_addr,
               const char *_remote_host, const char *_server_name,
               unsigned _server_port, bool _is_ssl,
               http_method_t _method, const char *_uri,
               StringMap &&_headers,
               Istream *_body,
               HttpResponseHandler &_handler,
               CancellablePointer &_cancel_ptr)
        :pool(_pool), event_loop(_event_loop),
         protocol(_protocol),
         remote_addr(_remote_addr), remote_host(_remote_host),
         server_name(_server_name), server_port(_server_port),
         is_ssl(_is_ssl),
         method(_method), uri(_uri),
         headers(std::move(_headers)), body(pool, _body),
         handler(_handler),
         cancel_ptr(_cancel_ptr) {
    }

    void BeginConnect(TcpBalancer &tcp_balancer, sticky_hash_t session_sticky,
                      const HttpAddress &address) {
        tcp_balancer.Get(pool,
                         false, SocketAddress::Null(),
                         session_sticky,
                         address.addresses,
                         20,
                         *this, cancel_ptr);
    }

private:
    /* virtual methods from class Cancellable */
    void Cancel() override {
        body.Clear();
        cancel_ptr.Cancel();
    }

    /* virtual methods from class StockGetHandler */
    void OnStockItemReady(StockItem &item) override;
    void OnStockItemError(std::exception_ptr ep) override;

    /* virtual methods from class Lease */
    void ReleaseLease(bool reuse) override {
        stock_item->Put(!reuse);
    }
};

/*
 * stock callback
 *
 */

void
AjpRequest::OnStockItemReady(StockItem &item)
{
    stock_item = &item;

    ajp_client_request(pool, event_loop,
                       tcp_stock_item_get(item),
                       tcp_stock_item_get_domain(item) == AF_LOCAL
                       ? FdType::FD_SOCKET : FdType::FD_TCP,
                       *this,
                       protocol, remote_addr,
                       remote_host, server_name,
                       server_port, is_ssl,
                       method, uri, headers, body.Steal(),
                       handler, cancel_ptr);
}

void
AjpRequest::OnStockItemError(std::exception_ptr ep)
{
    body.Clear();
    handler.InvokeError(ep);
}

/*
 * constructor
 *
 */

void
ajp_stock_request(struct pool &pool, EventLoop &event_loop,
                  TcpBalancer &tcp_balancer,
                  sticky_hash_t session_sticky,
                  const char *protocol, const char *remote_addr,
                  const char *remote_host, const char *server_name,
                  unsigned server_port, bool is_ssl,
                  http_method_t method,
                  const HttpAddress &uwa,
                  StringMap &&headers,
                  Istream *body,
                  HttpResponseHandler &handler,
                  CancellablePointer &_cancel_ptr)
{
    assert(uwa.path != nullptr);
    assert(body == nullptr || !body->HasHandler());

    auto hr = NewFromPool<AjpRequest>(pool, pool, event_loop,
                                      protocol,
                                      remote_addr, remote_host,
                                      server_name, server_port,
                                      is_ssl, method, uwa.path,
                                      std::move(headers), body,
                                      handler, _cancel_ptr);

    hr->BeginConnect(tcp_balancer, session_sticky, uwa);
}
<commit_msg>ajp/Glue: convert struct to class<commit_after>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "Glue.hxx"
#include "Client.hxx"
#include "http_response.hxx"
#include "http_address.hxx"
#include "header_writer.hxx"
#include "stock/GetHandler.hxx"
#include "stock/Item.hxx"
#include "strmap.hxx"
#include "lease.hxx"
#include "tcp_stock.hxx"
#include "tcp_balancer.hxx"
#include "abort_close.hxx"
#include "istream/istream.hxx"
#include "istream/UnusedHoldPtr.hxx"
#include "net/SocketDescriptor.hxx"
#include "net/SocketAddress.hxx"
#include "pool.hxx"
#include "util/Cancellable.hxx"

#include "util/Compiler.h"

#include <string.h>
#include <sys/socket.h>

class AjpRequest final : Cancellable, StockGetHandler, Lease {
    struct pool &pool;
    EventLoop &event_loop;

    StockItem *stock_item;

    const char *const protocol;
    const char *const remote_addr;
    const char *const remote_host;
    const char *const server_name;
    const unsigned server_port;
    const bool is_ssl;

    const http_method_t method;
    const char *const uri;
    StringMap headers;
    UnusedHoldIstreamPtr body;

    HttpResponseHandler &handler;
    CancellablePointer &cancel_ptr;

public:
    AjpRequest(struct pool &_pool, EventLoop &_event_loop,
               const char *_protocol, const char *_remote_addr,
               const char *_remote_host, const char *_server_name,
               unsigned _server_port, bool _is_ssl,
               http_method_t _method, const char *_uri,
               StringMap &&_headers,
               Istream *_body,
               HttpResponseHandler &_handler,
               CancellablePointer &_cancel_ptr)
        :pool(_pool), event_loop(_event_loop),
         protocol(_protocol),
         remote_addr(_remote_addr), remote_host(_remote_host),
         server_name(_server_name), server_port(_server_port),
         is_ssl(_is_ssl),
         method(_method), uri(_uri),
         headers(std::move(_headers)), body(pool, _body),
         handler(_handler),
         cancel_ptr(_cancel_ptr) {
    }

    void BeginConnect(TcpBalancer &tcp_balancer, sticky_hash_t session_sticky,
                      const HttpAddress &address) {
        tcp_balancer.Get(pool,
                         false, SocketAddress::Null(),
                         session_sticky,
                         address.addresses,
                         20,
                         *this, cancel_ptr);
    }

private:
    /* virtual methods from class Cancellable */
    void Cancel() override {
        body.Clear();
        cancel_ptr.Cancel();
    }

    /* virtual methods from class StockGetHandler */
    void OnStockItemReady(StockItem &item) override;
    void OnStockItemError(std::exception_ptr ep) override;

    /* virtual methods from class Lease */
    void ReleaseLease(bool reuse) override {
        stock_item->Put(!reuse);
    }
};

/*
 * stock callback
 *
 */

void
AjpRequest::OnStockItemReady(StockItem &item)
{
    stock_item = &item;

    ajp_client_request(pool, event_loop,
                       tcp_stock_item_get(item),
                       tcp_stock_item_get_domain(item) == AF_LOCAL
                       ? FdType::FD_SOCKET : FdType::FD_TCP,
                       *this,
                       protocol, remote_addr,
                       remote_host, server_name,
                       server_port, is_ssl,
                       method, uri, headers, body.Steal(),
                       handler, cancel_ptr);
}

void
AjpRequest::OnStockItemError(std::exception_ptr ep)
{
    body.Clear();
    handler.InvokeError(ep);
}

/*
 * constructor
 *
 */

void
ajp_stock_request(struct pool &pool, EventLoop &event_loop,
                  TcpBalancer &tcp_balancer,
                  sticky_hash_t session_sticky,
                  const char *protocol, const char *remote_addr,
                  const char *remote_host, const char *server_name,
                  unsigned server_port, bool is_ssl,
                  http_method_t method,
                  const HttpAddress &uwa,
                  StringMap &&headers,
                  Istream *body,
                  HttpResponseHandler &handler,
                  CancellablePointer &_cancel_ptr)
{
    assert(uwa.path != nullptr);
    assert(body == nullptr || !body->HasHandler());

    auto hr = NewFromPool<AjpRequest>(pool, pool, event_loop,
                                      protocol,
                                      remote_addr, remote_host,
                                      server_name, server_port,
                                      is_ssl, method, uwa.path,
                                      std::move(headers), body,
                                      handler, _cancel_ptr);

    hr->BeginConnect(tcp_balancer, session_sticky, uwa);
}
<|endoftext|>


<commit_before>// This file is part of OpenMVG, an Open Multiple View Geometry C++ library.

// Copyright (c) 2015 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "openMVG/sfm/pipelines/localization/SfM_Localizer.hpp"

#include "openMVG/cameras/Camera_Common.hpp"
#include "openMVG/cameras/Camera_Intrinsics.hpp"
#include "openMVG/cameras/Camera_Pinhole.hpp"
#include "openMVG/multiview/solver_resection_kernel.hpp"
#include "openMVG/multiview/solver_resection_p3p.hpp"
#include "openMVG/sfm/sfm_data.hpp"
#include "openMVG/sfm/sfm_data_BA.hpp"
#include "openMVG/sfm/sfm_data_BA_ceres.hpp"
#include "openMVG/sfm/sfm_landmark.hpp"
#include "openMVG/robust_estimation/robust_estimator_ACRansac.hpp"
#include "openMVG/robust_estimation/robust_estimator_ACRansacKernelAdaptator.hpp"

#include <memory>
#include <utility>

namespace openMVG
{
/// Pose/Resection Kernel adapter for the A contrario model estimator with
///  known camera intrinsics.
template <typename SolverArg,
  typename ModelArg = Mat34>
class ACKernelAdaptorResection_Intrinsics
{
public:
  using Solver = SolverArg;
  using Model = ModelArg;

  ACKernelAdaptorResection_Intrinsics
  (
    const Mat & x2d, // Undistorted 2d feature_point location
    const Mat & x3D, // 3D corresponding points
    const cameras::IntrinsicBase * camera
  ):x2d_(x2d),
    x3D_(x3D),
    logalpha0_(log10(M_PI)),
    N1_(Mat3::Identity()),
    camera_(camera)
  {
    N1_.diagonal().head(2) *= camera->imagePlane_toCameraPlaneError(1.0);
    assert(2 == x2d_.rows());
    assert(3 == x3D_.rows());
    assert(x2d_.cols() == x3D_.cols());
    bearing_vectors_= camera->operator()(x2d_);
  }

  enum { MINIMUM_SAMPLES = Solver::MINIMUM_SAMPLES };
  enum { MAX_MODELS = Solver::MAX_MODELS };

  void Fit(const std::vector<uint32_t> &samples, std::vector<Model> *models) const {
    Solver::Solve(ExtractColumns(bearing_vectors_, samples), // bearing vectors
                  ExtractColumns(x3D_, samples), // 3D points
                  models); // Found model hypothesis
  }

  double Error(uint32_t sample, const Model &model) const {
    const Vec3 t = model.block(0, 3, 3, 1);
    const geometry::Pose3 pose(model.block(0, 0, 3, 3),
                               - model.block(0, 0, 3, 3).transpose() * t);
    const bool ignore_distortion = true; // We ignore distortion since we are using undistorted bearing vector as input
    return (camera_->residual(pose(x3D_.col(sample)),
                              x2d_.col(sample),
                              ignore_distortion) * N1_(0,0)).squaredNorm();
  }

  void Errors(const Model & model, std::vector<double> & vec_errors) const
  {
    const Vec3 t = model.block(0, 3, 3, 1);
    const geometry::Pose3 pose(model.block(0, 0, 3, 3),
                               - model.block(0, 0, 3, 3).transpose() * t);

    vec_errors.resize(x2d_.cols());
    for (Mat::Index sample = 0; sample < x2d_.cols(); ++sample)
    {
      vec_errors[sample] = this->Error(sample, model);
    }
  }

  size_t NumSamples() const { return x2d_.cols(); }

  void Unnormalize(Model * model) const {
  }

  double logalpha0() const {return logalpha0_;}
  double multError() const {return 1.0;} // point to point error
  Mat3 normalizer1() const {return Mat3::Identity();}
  Mat3 normalizer2() const {return N1_;}
  double unormalizeError(double val) const {return sqrt(val) / N1_(0,0);}

private:
  Mat x2d_, bearing_vectors_;
  const Mat & x3D_;
  Mat3 N1_;
  double logalpha0_;  // Alpha0 is used to make the error adaptive to the image size
  const cameras::IntrinsicBase * camera_;   // Intrinsic camera parameter
};
} // namespace openMVG

namespace openMVG {
namespace sfm {

  struct ResectionSquaredResidualError {
    // Compute the residual of the projection distance(pt2D, Project(P,pt3D))
    // Return the squared error
    static double Error(const Mat34 & P, const Vec2 & pt2D, const Vec3 & pt3D) {
      const Vec2 x = Project(P, pt3D);
      return (x - pt2D).squaredNorm();
    }
  };

  bool SfM_Localizer::Localize
  (
    const resection::SolverType & solver_type,
    const Pair & image_size,
    const cameras::IntrinsicBase * optional_intrinsics,
    Image_Localizer_Match_Data & resection_data,
    geometry::Pose3 & pose
  )
  {
    // --
    // Compute the camera pose (resectioning)
    // --
    Mat34 P;
    resection_data.vec_inliers.clear();

    // Setup the admissible upper bound residual error
    const double dPrecision =
      resection_data.error_max == std::numeric_limits<double>::infinity() ?
      std::numeric_limits<double>::infinity() :
      Square(resection_data.error_max);

    size_t MINIMUM_SAMPLES = 0;

    switch (solver_type)
    {
      case resection::SolverType::DLT_6POINTS:
      {
        //--
        // Classic resection (try to compute the entire P matrix)
        using SolverType = openMVG::resection::kernel::SixPointResectionSolver;
        MINIMUM_SAMPLES = SolverType::MINIMUM_SAMPLES;

        using KernelType =
          openMVG::robust::ACKernelAdaptorResection<
            SolverType,
            ResectionSquaredResidualError,
            openMVG::robust::UnnormalizerResection,
            Mat34>;

        KernelType kernel(resection_data.pt2D, image_size.first, image_size.second,
          resection_data.pt3D);
        // Robust estimation of the pose and its precision
        const std::pair<double,double> ACRansacOut =
          openMVG::robust::ACRANSAC(kernel,
                                    resection_data.vec_inliers,
                                    resection_data.max_iteration,
                                    &P,
                                    dPrecision,
                                    true);
        // Update the upper bound precision of the model found by AC-RANSAC
        resection_data.error_max = ACRansacOut.first;
      }
      break;
      case resection::SolverType::P3P_KE_CVPR17:
      {
        if (!optional_intrinsics)
        {
          std::cerr << "Intrinsic data is required for P3P solvers." << std::endl;
          return false;
        }
        //--
        // Since the intrinsic data is known, compute only the pose
        using SolverType = openMVG::euclidean_resection::P3PSolver_Ke;
        MINIMUM_SAMPLES = SolverType::MINIMUM_SAMPLES;

        using KernelType =
          ACKernelAdaptorResection_Intrinsics<
            SolverType,
            Mat34>;

        KernelType kernel(resection_data.pt2D, resection_data.pt3D, optional_intrinsics);
        // Robust estimation of the pose matrix and its precision
        const auto ACRansacOut =
          openMVG::robust::ACRANSAC(kernel,
                                    resection_data.vec_inliers,
                                    resection_data.max_iteration,
                                    &P,
                                    dPrecision,
                                    true);
        // Update the upper bound precision of the model found by AC-RANSAC
        resection_data.error_max = ACRansacOut.first;
      }
      break;
      case resection::SolverType::P3P_KNEIP_CVPR11:
      {
        if (!optional_intrinsics)
        {
          std::cerr << "Intrinsic data is required for P3P solvers." << std::endl;
          return false;
        }
        //--
        // Since the intrinsic data is known, compute only the pose
        using SolverType = openMVG::euclidean_resection::P3PSolver_Kneip;
        MINIMUM_SAMPLES = SolverType::MINIMUM_SAMPLES;

        using KernelType =
          ACKernelAdaptorResection_Intrinsics<
            SolverType,
            Mat34>;

        KernelType kernel(resection_data.pt2D, resection_data.pt3D, optional_intrinsics);

        // Robust estimation of the pose matrix and its precision
        const auto ACRansacOut =
          openMVG::robust::ACRANSAC(kernel,
                                    resection_data.vec_inliers,
                                    resection_data.max_iteration,
                                    &P,
                                    dPrecision,
                                    true);
        // Update the upper bound precision of the model found by AC-RANSAC
        resection_data.error_max = ACRansacOut.first;
      }
      break;
      default:
      {
        std::cerr << "Unknown absolute pose solver type." << std::endl;
        return false;
      }
    }

    // Test if the mode support some points (more than those required for estimation)
    const bool bResection = (resection_data.vec_inliers.size() > 2.5 * MINIMUM_SAMPLES);

    if (bResection)
    {
      resection_data.projection_matrix = P;
      Mat3 K, R;
      Vec3 t;
      KRt_From_P(P, &K, &R, &t);
      pose = geometry::Pose3(R, -R.transpose() * t);
    }

    std::cout << "\n"
      << "-------------------------------" << "\n"
      << "-- Robust Resection " << "\n"
      << "-- Resection status: " << bResection << "\n"
      << "-- #Points used for Resection: " << resection_data.pt2D.cols() << "\n"
      << "-- #Points validated by robust Resection: " << resection_data.vec_inliers.size() << "\n"
      << "-- Threshold: " << resection_data.error_max << "\n"
      << "-------------------------------" << std::endl;

    return bResection;
  }

  bool SfM_Localizer::RefinePose
  (
    cameras::IntrinsicBase * intrinsics,
    geometry::Pose3 & pose,
    Image_Localizer_Match_Data & matching_data,
    bool b_refine_pose,
    bool b_refine_intrinsic
  )
  {
    if (!b_refine_pose && !b_refine_intrinsic)
    {
      // Nothing to do (There is no parameter to refine)
      return false;
    }

    // Setup a tiny SfM scene with the corresponding 2D-3D data
    SfM_Data sfm_data;
    // view
    sfm_data.views.insert({0, std::make_shared<View>("",0, 0, 0)});
    // pose
    sfm_data.poses[0] = pose;
    // intrinsic
    std::shared_ptr<cameras::IntrinsicBase> shared_intrinsics(intrinsics->clone());
    sfm_data.intrinsics[0] = shared_intrinsics;
    // structure data (2D-3D correspondences)
    for (size_t i = 0; i < matching_data.vec_inliers.size(); ++i)
    {
      const size_t idx = matching_data.vec_inliers[i];
      Landmark landmark;
      landmark.X = matching_data.pt3D.col(idx);
      landmark.obs[0] = Observation(matching_data.pt2D.col(idx), UndefinedIndexT);
      sfm_data.structure[i] = std::move(landmark);
    }

    // Configure BA options (refine the intrinsic and the pose parameter only if requested)
    const Optimize_Options ba_refine_options
    (
      (b_refine_intrinsic) ? cameras::Intrinsic_Parameter_Type::ADJUST_ALL : cameras::Intrinsic_Parameter_Type::NONE,
      (b_refine_pose) ? Extrinsic_Parameter_Type::ADJUST_ALL : Extrinsic_Parameter_Type::NONE,
      Structure_Parameter_Type::NONE // STRUCTURE must remain constant
    );
    Bundle_Adjustment_Ceres bundle_adjustment_obj;
    const bool b_BA_Status = bundle_adjustment_obj.Adjust(
      sfm_data,
      ba_refine_options);
    if (b_BA_Status)
    {
      pose = sfm_data.poses[0];
      if (b_refine_intrinsic)
        intrinsics->updateFromParams(shared_intrinsics->getParams());
    }

    return b_BA_Status;
  }

} // namespace sfm
} // namespace openMVG
<commit_msg>[SfM/Localizer] tiny refactoring<commit_after>// This file is part of OpenMVG, an Open Multiple View Geometry C++ library.

// Copyright (c) 2015 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "openMVG/sfm/pipelines/localization/SfM_Localizer.hpp"

#include "openMVG/cameras/Camera_Common.hpp"
#include "openMVG/cameras/Camera_Intrinsics.hpp"
#include "openMVG/cameras/Camera_Pinhole.hpp"
#include "openMVG/multiview/solver_resection_kernel.hpp"
#include "openMVG/multiview/solver_resection_p3p.hpp"
#include "openMVG/sfm/sfm_data.hpp"
#include "openMVG/sfm/sfm_data_BA.hpp"
#include "openMVG/sfm/sfm_data_BA_ceres.hpp"
#include "openMVG/sfm/sfm_landmark.hpp"
#include "openMVG/robust_estimation/robust_estimator_ACRansac.hpp"
#include "openMVG/robust_estimation/robust_estimator_ACRansacKernelAdaptator.hpp"

#include <memory>
#include <utility>

namespace openMVG
{
/// Pose/Resection Kernel adapter for the A contrario model estimator with
///  known camera intrinsics.
template <typename SolverArg,
  typename ModelArg = Mat34>
class ACKernelAdaptorResection_Intrinsics
{
public:
  using Solver = SolverArg;
  using Model = ModelArg;

  ACKernelAdaptorResection_Intrinsics
  (
    const Mat & x2d, // Undistorted 2d feature_point location
    const Mat & x3D, // 3D corresponding points
    const cameras::IntrinsicBase * camera
  ):x2d_(x2d),
    x3D_(x3D),
    logalpha0_(log10(M_PI)),
    N1_(Mat3::Identity()),
    camera_(camera)
  {
    N1_.diagonal().head(2) *= camera->imagePlane_toCameraPlaneError(1.0);
    assert(2 == x2d_.rows());
    assert(3 == x3D_.rows());
    assert(x2d_.cols() == x3D_.cols());
    bearing_vectors_= camera->operator()(x2d_);
  }

  enum { MINIMUM_SAMPLES = Solver::MINIMUM_SAMPLES };
  enum { MAX_MODELS = Solver::MAX_MODELS };

  void Fit(const std::vector<uint32_t> &samples, std::vector<Model> *models) const {
    Solver::Solve(ExtractColumns(bearing_vectors_, samples), // bearing vectors
                  ExtractColumns(x3D_, samples), // 3D points
                  models); // Found model hypothesis
  }

  void Errors(const Model & model, std::vector<double> & vec_errors) const
  {
    // Convert the found model into a Pose3
    const Vec3 t = model.block(0, 3, 3, 1);
    const geometry::Pose3 pose(model.block(0, 0, 3, 3),
                               - model.block(0, 0, 3, 3).transpose() * t);

    vec_errors.resize(x2d_.cols());

    const bool ignore_distortion = true; // We ignore distortion since we are using undistorted bearing vector as input

    for (Mat::Index sample = 0; sample < x2d_.cols(); ++sample)
    {
      vec_errors[sample] = (camera_->residual(pose(x3D_.col(sample)),
                              x2d_.col(sample),
                              ignore_distortion) * N1_(0,0)).squaredNorm();
    }
  }

  size_t NumSamples() const { return x2d_.cols(); }

  void Unnormalize(Model * model) const {
  }

  double logalpha0() const {return logalpha0_;}
  double multError() const {return 1.0;} // point to point error
  Mat3 normalizer1() const {return Mat3::Identity();}
  Mat3 normalizer2() const {return N1_;}
  double unormalizeError(double val) const {return sqrt(val) / N1_(0,0);}

private:
  Mat x2d_, bearing_vectors_;
  const Mat & x3D_;
  Mat3 N1_;
  double logalpha0_;  // Alpha0 is used to make the error adaptive to the image size
  const cameras::IntrinsicBase * camera_;   // Intrinsic camera parameter
};
} // namespace openMVG

namespace openMVG {
namespace sfm {

  struct ResectionSquaredResidualError {
    // Compute the residual of the projection distance(pt2D, Project(P,pt3D))
    // Return the squared error
    static double Error(const Mat34 & P, const Vec2 & pt2D, const Vec3 & pt3D) {
      const Vec2 x = Project(P, pt3D);
      return (x - pt2D).squaredNorm();
    }
  };

  bool SfM_Localizer::Localize
  (
    const resection::SolverType & solver_type,
    const Pair & image_size,
    const cameras::IntrinsicBase * optional_intrinsics,
    Image_Localizer_Match_Data & resection_data,
    geometry::Pose3 & pose
  )
  {
    // --
    // Compute the camera pose (resectioning)
    // --
    Mat34 P;
    resection_data.vec_inliers.clear();

    // Setup the admissible upper bound residual error
    const double dPrecision =
      resection_data.error_max == std::numeric_limits<double>::infinity() ?
      std::numeric_limits<double>::infinity() :
      Square(resection_data.error_max);

    size_t MINIMUM_SAMPLES = 0;

    switch (solver_type)
    {
      case resection::SolverType::DLT_6POINTS:
      {
        //--
        // Classic resection (try to compute the entire P matrix)
        using SolverType = openMVG::resection::kernel::SixPointResectionSolver;
        MINIMUM_SAMPLES = SolverType::MINIMUM_SAMPLES;

        using KernelType =
          openMVG::robust::ACKernelAdaptorResection<
            SolverType,
            ResectionSquaredResidualError,
            openMVG::robust::UnnormalizerResection,
            Mat34>;

        KernelType kernel(resection_data.pt2D, image_size.first, image_size.second,
          resection_data.pt3D);
        // Robust estimation of the pose and its precision
        const std::pair<double,double> ACRansacOut =
          openMVG::robust::ACRANSAC(kernel,
                                    resection_data.vec_inliers,
                                    resection_data.max_iteration,
                                    &P,
                                    dPrecision,
                                    true);
        // Update the upper bound precision of the model found by AC-RANSAC
        resection_data.error_max = ACRansacOut.first;
      }
      break;
      case resection::SolverType::P3P_KE_CVPR17:
      {
        if (!optional_intrinsics)
        {
          std::cerr << "Intrinsic data is required for P3P solvers." << std::endl;
          return false;
        }
        //--
        // Since the intrinsic data is known, compute only the pose
        using SolverType = openMVG::euclidean_resection::P3PSolver_Ke;
        MINIMUM_SAMPLES = SolverType::MINIMUM_SAMPLES;

        using KernelType =
          ACKernelAdaptorResection_Intrinsics<
            SolverType,
            Mat34>;

        KernelType kernel(resection_data.pt2D, resection_data.pt3D, optional_intrinsics);
        // Robust estimation of the pose matrix and its precision
        const auto ACRansacOut =
          openMVG::robust::ACRANSAC(kernel,
                                    resection_data.vec_inliers,
                                    resection_data.max_iteration,
                                    &P,
                                    dPrecision,
                                    true);
        // Update the upper bound precision of the model found by AC-RANSAC
        resection_data.error_max = ACRansacOut.first;
      }
      break;
      case resection::SolverType::P3P_KNEIP_CVPR11:
      {
        if (!optional_intrinsics)
        {
          std::cerr << "Intrinsic data is required for P3P solvers." << std::endl;
          return false;
        }
        //--
        // Since the intrinsic data is known, compute only the pose
        using SolverType = openMVG::euclidean_resection::P3PSolver_Kneip;
        MINIMUM_SAMPLES = SolverType::MINIMUM_SAMPLES;

        using KernelType =
          ACKernelAdaptorResection_Intrinsics<
            SolverType,
            Mat34>;

        KernelType kernel(resection_data.pt2D, resection_data.pt3D, optional_intrinsics);

        // Robust estimation of the pose matrix and its precision
        const auto ACRansacOut =
          openMVG::robust::ACRANSAC(kernel,
                                    resection_data.vec_inliers,
                                    resection_data.max_iteration,
                                    &P,
                                    dPrecision,
                                    true);
        // Update the upper bound precision of the model found by AC-RANSAC
        resection_data.error_max = ACRansacOut.first;
      }
      break;
      default:
      {
        std::cerr << "Unknown absolute pose solver type." << std::endl;
        return false;
      }
    }

    // Test if the mode support some points (more than those required for estimation)
    const bool bResection = (resection_data.vec_inliers.size() > 2.5 * MINIMUM_SAMPLES);

    if (bResection)
    {
      resection_data.projection_matrix = P;
      Mat3 K, R;
      Vec3 t;
      KRt_From_P(P, &K, &R, &t);
      pose = geometry::Pose3(R, -R.transpose() * t);
    }

    std::cout << "\n"
      << "-------------------------------" << "\n"
      << "-- Robust Resection " << "\n"
      << "-- Resection status: " << bResection << "\n"
      << "-- #Points used for Resection: " << resection_data.pt2D.cols() << "\n"
      << "-- #Points validated by robust Resection: " << resection_data.vec_inliers.size() << "\n"
      << "-- Threshold: " << resection_data.error_max << "\n"
      << "-------------------------------" << std::endl;

    return bResection;
  }

  bool SfM_Localizer::RefinePose
  (
    cameras::IntrinsicBase * intrinsics,
    geometry::Pose3 & pose,
    Image_Localizer_Match_Data & matching_data,
    bool b_refine_pose,
    bool b_refine_intrinsic
  )
  {
    if (!b_refine_pose && !b_refine_intrinsic)
    {
      // Nothing to do (There is no parameter to refine)
      return false;
    }

    // Setup a tiny SfM scene with the corresponding 2D-3D data
    SfM_Data sfm_data;
    // view
    sfm_data.views.insert({0, std::make_shared<View>("",0, 0, 0)});
    // pose
    sfm_data.poses[0] = pose;
    // intrinsic
    std::shared_ptr<cameras::IntrinsicBase> shared_intrinsics(intrinsics->clone());
    sfm_data.intrinsics[0] = shared_intrinsics;
    // structure data (2D-3D correspondences)
    for (size_t i = 0; i < matching_data.vec_inliers.size(); ++i)
    {
      const size_t idx = matching_data.vec_inliers[i];
      Landmark landmark;
      landmark.X = matching_data.pt3D.col(idx);
      landmark.obs[0] = Observation(matching_data.pt2D.col(idx), UndefinedIndexT);
      sfm_data.structure[i] = std::move(landmark);
    }

    // Configure BA options (refine the intrinsic and the pose parameter only if requested)
    const Optimize_Options ba_refine_options
    (
      (b_refine_intrinsic) ? cameras::Intrinsic_Parameter_Type::ADJUST_ALL : cameras::Intrinsic_Parameter_Type::NONE,
      (b_refine_pose) ? Extrinsic_Parameter_Type::ADJUST_ALL : Extrinsic_Parameter_Type::NONE,
      Structure_Parameter_Type::NONE // STRUCTURE must remain constant
    );
    Bundle_Adjustment_Ceres bundle_adjustment_obj;
    const bool b_BA_Status = bundle_adjustment_obj.Adjust(
      sfm_data,
      ba_refine_options);
    if (b_BA_Status)
    {
      pose = sfm_data.poses[0];
      if (b_refine_intrinsic)
        intrinsics->updateFromParams(shared_intrinsics->getParams());
    }

    return b_BA_Status;
  }

} // namespace sfm
} // namespace openMVG
<|endoftext|>