void PotreeConverter::convert(){
	aabb = calculateAABB(sources);
	cout << "AABB: " << endl << aabb << endl;

	aabb.makeCubic();

	cloudjs.boundingBox = aabb;

	auto start = high_resolution_clock::now();

	PotreeWriter writer(this->workDir, aabb, spacing, maxDepth, this->cloudJsOctreeDirPrefix, outputFormat);
	//PotreeWriterLBL writer(this->workDir, aabb, spacing, maxDepth, outputFormat);

	long long pointsProcessed = 0;
	for(int i = 0; i < sources.size(); i++){
		string source = sources[i];
		cout << "reading " << source << endl;

		PointReader *reader = createPointReader(source);
		while(reader->readNextPoint()){
			pointsProcessed++;
			//if((pointsProcessed%50) != 0){
			//	continue;
			//}

			Point p = reader->getPoint();
			writer.add(p);

			//if((pointsProcessed % (1000*1000)) == 0){
			//	//cout << (pointsProcessed / (1000*1000)) << "m points processed" << endl;
			//	cout << "flushing" << endl;
			//	writer.flush();
			//}

			if((pointsProcessed % (1000*1000)) == 0){
				writer.flush();

				cout << (pointsProcessed / (1000*1000)) << "m points processed" << endl;
				auto end = high_resolution_clock::now();
				long duration = duration_cast<milliseconds>(end-start).count();
				cout << "duration: " << (duration / 1000.0f) << "s" << endl;
				//return;
			}
		}
		writer.flush();
		reader->close();
		delete reader;
	}

	cout << writer.numAccepted << " points written" << endl;

	auto end = high_resolution_clock::now();
	long duration = duration_cast<milliseconds>(end-start).count();
	cout << "duration: " << (duration / 1000.0f) << "s" << endl;
	
	cout << "closing writer" << endl;
	writer.close();
}
void PotreeWriterNode::loadFromDisk(){
	PointReader *reader = createReader(path + "/data/" + name + potreeWriter->getExtension());
	while(reader->readNextPoint()){
		Point p = reader->getPoint();
		Vector3<double> position = Vector3<double>(p.x, p.y, p.z);
		grid->addWithoutCheck(position);
	}
	grid->numAccepted = numAccepted;
	reader->close();
	delete reader;
}
AABB calculateAABB(vector<string> sources){
	AABB aabb;

	for(int i = 0; i < sources.size(); i++){
		string source = sources[i];

		PointReader *reader = createPointReader(source);
		AABB lAABB = reader->getAABB();
		 

		aabb.update(lAABB.min);
		aabb.update(lAABB.max);

		reader->close();
		delete reader;
	}

	return aabb;
}
void PotreeWriterNode::flush(){

	if(cache.size() > 0){
		 // move data file aside to temporary directory for reading
		string filepath = path + "/data/" + name + potreeWriter->getExtension();
		string temppath = path +"/temp/prepend" + potreeWriter->getExtension();
		if(fs::exists(filepath)){
			fs::rename(fs::path(filepath), fs::path(temppath));
		}
		

		PointWriter *writer = createWriter(path + "/data/" + name + potreeWriter->getExtension(), scale);
		if(fs::exists(temppath)){
			PointReader *reader = createReader(temppath);
			while(reader->readNextPoint()){
				writer->write(reader->getPoint());
			}
			reader->close();
			delete reader;
			fs::remove(temppath);
		}

		for(int i = 0; i < cache.size(); i++){
			writer->write(cache[i]);
		}
		writer->close();
		delete writer;

		cache = vector<Point>();
	}else if(cache.size() == 0 && grid->numAccepted > 0 && addCalledSinceLastFlush == false){
		delete grid;
		grid = new SparseGrid(aabb, spacing);
	}
	
	addCalledSinceLastFlush = false;

	for(int i = 0; i < 8; i++){
		if(children[i] != NULL){
			children[i]->flush();
		}
	}
}