Пример #1
0
void UserAgentDlg::changePressed()
{
    UAProviderDlg pdlg(i18n("Modify Identification"), this, m_provider);

    QListViewItem *index = dlg->lvDomainPolicyList->currentItem();

    if(!index)
        return;

    QString old_site = index->text(0);
    pdlg.setSiteName(old_site);
    pdlg.setIdentity(index->text(1));

    if(pdlg.exec() == QDialog::Accepted)
    {
        QString new_site = pdlg.siteName();
        if(new_site == old_site || !handleDuplicate(new_site, pdlg.identity(), pdlg.alias()))
        {
            index->setText(0, new_site);
            index->setText(1, pdlg.identity());
            index->setText(2, pdlg.alias());
            configChanged();
        }
    }
}
Пример #2
0
void LogWindow::sPrint()
{
  QPrinter printer;
  QPrintDialog pdlg(&printer, this);
  if (pdlg.exec() == QDialog::Accepted)
    _log->print(&printer);
}
Пример #3
0
void ManagementDialog::OnProp(wxCommandEvent& event)
{
	CMainFrame * courant = (CMainFrame *)GetParent();
	
	courant->num_triangle_courant = list->FindString(list->GetStringSelection());
	
	PropDialog pdlg(this, -1, wxT("Proprietes"));
	pdlg.id_triangle->ChangeValue(list->GetStringSelection());
	pdlg.ShowModal();
}
// Download the .pretty libraries found in aUrlLis and store them on disk
// in a master folder
bool WIZARD_FPLIB_TABLE::downloadGithubLibsFromList( wxArrayString& aUrlList,
        wxString* aErrorMessage )
{
    // Display a progress bar to show the downlaod state
    wxProgressDialog pdlg( _( "Downloading libraries" ), wxEmptyString, aUrlList.GetCount() );

    // Download libs:
    for( unsigned ii = 0; ii < aUrlList.GetCount(); ii++ )
    {
        wxString& libsrc_name = aUrlList[ii];
        wxString libdst_name;

        // Extract the lib name from the full URL:
        wxURI url( libsrc_name );
        wxFileName fn( url.GetPath() );
        // Set our local path
        fn.SetPath( getDownloadDir() );
        libdst_name = fn.GetFullPath();

        if( !wxDirExists( libdst_name ) )
            wxMkdir( libdst_name );

        pdlg.Update( ii, libsrc_name );
        pdlg.Refresh();
        pdlg.Update();

        try
        {
            PLUGIN::RELEASER src( IO_MGR::PluginFind( IO_MGR::GITHUB ) );
            PLUGIN::RELEASER dst( IO_MGR::PluginFind( IO_MGR::KICAD ) );

            wxArrayString footprints = src->FootprintEnumerate( libsrc_name );

            for( unsigned i = 0;  i < footprints.size();  ++i )
            {
                std::auto_ptr<MODULE> m( src->FootprintLoad( libsrc_name, footprints[i] ) );
                dst->FootprintSave( libdst_name, m.get() );
                // m is deleted here by auto_ptr.
            }
        }
        catch( const IO_ERROR& ioe )
        {
            if( aErrorMessage )
                aErrorMessage->Printf( _( "Error:\n'%s'\nwhile downloading library:\n'%s'" ),
                                       GetChars( ioe.errorText ), GetChars( libsrc_name ) );
            return false;
        }
    }

    return true;
}
Пример #5
0
void UserAgentDlg::addPressed()
{
    UAProviderDlg pdlg(i18n("Add Identification"), this, m_provider);

    if(pdlg.exec() == QDialog::Accepted)
    {
        if(!handleDuplicate(pdlg.siteName(), pdlg.identity(), pdlg.alias()))
        {
            QListViewItem *index = new QListViewItem(dlg->lvDomainPolicyList, pdlg.siteName(), pdlg.identity(), pdlg.alias());
            dlg->lvDomainPolicyList->sort();
            dlg->lvDomainPolicyList->setCurrentItem(index);
            configChanged();
        }
    }
}
Пример #6
0
void CPictureCatalogDialog::do_print()
{
	// Set our title so that the user will know what is being printed.
   m_pDoc->SetTitle(GET_PMWAPP()->GetResourceStringPointer (IDS_PICTURES));

	CPrintInfo pInfo;

	CPrintDialog *dlg_save = pInfo.m_pPD;

	CCatalogPrint pdlg(m_pDoc);

	pInfo.m_pPD = &pdlg;

	// Bring over the list.
	if (AfxGetApp()->DoPrintDialog(&pdlg) == IDOK)
	{
		// get all the filenames they selected
		POSITION pos = GetStartPosition();
		CStringArray files;
		while (pos != NULL)
		{
			CString file = GetNextPathName(pos);
			files.Add(file);
		}

		CString strDir = GetPathName();
		CCatalogView view(files, strDir);

		m_pDoc->m_bAutoDelete = FALSE;  // don't destroy document while closing views
		m_pDoc->size_to_paper();

		// Hook the view into the document.
		((CCatalogDoc *)m_pDoc)->add_hidden_view(&view);

		// Print the project.
		view.PrintProject(&pInfo);

		// Remove the view before its destructor happens.
		m_pDoc->RemoveView(&view);
	}

	pInfo.m_pPD = dlg_save;
}
// Download the .pretty libraries folders found in aUrlList and store them on disk
// in a master folder
bool WIZARD_3DSHAPE_LIBS_DOWNLOADER::downloadGithubLibsFromList( wxArrayString& aUrlList,
                                                     wxString* aErrorMessage )
{
    // Display a progress bar to show the download state
    // The title is updated for each downloaded library.
    // the state will be updated by downloadOneLib() for each file.
    wxProgressDialog pdlg( _( "Downloading 3D libraries" ), wxEmptyString,
                           aUrlList.GetCount(), GetParent(),
                           wxPD_CAN_ABORT | wxPD_APP_MODAL | wxPD_AUTO_HIDE );

    wxString url_base = GetGithubURL();

    // Download libs:
    for( unsigned ii = 0; ii < aUrlList.GetCount(); ii++ )
    {
        wxString& libsrc_name = aUrlList[ii];

        // Extract the lib name from the full URL:
        wxString url = GetGithubURL() + wxT( "/" ) + libsrc_name;
        wxFileName fn( libsrc_name );
        // Set our local path
        fn.SetPath( getDownloadDir() );
        wxString libdst_name = fn.GetFullPath();

        // Display the name of the library to download in the wxProgressDialog
        pdlg.SetTitle( wxString::Format( wxT("%s [%d/%d]" ),
                       libsrc_name.AfterLast( '/' ).GetData(),
                       ii + 1, aUrlList.GetCount() ) );

        if( !wxDirExists( libdst_name ) )
            wxMkdir( libdst_name );

        if( !downloadOneLib( url, libdst_name, &pdlg, aErrorMessage ) )
            return false;
    }

    return true;
}
Пример #8
0
int Unpack(wxFile& pkg_f, std::string src, std::string dst)
{
	PKGHeader* m_header = (PKGHeader*) malloc (sizeof(PKGHeader));

	wxFile dec_pkg_f;
	std::string decryptedFile = wxGetCwd() + "/dev_hdd1/" + src + ".dec";

	dec_pkg_f.Create(decryptedFile, true);
	
	if (Decrypt(pkg_f, dec_pkg_f, m_header) < 0)
		return -1;
	
	dec_pkg_f.Close();

	wxFile n_dec_pkg_f(decryptedFile, wxFile::read);

	std::vector<PKGEntry> m_entries;
	m_entries.resize(m_header->file_count);

	PKGEntry *m_entries_ptr = &m_entries[0];
	if (!LoadEntries(n_dec_pkg_f, m_header, m_entries_ptr))
		return -1;

	wxProgressDialog pdlg("PKG Decrypter / Installer", "Please wait, unpacking...", m_entries.size(), 0, wxPD_AUTO_HIDE | wxPD_APP_MODAL);

	for (const PKGEntry& entry : m_entries)
	{
		UnpackEntry(n_dec_pkg_f, entry, dst + src + "/");
		pdlg.Update(pdlg.GetValue() + 1);
	}
	pdlg.Update(m_entries.size());

	n_dec_pkg_f.Close();
	wxRemoveFile(decryptedFile);

	return 0;
}
Пример #9
0
CC_FILE_ERROR SoiFilter::loadFile(const char* filename, ccHObject& container, bool alwaysDisplayLoadDialog/*=true*/, bool* coordinatesShiftEnabled/*=0*/, double* coordinatesShift/*=0*/)
{
    //open the file
	FILE *fp = fopen(filename, "rt");
    if (!fp)
        return CC_FERR_READING;

	std::string line;
	line.resize(MAX_ASCII_FILE_LINE_LENGTH);
	unsigned nbScansTotal = 0;
	unsigned nbPointsTotal = 0;

	//we read the first line
	char* eof = fgets ((char*)line.c_str(), MAX_ASCII_FILE_LINE_LENGTH , fp);
    char* pEnd;

    //header
	while ((strcmp((char*)line.substr(0,4).c_str(),"#CC#") != 0)&&(eof != NULL))
	{
		if (strcmp(line.substr(0,4).c_str(),"#NP#")==0)
		{
			std::string numPoints (line,4,line.size()-4);
			nbPointsTotal=strtol(numPoints.c_str(),&pEnd,0);
			//ccConsole::Print("[SoiFilter::loadFile] Total number of points: %i\n",nbPointsTotal);
		}
		else if (strcmp(line.substr(0,4).c_str(),"#NS#")==0)
		{
			std::string numScans (line,4,line.size()-4);
			nbScansTotal=strtol(numScans.c_str(),&pEnd,0);
			//ccConsole::Print("[SoiFilter::loadFile] Total number of scans: %i\n",nbScansTotal);
		}

		eof = fgets ((char*)line.c_str(), MAX_ASCII_FILE_LINE_LENGTH , fp);
	}

	if ((nbScansTotal == 0)||(nbPointsTotal == 0))
	{
		ccConsole::Warning("[SoiFilter::loadFile] No points or scans defined in this file!");
		fclose(fp);
		return CC_FERR_NO_LOAD;
	}


	//Progress dialog
	ccProgressDialog pdlg(false); //cancel is not supported
	pdlg.setMethodTitle("Open SOI file");
	char buffer[256];
	sprintf(buffer,"%i scans / %i points\n",nbScansTotal,nbPointsTotal);
	CCLib::NormalizedProgress nprogress(&pdlg,nbPointsTotal);
	pdlg.setInfo(buffer);
	pdlg.start();

    //Scan by scan
	for (unsigned k=0;k<nbScansTotal;k++)
	{
		char* eof = fgets ((char*)line.c_str(), MAX_ASCII_FILE_LINE_LENGTH , fp);

        //we only look for points (we ignore the rest)
		while ((strcmp(line.substr(0,4).c_str(),"#pt#")!=0)&&(eof != NULL))
			eof = fgets ((char*)line.c_str(), MAX_ASCII_FILE_LINE_LENGTH , fp);

		unsigned nbOfPoints = 0;

		if (strcmp(line.substr(0,4).c_str(),"#pt#")==0)
		{
			std::string numPoints(line,4,line.size()-4);
			nbOfPoints=strtol(numPoints.c_str(),&pEnd,0);
			//ccConsole::Print("[SoiFilter::loadFile] Scan %i - points: %i\n",k+1,nbOfPoints);
		}
		else
		{
			ccConsole::Warning("[SoiFilter::loadFile] Can't find marker '#pt#'!\n");
			fclose(fp);
			return CC_FERR_WRONG_FILE_TYPE;
		}

		//Creation de la liste de points
		char name[64];
		sprintf(name,"unnamed - Scan #%i",k);
		ccPointCloud* loadedCloud = new ccPointCloud(name);

		if (!loadedCloud)
		{
            fclose(fp);
            return CC_FERR_NOT_ENOUGH_MEMORY;
		}

		if (nbOfPoints>0)
		{
            loadedCloud->reserveThePointsTable(nbOfPoints);
			loadedCloud->reserveTheRGBTable();
			loadedCloud->showColors(true);
		}
		else
		{
			ccConsole::Warning("[SoiFilter::loadFile] Scan #%i is empty!\n",k);
			continue;
		}

		CCVector3 P;
		int c = 0;

		//we can read points now
		for (unsigned i=0;i<nbOfPoints;i++)
		{
			fscanf(fp,"%f %f %f %i",&P.x,&P.y,&P.z,&c);

			loadedCloud->addPoint(P);
			loadedCloud->addGreyColor(colorType(c<<3)); //<<2 ? <<3 ? we lack some info. here ...

			nprogress.oneStep();
		}

		container.addChild(loadedCloud);
	}

	fclose(fp);

    return CC_FERR_NO_ERROR;
}
Пример #10
0
void MainFrame::InstallPkg(wxCommandEvent& WXUNUSED(event))
{
	const bool paused = Emu.Pause();

	wxFileDialog ctrl(this, L"Select PKG", wxEmptyString, wxEmptyString, "PKG files (*.pkg)|*.pkg|All files (*.*)|*.*", wxFD_OPEN | wxFD_FILE_MUST_EXIST);
	
	if (ctrl.ShowModal() == wxID_CANCEL)
	{
		if (paused) Emu.Resume();
		return;
	}

	Emu.Stop();

	// Open PKG file
	fs::file pkg_f(ctrl.GetPath().ToStdString());

	if (!pkg_f || pkg_f.size() < 64)
	{
		LOG_ERROR(LOADER, "PKG: Failed to open %s", ctrl.GetPath().ToStdString());
		return;
	}

	// Get title ID
	std::vector<char> title_id(9);
	pkg_f.seek(55);
	pkg_f.read(title_id);
	pkg_f.seek(0);

	// Get full path
	const auto& local_path = Emu.GetGameDir() + std::string(std::begin(title_id), std::end(title_id));

	if (!fs::create_dir(local_path))
	{
		if (fs::is_dir(local_path))
		{
			if (wxMessageDialog(this, "Another installation found. Do you want to overwrite it?", "PKG Decrypter / Installer", wxYES_NO | wxCENTRE).ShowModal() != wxID_YES)
			{
				LOG_ERROR(LOADER, "PKG: Cancelled installation to existing directory %s", local_path);
				return;
			}
		}
		else
		{
			LOG_ERROR(LOADER, "PKG: Could not create the installation directory %s", local_path);
			return;
		}
	}

	wxProgressDialog pdlg("PKG Installer", "Please wait, unpacking...", 1000, this, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);

	// Synchronization variable
	atomic_t<double> progress(0.);
	{
		// Run PKG unpacking asynchronously
		scope_thread worker("PKG Installer", [&]
		{
			if (pkg_install(pkg_f, local_path + '/', progress))
			{
				progress = 1.;
				return_;
			}

			// TODO: Ask user to delete files on cancellation/failure?
			progress = -1.;
		});

		// Wait for the completion
		while (std::this_thread::sleep_for(5ms), std::abs(progress) < 1.)
		{
			// Update progress window
			if (!pdlg.Update(static_cast<int>(progress * pdlg.GetRange())))
			{
				// Installation cancelled (signal with negative value)
				progress -= 1.;
				break;
			}
		}
		
		if (progress > 0.)
		{
			pdlg.Update(pdlg.GetRange());
			std::this_thread::sleep_for(100ms);
		}
	}

	pdlg.Close();

	if (progress >= 1.)
	{
		// Refresh game list
		m_game_viewer->Refresh();
	}
}
Пример #11
0
CC_FILE_ERROR LASFilter::loadFile(const char* filename, ccHObject& container, bool alwaysDisplayLoadDialog/*=true*/, bool* coordinatesShiftEnabled/*=0*/, double* coordinatesShift/*=0*/)
{
	//opening file
	std::ifstream ifs;
	ifs.open(filename, std::ios::in | std::ios::binary);

	if (ifs.fail())
		return CC_FERR_READING;

	liblas::Reader* reader = 0;
	unsigned nbOfPoints = 0;
	std::vector<std::string> dimensions;

	try
	{
		reader = new liblas::Reader(liblas::ReaderFactory().CreateWithStream(ifs));	//using factory for automatic and transparent
		//handling of compressed/uncompressed files
		liblas::Header const& header = reader->GetHeader();

#ifdef _DEBUG
		//ccConsole::Print("[LAS FILE] %s - signature: %s",filename,header.GetFileSignature().c_str());
#endif

		//get fields present in file
		dimensions = header.GetSchema().GetDimensionNames();

		//and of course the number of points
		nbOfPoints = header.GetPointRecordsCount();
	}
	catch (...)
	{
		delete reader;
		ifs.close();
		return CC_FERR_READING;
	}

	if (nbOfPoints==0)
	{
		//strange file ;)
		delete reader;
		ifs.close();
		return CC_FERR_NO_LOAD;
	}

	liblas::Color rgbColorMask; //(0,0,0) on construction
	bool hasClassif = false;
	bool hasIntensity = false;
	bool hasTime = false;
	bool hasReturnNumber = false;
	for (unsigned k=0;k<dimensions.size();++k)
	{
		QString dim = QString(dimensions[k].c_str()).toUpper();
		bool handled = true;
		if (dim == "RED")
			rgbColorMask.SetRed(~0);
		else if (dim == "BLUE")
			rgbColorMask.SetBlue(~0);
		else if (dim == "GREEN")
			rgbColorMask.SetGreen(~0);
		else if (dim == "CLASSIFICATION")
			hasClassif = true;
		else if (dim == "TIME")
			hasTime = true;
		else if (dim == "INTENSITY")
			hasIntensity = true;
		else if (dim == "RETURN NUMBER")
			hasReturnNumber = true;
		else if (dim != "X" && dim != "Y" && dim != "Z")
			handled = false;

		ccConsole::Print(QString("[LAS FILE] Found dimension '%1' (%2)").arg(dimensions[k].c_str()).arg(handled ? "handled" : "not handled"));
	}
	bool hasColor = (rgbColorMask[0] || rgbColorMask[1] || rgbColorMask[2]);

	//progress dialog
	ccProgressDialog pdlg(true); //cancel available
	CCLib::NormalizedProgress nprogress(&pdlg,nbOfPoints);
	pdlg.setMethodTitle("Open LAS file");
	pdlg.setInfo(qPrintable(QString("Points: %1").arg(nbOfPoints)));
	pdlg.start();

	//number of points read from the begining of the current cloud part
	unsigned pointsRead = 0;
	double Pshift[3] = {0.0,0.0,0.0};

	//by default we read color as 8 bits integers and we will change this to 16 bits if it's not (16 bits is the standard!)
	unsigned char colorCompBitDec = 0;
	colorType rgb[3] = {0,0,0};

	ccPointCloud* loadedCloud = 0;

	ccScalarField* classifSF = 0;
	uint8_t firstClassifValue = 0;

	ccScalarField* timeSF = 0;
	double firstTime = 0.0;

	ccScalarField* intensitySF = 0;
	uint16_t firstIntensity = 0;

	ccScalarField* returnNumberSF = 0;
	uint16_t firstReturnNumber = 0;

	//if the file is too big, we will chunck it in multiple parts
	unsigned int fileChunkPos = 0;
	unsigned int fileChunkSize = 0;

	while (true)
	{
		//if we reach the end of the file, or the max. cloud size limit (in which case we cerate a new chunk)
		bool newPointAvailable = (nprogress.oneStep() && reader->ReadNextPoint());

		if (!newPointAvailable || pointsRead == fileChunkPos+fileChunkSize)
		{
			if (loadedCloud)
			{
				if (loadedCloud->size())
				{
					bool thisChunkHasColors = loadedCloud->hasColors();
					loadedCloud->showColors(thisChunkHasColors);
					if (hasColor && !thisChunkHasColors)
						ccLog::Warning("[LAS FILE] Color field was all black! We ignored it...");

					if (hasClassif)
					{
						if (classifSF)
						{
							classifSF->computeMinAndMax();
							int cMin = (int)classifSF->getMin();
							int cMax = (int)classifSF->getMax();
							classifSF->setColorRampSteps(cMax-cMin);
							//classifSF->setMinSaturation(cMin);
							int sfIndex = loadedCloud->addScalarField(classifSF);
							if (!loadedCloud->hasDisplayedScalarField())
							{
								loadedCloud->setCurrentDisplayedScalarField(sfIndex);
								loadedCloud->showSF(!thisChunkHasColors);
							}
						}
						else
						{
							ccLog::Warning(QString("[LAS FILE] All classification values were the same (%1)! We ignored them...").arg(firstClassifValue));
						}
					}

					if (hasIntensity)
					{
						if (intensitySF)
						{
							intensitySF->computeMinAndMax();
							intensitySF->setColorScale(ccColorScalesManager::GetDefaultScale(ccColorScalesManager::GREY));
							int sfIndex = loadedCloud->addScalarField(intensitySF);
							if (!loadedCloud->hasDisplayedScalarField())
							{
								loadedCloud->setCurrentDisplayedScalarField(sfIndex);
								loadedCloud->showSF(!thisChunkHasColors);
							}
						}
						else
						{
							ccLog::Warning(QString("[LAS FILE] All intensities were the same (%1)! We ignored them...").arg(firstIntensity));
						}
					}

					if (hasTime)
					{
						if (timeSF)
						{
							timeSF->computeMinAndMax();
							int sfIndex = loadedCloud->addScalarField(timeSF);
							if (!loadedCloud->hasDisplayedScalarField())
							{
								loadedCloud->setCurrentDisplayedScalarField(sfIndex);
								loadedCloud->showSF(!thisChunkHasColors);
							}
						}
						else
						{
							ccLog::Warning(QString("[LAS FILE] All timestamps were the same (%1)! We ignored them...").arg(firstTime));
						}
					}

					if (hasReturnNumber)
					{
						if (returnNumberSF)
						{
							returnNumberSF->computeMinAndMax();
							int rMin = (int)returnNumberSF->getMin();
							int rMax = (int)returnNumberSF->getMax();
							returnNumberSF->setColorRampSteps(rMax-rMin);
							int sfIndex = loadedCloud->addScalarField(returnNumberSF);
							if (!loadedCloud->hasDisplayedScalarField())
							{
								loadedCloud->setCurrentDisplayedScalarField(sfIndex);
								loadedCloud->showSF(!thisChunkHasColors);
							}
						}
						else
						{
							ccLog::Warning(QString("[LAS FILE] All return numbers were the same (%1)! We ignored them...").arg(firstReturnNumber));
						}
					}

					//if we have reserved too much memory
					if (loadedCloud->size() < loadedCloud->capacity())
						loadedCloud->resize(loadedCloud->size());

					QString chunkName("unnamed - Cloud");
					unsigned n = container.getChildrenNumber();
					if (n!=0) //if we have more than one cloud, we append an index
					{
						if (n==1)  //we must also update the first one!
							container.getChild(0)->setName(chunkName+QString(" #1"));
						chunkName += QString(" #%1").arg(n+1);
					}
					loadedCloud->setName(chunkName);

					container.addChild(loadedCloud);
					loadedCloud=0;
				}
				else
				{
					//empty cloud?!
					delete loadedCloud;
					loadedCloud=0;
				}

				if (classifSF)
					classifSF->release();
				classifSF=0;
				if (intensitySF)
					intensitySF->release();
				intensitySF=0;
				if (returnNumberSF)
					returnNumberSF->release();
				returnNumberSF=0;
				if (timeSF)
					timeSF->release();
				timeSF=0;
			}

			if (!newPointAvailable)
				break; //end of the file (or cancel requested)

			//otherwise, we must create a new cloud
			fileChunkPos = pointsRead;
			fileChunkSize = std::min(nbOfPoints-pointsRead,CC_MAX_NUMBER_OF_POINTS_PER_CLOUD);
			loadedCloud = new ccPointCloud();
			if (!loadedCloud->reserveThePointsTable(fileChunkSize))
			{
				ccLog::Warning("[LASFilter::loadFile] Not enough memory!");
				delete loadedCloud;
				delete reader;
				ifs.close();
				return CC_FERR_NOT_ENOUGH_MEMORY;
			}
			loadedCloud->setOriginalShift(Pshift[0],Pshift[1],Pshift[2]);

			//DGM: from now on, we only enable scalar fields when we detect a valid value!
			if (hasClassif)
			{
				assert(!classifSF);
				firstClassifValue = 0;
			}

			if (hasTime)
			{
				assert(!timeSF);
				firstTime = 0.0;
			}

			if (hasIntensity)
			{
				assert(!intensitySF);
				firstIntensity=0;
			}

			if (hasReturnNumber)
			{
				assert(!returnNumberSF);
				firstReturnNumber = 0;
			}
		}

		assert(newPointAvailable);
		const liblas::Point& p = reader->GetPoint();

		//first point: check for 'big' coordinates
		if (pointsRead==0)
		{
			double P[3]={p.GetX(),p.GetY(),p.GetZ()};
			bool shiftAlreadyEnabled = (coordinatesShiftEnabled && *coordinatesShiftEnabled && coordinatesShift);
			if (shiftAlreadyEnabled)
				memcpy(Pshift,coordinatesShift,sizeof(double)*3);
			bool applyAll=false;
			if (ccCoordinatesShiftManager::Handle(P,0,alwaysDisplayLoadDialog,shiftAlreadyEnabled,Pshift,0,applyAll))
			{
				loadedCloud->setOriginalShift(Pshift[0],Pshift[1],Pshift[2]);
				ccConsole::Warning("[LASFilter::loadFile] Cloud has been recentered! Translation: (%.2f,%.2f,%.2f)",Pshift[0],Pshift[1],Pshift[2]);

				//we save coordinates shift information
				if (applyAll && coordinatesShiftEnabled && coordinatesShift)
				{
					*coordinatesShiftEnabled = true;
					coordinatesShift[0] = Pshift[0];
					coordinatesShift[1] = Pshift[1];
					coordinatesShift[2] = Pshift[2];
				}
			}
		}

		CCVector3 P(p.GetX()+Pshift[0],p.GetY()+Pshift[1],p.GetZ()+Pshift[2]);
		loadedCloud->addPoint(P);

		//color field
		if (hasColor)
		{
			//Warning: LAS colors are stored on 16 bits!
			liblas::Color col = p.GetColor();
			col[0] &= rgbColorMask[0];
			col[1] &= rgbColorMask[1];
			col[2] &= rgbColorMask[2];

			//if we don't have reserved a color field yet, we check first that color is not black
			bool pushColor = true;
			if (!loadedCloud->hasColors())
			{
				//if the color is not black, we are sure it's a valid color field!
				if (col[0] || col[1] || col[2])
				{
					if (loadedCloud->reserveTheRGBTable())
					{
						//we must set the color (black) of all the precedently skipped points
						for (unsigned i=0;i<loadedCloud->size()-1;++i)
							loadedCloud->addRGBColor(ccColor::black);
					}
					else
					{
						ccConsole::Warning("[LAS FILE] Not enough memory: color field will be ignored!");
						hasColor = false; //no need to retry with the other chunks anyway
						pushColor = false;
					}
				}
				else //otherwise we ignore it for the moment (we'll add it later if necessary)
				{
					pushColor = false;
				}
			}

			//do we need to push this color?
			if (pushColor)
			{
				//we test if the color components are on 16 bits (standard) or only on 8 bits (it happens ;)
				if (colorCompBitDec==0)
				{
					if (	(col[0] & 0xFF00)
						||  (col[1] & 0xFF00)
						||  (col[2] & 0xFF00))
					{
						//the color components are on 16 bits!
						ccLog::Print("[LAS FILE] Color components are coded on 16 bits");
						colorCompBitDec = 8;
						//we fix all the precedently read colors
						for (unsigned i=0;i<loadedCloud->size()-1;++i)
							loadedCloud->setPointColor(i,ccColor::black); //255 >> 8 = 0!
					}
				}

				rgb[0]=(colorType)(col[0]>>colorCompBitDec);
				rgb[1]=(colorType)(col[1]>>colorCompBitDec);
				rgb[2]=(colorType)(col[2]>>colorCompBitDec);

				loadedCloud->addRGBColor(rgb);
			}
		}

		if (hasClassif)
		{
			uint8_t intValue = p.GetClassification().GetClass();
			if (classifSF)
			{
				classifSF->addElement(intValue);
			}
			else
			{
				//first point? we track its value
				if (loadedCloud->size()==1)
				{
					firstClassifValue = intValue;
				}
				
				if (intValue != firstClassifValue || firstClassifValue > 1) //0 = Created, never classified, 1 = Unclassified
				{
					classifSF = new ccScalarField(CC_LAS_CLASSIFICATION_FIELD_NAME);
					if (classifSF->reserve(fileChunkSize))
					{
						classifSF->link();
						//we must set the classification value (firstClassifValue) of all the precedently skipped points
						for (unsigned i=0;i<loadedCloud->size()-1;++i)
							classifSF->addElement(firstClassifValue);
						classifSF->addElement(intValue);
					}
					else
					{
						ccConsole::Warning("[LAS FILE] Not enough memory: classificaiton field will be ignored!");
						hasClassif = false; //no need to retry with the other chunks anyway
						classifSF->release();
						classifSF=0;
					}
				}
			}
		}

		if (hasTime)
		{
			double timeValue = p.GetTime();

			if (timeSF)
			{
				timeSF->addElement(timeValue);
			}
			else
			{
				//first point? we track its value
				if (loadedCloud->size()==1)
				{
					firstTime = timeValue;
				}
				else if (timeValue != firstTime)
				{
					timeSF = new ccScalarField(CC_SCAN_TIME_FIELD_NAME);
					if (timeSF->reserve(fileChunkSize))
					{
						timeSF->link();
						//we must set the timestamp value (firstTime) of all the precedently skipped points
						for (unsigned i=0;i<loadedCloud->size()-1;++i)
							timeSF->addElement(firstTime);
						timeSF->addElement(timeValue);
					}
					else
					{
						ccConsole::Warning("[LAS FILE] Not enough memory: 'time' field will be ignored!");
						hasTime = false; //no need to retry with the other chunks anyway
						timeSF->release();
						timeSF=0;
					}
				}
			}
		}

		if (hasIntensity)
		{
			uint16_t intValue = p.GetIntensity();
			if (intensitySF)
			{
				intensitySF->addElement(intValue);
			}
			else
			{
				//first point? we track its value
				if (loadedCloud->size()==1)
				{
					firstIntensity = intValue;
				}
				
				if (intValue != firstIntensity || (firstIntensity != 0 && firstIntensity != 65535))
				{
					intensitySF = new ccScalarField(CC_SCAN_INTENSITY_FIELD_NAME);
					if (intensitySF->reserve(fileChunkSize))
					{
						intensitySF->link();
						//we must set the intensity (firstIntensity) of all the precedently skipped points
						for (unsigned i=0;i<loadedCloud->size()-1;++i)
							intensitySF->addElement(firstIntensity);
						intensitySF->addElement(intValue);
					}
					else
					{
						ccConsole::Warning("[LAS FILE] Not enough memory: intensity field will be ignored!");
						hasIntensity = false; //no need to retry with the other chunks anyway
						intensitySF->release();
						intensitySF=0;
					}
				}
			}
		}

		if (hasReturnNumber)
		{
			uint16_t intValue = p.GetReturnNumber();
			if (returnNumberSF)
			{
				returnNumberSF->addElement(intValue);
			}
			else
			{
				//first point? we track its value
				if (loadedCloud->size()==1)
				{
					firstReturnNumber = intValue;
				}
				
				if (intValue != firstReturnNumber)
				{
					returnNumberSF = new ccScalarField(CC_SCAN_RETURN_INDEX_FIELD_NAME);
					if (returnNumberSF->reserve(fileChunkSize))
					{
						returnNumberSF->link();
						//we must set the return index (firstReturnNumber) of all the precedently skipped points
						for (unsigned i=0;i<loadedCloud->size()-1;++i)
							returnNumberSF->addElement(firstReturnNumber);
						returnNumberSF->addElement(intValue);
					}
					else
					{
						ccConsole::Warning("[LAS FILE] Not enough memory: return number field will be ignored!");
						hasReturnNumber = false; //no need to retry with the other chunks anyway
						returnNumberSF->release();
						returnNumberSF=0;
					}
				}
			}

		}

		++pointsRead;
	}

	if (reader)
		delete reader;
	reader=0;
	ifs.close();

	return CC_FERR_NO_ERROR;
}
Пример #12
0
CC_FILE_ERROR AsciiFilter::loadCloudFromFormatedAsciiFile(	const QString& filename,
															ccHObject& container,
															const AsciiOpenDlg::Sequence& openSequence,
															char separator,
															unsigned approximateNumberOfLines,
															qint64 fileSize,
															unsigned maxCloudSize,
															unsigned skipLines,
															LoadParameters& parameters)
{
	//we may have to "slice" clouds when opening them if they are too big!
	maxCloudSize = std::min(maxCloudSize,CC_MAX_NUMBER_OF_POINTS_PER_CLOUD);
	unsigned cloudChunkSize = std::min(maxCloudSize,approximateNumberOfLines);
	unsigned cloudChunkPos = 0;
	unsigned chunkRank = 1;

	//we initialize the loading accelerator structure and point cloud
	int maxPartIndex = -1;
	cloudAttributesDescriptor cloudDesc = prepareCloud(openSequence, cloudChunkSize, maxPartIndex, separator, chunkRank);

	if (!cloudDesc.cloud)
		return CC_FERR_NOT_ENOUGH_MEMORY;

	//we re-open the file (ASCII mode)
	QFile file(filename);
	if (!file.open(QFile::ReadOnly))
	{
		//we clear already initialized data
		clearStructure(cloudDesc);
		return CC_FERR_READING;
	}
	QTextStream stream(&file);

	//we skip lines as defined on input
	{
		for (unsigned i=0; i<skipLines; ++i)
		{
			stream.readLine();
		}
	}

	//progress indicator
	ccProgressDialog pdlg(true);
	CCLib::NormalizedProgress nprogress(&pdlg,approximateNumberOfLines);
	pdlg.setMethodTitle(qPrintable(QString("Open ASCII file [%1]").arg(filename)));
	pdlg.setInfo(qPrintable(QString("Approximate number of points: %1").arg(approximateNumberOfLines)));
	pdlg.start();

	//buffers
	ScalarType D = 0;
	CCVector3d P(0,0,0);
	CCVector3d Pshift(0,0,0);
	CCVector3 N(0,0,0);
	ccColor::Rgb col;

	//other useful variables
	unsigned linesRead = 0;
	unsigned pointsRead = 0;

	CC_FILE_ERROR result = CC_FERR_NO_ERROR;

	//main process
	unsigned nextLimit = /*cloudChunkPos+*/cloudChunkSize;
	QString currentLine = stream.readLine();
	while (!currentLine.isNull())
	{
		++linesRead;

		//comment
		if (currentLine.startsWith("//"))
		{
			currentLine = stream.readLine();
			continue;
		}

		if (currentLine.size() == 0)
		{
			ccLog::Warning("[AsciiFilter::Load] Line %i is corrupted (empty)!",linesRead);
			currentLine = stream.readLine();
			continue;
		}

		//if we have reached the max. number of points per cloud
		if (pointsRead == nextLimit)
		{
			ccLog::PrintDebug("[ASCII] Point %i -> end of chunk (%i points)",pointsRead,cloudChunkSize);

			//we re-evaluate the average line size
			{
				double averageLineSize = static_cast<double>(file.pos())/(pointsRead+skipLines);
				double newNbOfLinesApproximation = std::max(1.0, static_cast<double>(fileSize)/averageLineSize - static_cast<double>(skipLines));

				//if approximation is smaller than actual one, we add 2% by default
				if (newNbOfLinesApproximation <= pointsRead)
				{
					newNbOfLinesApproximation = std::max(static_cast<double>(cloudChunkPos+cloudChunkSize)+1.0,static_cast<double>(pointsRead) * 1.02);
				}
				approximateNumberOfLines = static_cast<unsigned>(ceil(newNbOfLinesApproximation));
				ccLog::PrintDebug("[ASCII] New approximate nb of lines: %i",approximateNumberOfLines);
			}

			//we try to resize actual clouds
			if (cloudChunkSize < maxCloudSize || approximateNumberOfLines-cloudChunkPos <= maxCloudSize)
			{
				ccLog::PrintDebug("[ASCII] We choose to enlarge existing clouds");

				cloudChunkSize = std::min(maxCloudSize,approximateNumberOfLines-cloudChunkPos);
				if (!cloudDesc.cloud->reserve(cloudChunkSize))
				{
					ccLog::Error("Not enough memory! Process stopped ...");
					result = CC_FERR_NOT_ENOUGH_MEMORY;
					break;
				}
			}
			else //otherwise we have to create new clouds
			{
				ccLog::PrintDebug("[ASCII] We choose to instantiate new clouds");

				//we store (and resize) actual cloud
				if (!cloudDesc.cloud->resize(cloudChunkSize))
					ccLog::Warning("Memory reallocation failed ... some memory may have been wasted ...");
				if (!cloudDesc.scalarFields.empty())
				{
					for (unsigned k=0; k<cloudDesc.scalarFields.size(); ++k)
						cloudDesc.scalarFields[k]->computeMinAndMax();
					cloudDesc.cloud->setCurrentDisplayedScalarField(0);
					cloudDesc.cloud->showSF(true);
				}
				//we add this cloud to the output container
				container.addChild(cloudDesc.cloud);
				cloudDesc.reset();

				//and create new one
				cloudChunkPos = pointsRead;
				cloudChunkSize = std::min(maxCloudSize,approximateNumberOfLines-cloudChunkPos);
				cloudDesc = prepareCloud(openSequence, cloudChunkSize, maxPartIndex, separator, ++chunkRank);
				if (!cloudDesc.cloud)
				{
					ccLog::Error("Not enough memory! Process stopped ...");
					break;
				}
				cloudDesc.cloud->setGlobalShift(Pshift);
			}

			//we update the progress info
			nprogress.scale(approximateNumberOfLines,100,true);
			pdlg.setInfo(qPrintable(QString("Approximate number of points: %1").arg(approximateNumberOfLines)));

			nextLimit = cloudChunkPos+cloudChunkSize;
		}

		//we split current line
		QStringList parts = currentLine.split(separator,QString::SkipEmptyParts);

		int nParts = parts.size();
		if (nParts > maxPartIndex)
		{
			//(X,Y,Z)
			if (cloudDesc.xCoordIndex >= 0)
				P.x = parts[cloudDesc.xCoordIndex].toDouble();
			if (cloudDesc.yCoordIndex >= 0)
				P.y = parts[cloudDesc.yCoordIndex].toDouble();
			if (cloudDesc.zCoordIndex >= 0)
				P.z = parts[cloudDesc.zCoordIndex].toDouble();

			//first point: check for 'big' coordinates
			if (pointsRead == 0)
			{
				if (HandleGlobalShift(P,Pshift,parameters))
				{
					cloudDesc.cloud->setGlobalShift(Pshift);
					ccLog::Warning("[ASCIIFilter::loadFile] Cloud has been recentered! Translation: (%.2f,%.2f,%.2f)",Pshift.x,Pshift.y,Pshift.z);
				}
			}

			//add point
			cloudDesc.cloud->addPoint(CCVector3::fromArray((P+Pshift).u));

			//Normal vector
			if (cloudDesc.hasNorms)
			{
				if (cloudDesc.xNormIndex >= 0)
					N.x = static_cast<PointCoordinateType>(parts[cloudDesc.xNormIndex].toDouble());
				if (cloudDesc.yNormIndex >= 0)
					N.y = static_cast<PointCoordinateType>(parts[cloudDesc.yNormIndex].toDouble());
				if (cloudDesc.zNormIndex >= 0)
					N.z = static_cast<PointCoordinateType>(parts[cloudDesc.zNormIndex].toDouble());
				cloudDesc.cloud->addNorm(N);
			}

			//Colors
			if (cloudDesc.hasRGBColors)
			{
				if (cloudDesc.iRgbaIndex >= 0)
				{
					const uint32_t rgb = parts[cloudDesc.iRgbaIndex].toInt();
					col.r = ((rgb >> 16) & 0x0000ff);
					col.g = ((rgb >> 8 ) & 0x0000ff);
					col.b = ((rgb      ) & 0x0000ff);

				}
				else if (cloudDesc.fRgbaIndex >= 0)
				{
					const float rgbf = parts[cloudDesc.fRgbaIndex].toFloat();
					const uint32_t rgb = (uint32_t)(*((uint32_t*)&rgbf));
					col.r = ((rgb >> 16) & 0x0000ff);
					col.g = ((rgb >> 8 ) & 0x0000ff);
					col.b = ((rgb      ) & 0x0000ff);
				}
				else
				{
					if (cloudDesc.redIndex >= 0)
					{
						float multiplier = cloudDesc.hasFloatRGBColors[0] ? static_cast<float>(ccColor::MAX) : 1.0f;
						col.r = static_cast<ColorCompType>(parts[cloudDesc.redIndex].toFloat() * multiplier);
					}
					if (cloudDesc.greenIndex >= 0)
					{
						float multiplier = cloudDesc.hasFloatRGBColors[1] ? static_cast<float>(ccColor::MAX) : 1.0f;
						col.g = static_cast<ColorCompType>(parts[cloudDesc.greenIndex].toFloat() * multiplier);
					}
					if (cloudDesc.blueIndex >= 0)
					{
						float multiplier = cloudDesc.hasFloatRGBColors[2] ? static_cast<float>(ccColor::MAX) : 1.0f;
						col.b = static_cast<ColorCompType>(parts[cloudDesc.blueIndex].toFloat() * multiplier);
					}
				}
				cloudDesc.cloud->addRGBColor(col.rgb);
			}
			else if (cloudDesc.greyIndex >= 0)
Пример #13
0
CC_FILE_ERROR LASFilter::saveToFile(ccHObject* entity, const char* filename)
{
	if (!entity || !filename)
		return CC_FERR_BAD_ARGUMENT;

	ccHObject::Container clouds;
	if (entity->isKindOf(CC_POINT_CLOUD))
		clouds.push_back(entity);
	else
		entity->filterChildren(clouds, true, CC_POINT_CLOUD);

	if (clouds.empty())
	{
		ccLog::Error("No point cloud in input selection!");
		return CC_FERR_BAD_ENTITY_TYPE;
	}
	else if (clouds.size()>1)
	{
		ccLog::Error("Can't save more than one cloud per LAS file!");
		return CC_FERR_BAD_ENTITY_TYPE;
	}

	//the cloud to save
	ccGenericPointCloud* theCloud = ccHObjectCaster::ToGenericPointCloud(clouds[0]);
	unsigned numberOfPoints = theCloud->size();

	if (numberOfPoints==0)
	{
		ccLog::Error("Cloud is empty!");
		return CC_FERR_BAD_ENTITY_TYPE;
	}

	//colors
	bool hasColor = theCloud->hasColors();

	//additional fields (as scalar fields)
	std::vector<LasField> fieldsToSave;

	if (theCloud->isA(CC_POINT_CLOUD))
	{
		ccPointCloud* pc = static_cast<ccPointCloud*>(theCloud);

		//Match cloud SFs with official LAS fields
		{
			//official LAS fields
			std::vector<LasField> lasFields;
			{
				lasFields.push_back(LasField(LAS_CLASSIFICATION,0,0,255)); //unsigned char: between 0 and 255
				lasFields.push_back(LasField(LAS_CLASSIF_VALUE,0,0,31)); //5 bits: between 0 and 31
				lasFields.push_back(LasField(LAS_CLASSIF_SYNTHETIC,0,0,1)); //1 bit: 0 or 1
				lasFields.push_back(LasField(LAS_CLASSIF_KEYPOINT,0,0,1)); //1 bit: 0 or 1
				lasFields.push_back(LasField(LAS_CLASSIF_WITHHELD,0,0,1)); //1 bit: 0 or 1
				lasFields.push_back(LasField(LAS_INTENSITY,0,0,65535)); //16 bits: between 0 and 65536
				lasFields.push_back(LasField(LAS_TIME,0,0,-1.0)); //8 bytes (double)
				lasFields.push_back(LasField(LAS_RETURN_NUMBER,1,1,7)); //3 bits: between 1 and 7
				lasFields.push_back(LasField(LAS_NUMBER_OF_RETURNS,1,1,7)); //3 bits: between 1 and 7
				lasFields.push_back(LasField(LAS_SCAN_DIRECTION,0,0,1)); //1 bit: 0 or 1
				lasFields.push_back(LasField(LAS_FLIGHT_LINE_EDGE,0,0,1)); //1 bit: 0 or 1
				lasFields.push_back(LasField(LAS_SCAN_ANGLE_RANK,0,-90,90)); //signed char: between -90 and +90
				lasFields.push_back(LasField(LAS_USER_DATA,0,0,255)); //unsigned char: between 0 and 255
				lasFields.push_back(LasField(LAS_POINT_SOURCE_ID,0,0,65535)); //16 bits: between 0 and 65536
			}

			//we are going to check now the existing cloud SFs
			for (unsigned i=0; i<pc->getNumberOfScalarFields(); ++i)
			{
				ccScalarField* sf = static_cast<ccScalarField*>(pc->getScalarField(i));
				//find an equivalent in official LAS fields
				QString sfName = QString(sf->getName()).toUpper();
				bool outBounds = false;
				for (size_t j=0; j<lasFields.size(); ++j)
				{
					//if the name matches
					if (sfName == QString(lasFields[j].getName()).toUpper())
					{
						//check bounds
						if (sf->getMin() < lasFields[j].minValue || (lasFields[j].maxValue != -1.0 && sf->getMax() > lasFields[j].maxValue)) //outbounds?
						{
							ccLog::Warning(QString("[LASFilter] Found a '%1' scalar field, but its values outbound LAS specifications (%2-%3)...").arg(sf->getName()).arg(lasFields[j].minValue).arg(lasFields[j].maxValue));
							outBounds = true;
						}
						else
						{
							//we add the SF to the list of saved fields
							fieldsToSave.push_back(lasFields[j]);
							fieldsToSave.back().sf = sf;
						}
						break;
					}
				}
				
				//no correspondance was found?
				if (!outBounds && (fieldsToSave.empty() || fieldsToSave.back().sf != sf))
				{
					ccLog::Warning(QString("[LASFilter] Found a '%1' scalar field, but it doesn't match with any of the official LAS fields... we will ignore it!").arg(sf->getName()));
				}
			}
		}
	}

	//open binary file for writing
	std::ofstream ofs;
	ofs.open(filename, std::ios::out | std::ios::binary);

	if (ofs.fail())
		return CC_FERR_WRITING;

	liblas::Writer* writer = 0;
	try
	{
		liblas::Header header;

		//LAZ support based on extension!
		if (QFileInfo(filename).suffix().toUpper() == "LAZ")
		{
			header.SetCompressed(true);
		}

		//header.SetDataFormatId(liblas::ePointFormat3);
		ccBBox bBox = theCloud->getBB();
		if (bBox.isValid())
		{
			CCVector3d bbMin = theCloud->toGlobal3d<PointCoordinateType>(bBox.minCorner());
			CCVector3d bbMax = theCloud->toGlobal3d<PointCoordinateType>(bBox.maxCorner());
			
			header.SetMin(	bbMin.x, bbMin.y, bbMin.z );
			header.SetMax(	bbMax.x, bbMax.y, bbMax.z );
			CCVector3 diag = bBox.getDiagVec();

			//Set offset & scale, as points will be stored as boost::int32_t values (between 0 and 4294967296)
			//int_value = (double_value-offset)/scale
			header.SetOffset(	bbMin.x, bbMin.y, bbMin.z );
			
			header.SetScale(1.0e-9 * std::max<double>(diag.x,ZERO_TOLERANCE), //result must fit in 32bits?!
							1.0e-9 * std::max<double>(diag.y,ZERO_TOLERANCE),
							1.0e-9 * std::max<double>(diag.z,ZERO_TOLERANCE));
		}
		header.SetPointRecordsCount(numberOfPoints);

		//DGM FIXME: doesn't seem to do anything;)
		//if (!hasColor) //we must remove the colors dimensions!
		//{
		//	liblas::Schema schema = header.GetSchema();
		//	boost::optional< liblas::Dimension const& > redDim = schema.GetDimension("Red");
		//	if (redDim)
		//		schema.RemoveDimension(redDim.get());
		//	boost::optional< liblas::Dimension const& > greenDim = schema.GetDimension("Green");
		//	if (greenDim)
		//		schema.RemoveDimension(greenDim.get());
		//	boost::optional< liblas::Dimension const& > blueDim = schema.GetDimension("Blue");
		//	if (blueDim)
		//		schema.RemoveDimension(blueDim.get());
		//	header.SetSchema(schema);
		//}
		//header.SetDataFormatId(Header::ePointFormat1);

		writer = new liblas::Writer(ofs, header);
	}
	catch (...)
	{
		return CC_FERR_WRITING;
	}

	//progress dialog
	ccProgressDialog pdlg(true); //cancel available
	CCLib::NormalizedProgress nprogress(&pdlg,numberOfPoints);
	pdlg.setMethodTitle("Save LAS file");
	char buffer[256];
	sprintf(buffer,"Points: %u",numberOfPoints);
	pdlg.setInfo(buffer);
	pdlg.start();

	//liblas::Point point(boost::shared_ptr<liblas::Header>(new liblas::Header(writer->GetHeader())));
	liblas::Point point(&writer->GetHeader());
	liblas::Classification classif = point.GetClassification();

	for (unsigned i=0; i<numberOfPoints; i++)
	{
		const CCVector3* P = theCloud->getPoint(i);
		{
			CCVector3d Pglobal = theCloud->toGlobal3d<PointCoordinateType>(*P);
			point.SetCoordinates(Pglobal.x, Pglobal.y, Pglobal.z);
		}
		
		if (hasColor)
		{
			const colorType* rgb = theCloud->getPointColor(i);
			point.SetColor(liblas::Color(rgb[0]<<8,rgb[1]<<8,rgb[2]<<8)); //DGM: LAS colors are stored on 16 bits!
		}

		//additional fields
		for (std::vector<LasField>::const_iterator it = fieldsToSave.begin(); it != fieldsToSave.end(); ++it)
		{
			assert(it->sf);
			switch(it->type)
			{
			case LAS_X:
			case LAS_Y:
			case LAS_Z:
				assert(false);
				break;
			case LAS_INTENSITY:
				point.SetIntensity((boost::uint16_t)it->sf->getValue(i));
				break;
			case LAS_RETURN_NUMBER:
				point.SetReturnNumber((boost::uint16_t)it->sf->getValue(i));
				break;
			case LAS_NUMBER_OF_RETURNS:
				point.SetNumberOfReturns((boost::uint16_t)it->sf->getValue(i));
				break;
			case LAS_SCAN_DIRECTION:
				point.SetScanDirection((boost::uint16_t)it->sf->getValue(i));
				break;
			case LAS_FLIGHT_LINE_EDGE:
				point.SetFlightLineEdge((boost::uint16_t)it->sf->getValue(i));
				break;
			case LAS_CLASSIFICATION:
				{
					boost::uint32_t val = (boost::uint32_t)it->sf->getValue(i);
					classif.SetClass(val & 31);		//first 5 bits
					classif.SetSynthetic(val & 32); //6th bit
					classif.SetKeyPoint(val & 64);	//7th bit
					classif.SetWithheld(val & 128);	//8th bit
				}
				break;
			case LAS_SCAN_ANGLE_RANK:
				point.SetScanAngleRank((boost::uint8_t)it->sf->getValue(i));
				break;
			case LAS_USER_DATA:
				point.SetUserData((boost::uint8_t)it->sf->getValue(i));
				break;
			case LAS_POINT_SOURCE_ID:
				point.SetPointSourceID((boost::uint16_t)it->sf->getValue(i));
				break;
			case LAS_RED:
			case LAS_GREEN:
			case LAS_BLUE:
				assert(false);
				break;
			case LAS_TIME:
				point.SetTime((double)it->sf->getValue(i));
				break;
			case LAS_CLASSIF_VALUE:
				classif.SetClass((boost::uint32_t)it->sf->getValue(i));
				break;
			case LAS_CLASSIF_SYNTHETIC:
				classif.SetSynthetic((boost::uint32_t)it->sf->getValue(i));
				break;
			case LAS_CLASSIF_KEYPOINT:
				classif.SetKeyPoint((boost::uint32_t)it->sf->getValue(i));
				break;
			case LAS_CLASSIF_WITHHELD:
				classif.SetWithheld((boost::uint32_t)it->sf->getValue(i));
				break;
			case LAS_INVALID:
			default:
				assert(false);
				break;
			}
		}

		//set classification (it's mandatory anyway ;)
		point.SetClassification(classif);

		writer->WritePoint(point);

		if (!nprogress.oneStep())
			break;
	}

	delete writer;
	ofs.close();

	return CC_FERR_NO_ERROR;
}
Пример #14
0
CC_FILE_ERROR MAFilter::saveToFile(ccHObject* entity, QString filename)
{
	if (!entity || filename.isEmpty())
		return CC_FERR_BAD_ARGUMENT;

	//the mesh to save
	ccGenericMesh* theMesh = ccHObjectCaster::ToGenericMesh(entity);
	if (!theMesh)
	{
		ccLog::Error("[MA] This filter can only save one mesh at a time!");
		return CC_FERR_BAD_ENTITY_TYPE;
	}
	//and its vertices
	ccGenericPointCloud* theCloud = theMesh->getAssociatedCloud();

	unsigned numberOfTriangles = theMesh->size();
	unsigned numberOfVertexes = theCloud->size();

	if (numberOfTriangles == 0 || numberOfVertexes == 0)
	{
		ccLog::Error("Mesh is empty!");
		return CC_FERR_BAD_ENTITY_TYPE;
	}

	bool hasColors = false;
	if (theCloud->isA(CC_TYPES::POINT_CLOUD))
		static_cast<ccPointCloud*>(theCloud)->hasColors();

	//and its scalar field
	/*CCLib::ScalarField* sf = 0;
	if (theCloud->isA(CC_TYPES::POINT_CLOUD))
	sf = static_cast<ccPointCloud*>(theCloud)->getCurrentDisplayedScalarField();

	if (!sf)
		ccLog::Warning("No displayed scalar field! Values will all be 0!\n");

	//*/

	//open ASCII file for writing
	FILE* fp = fopen(qPrintable(filename) , "wt");

	if (!fp)
		return CC_FERR_WRITING;

	//progress dialog
	ccProgressDialog pdlg(true); //cancel available
	unsigned palierModifier = (hasColors ? 1 : 0);
	CCLib::NormalizedProgress nprogress(&pdlg,unsigned(float((2+palierModifier)*numberOfTriangles+(3+palierModifier)*numberOfVertexes)));
	pdlg.setMethodTitle("Save MA file");
	char buffer[256];
	sprintf(buffer,"Triangles = %u",numberOfTriangles);
	pdlg.setInfo(buffer);
	pdlg.start();

	//we extract the (short) filename from the whole path
	QString baseFilename = QFileInfo(filename).fileName();

	//header
	if (fprintf(fp,"//Maya ASCII 7.0 scene\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (fprintf(fp,"//Name: %s\n",qPrintable(baseFilename)) < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (fprintf(fp,"//Last modified: Sat, Mai 10, 2008 00:00:00 PM\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (fprintf(fp,"requires maya \"4.0\";\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (fprintf(fp,"currentUnit -l %s -a degree -t film;\n","centimeter") < 0)
		{fclose(fp);return CC_FERR_WRITING;}

	//for multiple meshes handling (does not work yet)
	unsigned char currentMesh = 0;

	//transformation node
	if (fprintf(fp,"createNode transform -n \"Mesh%i\";\n",currentMesh+1) < 0)
		{fclose(fp);return CC_FERR_WRITING;}

	//main node
	if (fprintf(fp,"createNode mesh -n \"MeshShape%i\" -p \"Mesh%i\";\n",currentMesh+1,currentMesh+1) < 0)
		{fclose(fp);return CC_FERR_WRITING;}

	if (fprintf(fp,"\tsetAttr -k off \".v\";\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}

	if (fprintf(fp,"\tsetAttr \".uvst[0].uvsn\" -type \"string\" \"map1\";\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (fprintf(fp,"\tsetAttr \".cuvs\" -type \"string\" \"map1\";\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (hasColors)
	{
		if (fprintf(fp,"\tsetAttr \".dcol\" yes;\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}
	}
	if (fprintf(fp,"\tsetAttr \".dcc\" -type \"string\" \"Ambient+Diffuse\";\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (fprintf(fp,"\tsetAttr \".ccls\" -type \"string\" \"colorSet%i\";\n",currentMesh+1) < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (fprintf(fp,"\tsetAttr \".clst[0].clsn\" -type \"string\" \"colorSet%i\";\n",currentMesh+1) < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (hasColors)
	{
		if (fprintf(fp,"\tsetAttr \".ndt\" 0;\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"\tsetAttr \".tgsp\" 1;\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}

		//insert a secondary nodes
		if (fprintf(fp,"createNode mesh -n \"polySurfaceShape%i\" -p \"Mesh%i\";\n",currentMesh+1,currentMesh+1) < 0)
			{fclose(fp);return CC_FERR_WRITING;}

		if (fprintf(fp,"\tsetAttr -k off \".v\";\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"\tsetAttr \".io\" yes;\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"\tsetAttr \".uvst[0].uvsn\" -type \"string\" \"map1\";\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"\tsetAttr \".cuvs\" -type \"string\" \"map1\";\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"\tsetAttr \".dcol\" yes;\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"\tsetAttr \".dcc\" -type \"string\" \"Ambient+Diffuse\";\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"\tsetAttr \".ccls\" -type \"string\" \"colorSet%i\";\n",currentMesh+1) < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"\tsetAttr \".clst[0].clsn\" -type \"string\" \"colorSet%i\";\n",currentMesh+1) < 0)
			{fclose(fp);return CC_FERR_WRITING;}
	}

	//save vertexes
	if (fprintf(fp,"\tsetAttr -s %u \".vt[0:%u]\"\n",numberOfVertexes,numberOfVertexes-1) < 0)
	{
		fclose(fp);
		return CC_FERR_WRITING;
	}
	{
		for (unsigned i=0; i<numberOfVertexes; ++i)
		{
			const CCVector3* P = theCloud->getPoint(i);
			CCVector3d Pglobal = theCloud->toGlobal3d<PointCoordinateType>(*P);
			if (fprintf(fp,(i+1==numberOfVertexes ? "\t\t%f %f %f;\n" : "\t\t%f %f %f\n"),
							Pglobal.x,
							Pglobal.y,
							Pglobal.z) < 0)
			{
				fclose(fp);
				return CC_FERR_WRITING;
			}

			nprogress.oneStep();
		}
	}

	//save "edges"
	edge** theEdges = new edge*[numberOfVertexes];
	memset(theEdges,0,sizeof(edge*)*numberOfVertexes);
	unsigned ind[3],a,b;
	int currentEdgeIndex=0,lastEdgeIndexPushed=-1;

	int hard=0; //Maya edges cab be "hard" or "soft" ...
	{
		theMesh->placeIteratorAtBegining();
		for (unsigned i=0;i<numberOfTriangles;++i)
		{
			const CCLib::TriangleSummitsIndexes* tsi = theMesh->getNextTriangleIndexes(); //DGM: getNextTriangleIndexes is faster for mesh groups!

			ind[0] = tsi->i1;
			ind[1] = tsi->i2;
			ind[2] = tsi->i3;

			uchar k,l;
			for (k=0; k<3; ++k)
			{
				l=(k<2 ? k+1 : 0);
				a = (ind[k]<ind[l] ? ind[k] : ind[l]);
				b = (a==ind[k] ? ind[l] : ind[k]);

				currentEdgeIndex = -1;
				edge* e = theEdges[a];
				while (e)
				{
					if (e->theOtherPoint == b)
					{
						currentEdgeIndex = e->edgeIndex;
						break;
					}
					e = e->nextEdge;
				}

				if (currentEdgeIndex < 0) //create a new edge
				{
					edge* newEdge = new edge;
					newEdge->nextEdge = NULL;
					newEdge->theOtherPoint = b;
					newEdge->positif = (a==ind[k]);
					//newEdge->edgeIndex = ++lastEdgeIndexPushed; //don't write the edge right now
					newEdge->edgeIndex = 0;
					++lastEdgeIndexPushed;
					//currentEdgeIndex = lastEdgeIndexPushed;

					//don't forget the node!
					if (theEdges[a])
					{
						e = theEdges[a];
						while (e->nextEdge) e=e->nextEdge;
						e->nextEdge = newEdge;
					}
					else theEdges[a]=newEdge;

					/*if (fprintf(fp,"\n \t\t%i %i %i",a,b,hard) < 0)
						return CC_FERR_WRITING;*/
				}
			}

			nprogress.oneStep();
		}
	}

	//now write the edges
	{
		unsigned numberOfEdges = unsigned(lastEdgeIndexPushed+1);
		if (fprintf(fp,"\tsetAttr -s %u \".ed[0:%u]\"",numberOfEdges,numberOfEdges-1) < 0)
		{
			fclose(fp);
			return CC_FERR_WRITING;
		}

		lastEdgeIndexPushed = 0;
		for (unsigned i=0; i<numberOfVertexes; ++i)
		{
			edge* e = theEdges[i];
			while (e)
			{
				e->edgeIndex = lastEdgeIndexPushed++;
				if (fprintf(fp,"\n \t\t%u %u %i",i,e->theOtherPoint,hard) < 0)
				{
					fclose(fp);
					return CC_FERR_WRITING;
				}
				e = e->nextEdge;
			}

			nprogress.oneStep();
		}
	}

	if (fprintf(fp,";\n") < 0)
	{
		fclose(fp);
		return CC_FERR_WRITING;
	}

	//write faces
	if (fprintf(fp,"\tsetAttr -s %u \".fc[0:%u]\" -type \"polyFaces\"\n",numberOfTriangles,numberOfTriangles-1) < 0)
	{
		fclose(fp);
		return CC_FERR_WRITING;
	}

	theMesh->placeIteratorAtBegining();
	{
		for (unsigned i=0; i<numberOfTriangles; ++i)
		{
			if (fprintf(fp,"\t\tf 3") < 0)
			{
				fclose(fp);
				return CC_FERR_WRITING;
			}

			CCLib::TriangleSummitsIndexes* tsi = theMesh->getNextTriangleIndexes(); //DGM: getNextTriangleIndexes is faster for mesh groups!
			ind[0] = tsi->i1;
			ind[1] = tsi->i2;
			ind[2] = tsi->i3;

			for (uchar k=0; k<3; ++k)
			{
				uchar l = (k<2 ? k+1 : 0);
				a = (ind[k]<ind[l] ? ind[k] : ind[l]);
				b = (a==ind[k] ? ind[l] : ind[k]);

				edge* e = theEdges[a];
				while (e->theOtherPoint != b)
					e = e->nextEdge;

				if (fprintf(fp," %i",((e->positif && a==ind[k]) || (!e->positif && a==ind[l]) ? e->edgeIndex : -(e->edgeIndex+1))) < 0)
				{
					fclose(fp);
					return CC_FERR_WRITING;
				}
			}

			if (fprintf(fp,(i+1==numberOfTriangles ? ";\n" : "\n")) < 0)
			{
				fclose(fp);
				return CC_FERR_WRITING;
			}

			nprogress.oneStep();
		}
	}

	//free memory
	{
		for (unsigned i=0; i<numberOfVertexes; ++i)
		{
			if (theEdges[i])
			{
				edge* e = theEdges[i]->nextEdge;
				while (e)
				{
					edge* nextE = e->nextEdge;
					delete e;
					e = nextE;
				}
				delete theEdges[i];
			}

			nprogress.oneStep();
		}
	}

	//bonus track
	if (	fprintf(fp,"\tsetAttr \".cd\" -type \"dataPolyComponent\" Index_Data Edge 0 ;\n") < 0
		||	fprintf(fp,"\tsetAttr \".ndt\" 0;\n") < 0
		||	fprintf(fp,"\tsetAttr \".tgsp\" 1;\n") < 0 )
	{
		fclose(fp);
		return CC_FERR_WRITING;
	}

	//vertex colors
	if (hasColors)
	{
		assert(theCloud->isA(CC_TYPES::POINT_CLOUD));
		ccPointCloud* pc = static_cast<ccPointCloud*>(theCloud);

		if (fprintf(fp,"createNode polyColorPerVertex -n \"polyColorPerVertex%i\";\n",currentMesh+1) < 0)
			{fclose(fp);return CC_FERR_WRITING;}

		if (fprintf(fp,"\tsetAttr \".uopa\" yes;\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}

		if (fprintf(fp,"\tsetAttr -s %u \".vclr\";\n",numberOfVertexes) < 0)
			{fclose(fp);return CC_FERR_WRITING;}

		//association of each vertex with the faces it belongs to
		faceIndexes** theFacesIndexes = new faceIndexes*[numberOfVertexes];
		memset(theFacesIndexes,0,sizeof(faceIndexes*)*numberOfVertexes);
		theMesh->placeIteratorAtBegining();
		{
			for (unsigned i=0; i<numberOfTriangles; ++i)
			{
				CCLib::TriangleSummitsIndexes* tsi = theMesh->getNextTriangleIndexes(); //DGM: getNextTriangleIndexes is faster for mesh groups!
				ind[0] = tsi->i1;
				ind[1] = tsi->i2;
				ind[2] = tsi->i3;

				for (uchar j=0; j<3; ++j)
				{
					if (!theFacesIndexes[ind[j]])
					{
						faceIndexes* f = new faceIndexes;
						f->faceIndex = i;
						f->nextFace = NULL;
						theFacesIndexes[ind[j]] = f;
					}
					else
					{
						faceIndexes* f = theFacesIndexes[ind[j]];
						while (f->nextFace)
							f = f->nextFace;
						f->nextFace = new faceIndexes;
						f->nextFace->faceIndex = i;
						f->nextFace->nextFace = NULL;
					}
				}

				nprogress.oneStep();
			}
		}

		//for each vertex
		{
			float col[3];
			float coef = 1.0f/static_cast<float>(MAX_COLOR_COMP);
			for (unsigned i=0; i<numberOfVertexes; ++i)
			{
				const colorType* c = pc->getPointColor(i);
				col[0] = static_cast<float>(c[0]) * coef;
				col[1] = static_cast<float>(c[1]) * coef;
				col[2] = static_cast<float>(c[2]) * coef;

				//on compte le nombre de faces
				int nf = 0;
				faceIndexes* f = theFacesIndexes[i];
				while (f)
				{
					++nf;
					f = f->nextFace;
				}

				if (nf > 0)
				{
					if (fprintf(fp,"\tsetAttr -s %i \".vclr[%u].vfcl\";\n",nf,i) < 0)
						{fclose(fp);return CC_FERR_WRITING;}

					faceIndexes *oldf, *f = theFacesIndexes[i];
					while (f)
					{
						if (fprintf(fp,"\tsetAttr \".vclr[%u].vfcl[%i].frgb\" -type \"float3\" %f %f %f;\n",i,f->faceIndex,col[0],col[1],col[2]) < 0)
						{
							fclose(fp);
							return CC_FERR_WRITING;
						}

						oldf = f;
						f = f->nextFace;
						delete oldf;
					}
					theFacesIndexes[i] = NULL;
				}

				nprogress.oneStep();
			}
		}
		delete[] theFacesIndexes;

		if (fprintf(fp,"\tsetAttr \".cn\" -type \"string\" \"colorSet%i\";\n",currentMesh+1) < 0)
		{
			fclose(fp);
			return CC_FERR_WRITING;
		}
	}

	//Maya connections
	if (hasColors)
	{
		if (	fprintf(fp,"connectAttr \"polyColorPerVertex%i.out\" \"MeshShape%i.i\";\n",currentMesh+1,currentMesh+1) < 0
			||	fprintf(fp,"connectAttr \"polySurfaceShape%i.o\" \"polyColorPerVertex%i.ip\";\n",currentMesh+1,currentMesh+1) < 0 )
		{
			fclose(fp);
			return CC_FERR_WRITING;
		}
	}
	
	if (fprintf(fp,"connectAttr \"MeshShape%i.iog\" \":initialShadingGroup.dsm\" -na;\n",currentMesh+1) < 0)
	{
		fclose(fp);
		return CC_FERR_WRITING;
	}

	//end of file
	if (fprintf(fp,"//End of %s\n",qPrintable(baseFilename)) < 0)
	{
		fclose(fp);
		return CC_FERR_WRITING;
	}

	fclose(fp);

	return CC_FERR_NO_ERROR;
}
Пример #15
0
int Decrypt(wxFile& pkg_f, wxFile& dec_pkg_f, PKGHeader* m_header)
{
	if (!LoadHeader(pkg_f, m_header))
		return -1;

	aes_context c;
	u8 iv[HASH_LEN];
	u8 buf[BUF_SIZE];
	u8 ctr[BUF_SIZE];
	
	// Debug key
	u8 key[0x40];
	memset(key, 0, 0x40);
	memcpy(key+0x00, &m_header->qa_digest[0], 8); // &data[0x60]
	memcpy(key+0x08, &m_header->qa_digest[0], 8); // &data[0x60]
	memcpy(key+0x10, &m_header->qa_digest[8], 8); // &data[0x68]
	memcpy(key+0x18, &m_header->qa_digest[8], 8); // &data[0x68]

	pkg_f.Seek(m_header->data_offset);
	u32 parts = (m_header->data_size + BUF_SIZE - 1) / BUF_SIZE;

	wxProgressDialog pdlg("PKG Decrypter / Installer", "Please wait, decrypting...", parts, 0, wxPD_AUTO_HIDE | wxPD_APP_MODAL);

	memcpy(iv, m_header->klicensee, sizeof(iv));
	aes_setkey_enc(&c, PKG_AES_KEY, 128);
	
	for (u32 i=0; i<parts; i++)
	{
		memset(buf, 0, sizeof(buf));
		u32 length = pkg_f.Read(buf, BUF_SIZE);
		u32 bits = (length + HASH_LEN - 1) / HASH_LEN;
		
		if (m_header->pkg_type == PKG_RELEASE_TYPE_DEBUG)
		{
			for (u32 j=0; j<bits; j++)
			{
				u8 hash[0x14];
				sha1(key, 0x40, hash);
				*(u64*)&buf[j*HASH_LEN + 0] ^= *(u64*)&hash[0];
				*(u64*)&buf[j*HASH_LEN + 8] ^= *(u64*)&hash[8];
				*(be_t<u64>*)&key[0x38] += 1;
			}
		}

		if (m_header->pkg_type == PKG_RELEASE_TYPE_RELEASE)
		{
			for (u32 j=0; j<bits; j++)
			{
				aes_crypt_ecb(&c, AES_ENCRYPT, iv, ctr+j*HASH_LEN);

				be_t<u64> hi = *(be_t<u64>*)&iv[0];
				be_t<u64> lo = *(be_t<u64>*)&iv[8] + 1;

				if (lo == 0)
					hi += 1;

				*(be_t<u64>*)&iv[0] = hi;
				*(be_t<u64>*)&iv[8] = lo;
			}
		
			for (u32 j=0; j<length; j++) {
				buf[j] ^= ctr[j];
			}
		}		
		dec_pkg_f.Write(buf, length);
		pdlg.Update(i);
	}
	pdlg.Update(parts);
	return 0;
}
Пример #16
0
CC_FILE_ERROR PVFilter::saveToFile(ccHObject* entity, QString filename)
{
	if (!entity || filename.isEmpty())
		return CC_FERR_BAD_ARGUMENT;

	//the cloud to save
	ccGenericPointCloud* theCloud = ccHObjectCaster::ToGenericPointCloud(entity);
	if (!theCloud)
	{
		ccLog::Warning("[PV] This filter can only save one cloud at a time!");
		return CC_FERR_BAD_ENTITY_TYPE;
	}
	unsigned numberOfPoints = theCloud->size();

	if (numberOfPoints == 0)
	{
		ccLog::Warning("[PV] Input cloud is empty!");
		return CC_FERR_NO_SAVE;
	}

	//open binary file for writing
	QFile out(filename);
	if (!out.open(QIODevice::WriteOnly))
		return CC_FERR_WRITING;

	//Has the cloud been recentered?
	if (theCloud->isShifted())
		ccLog::Warning(QString("[PVFilter::save] Can't recenter or rescale cloud '%1' when saving it in a PN file!").arg(theCloud->getName()));

	//for point clouds with multiple SFs, we must set the currently displayed one as 'input' SF
	//if (theCloud->isA(CC_TYPES::POINT_CLOUD))
	//{
	//	ccPointCloud* pc = static_cast<ccPointCloud*>(theCloud);
	//	pc->setCurrentInScalarField(pc->getCurrentDisplayedScalarFieldIndex());
	//}
	bool hasSF = theCloud->hasDisplayedScalarField();
	if (!hasSF)
		ccLog::Warning(QString("[PVFilter::save] Cloud '%1' has no displayed scalar field (we will save points with a default scalar value)!").arg(theCloud->getName()));

	float val = std::numeric_limits<float>::quiet_NaN();

	//progress dialog
	ccProgressDialog pdlg(true); //cancel available
	CCLib::NormalizedProgress nprogress(&pdlg,numberOfPoints);
	pdlg.setMethodTitle("Save PV file");
	pdlg.setInfo(qPrintable(QString("Points: %1").arg(numberOfPoints)));
	pdlg.start();

	CC_FILE_ERROR result = CC_FERR_NO_ERROR;

	for (unsigned i=0; i<numberOfPoints; i++)
	{
		//write point
		{
			const CCVector3* P = theCloud->getPoint(i);
			
			//conversion to float
			float wBuff[3] = {(float)P->x, (float)P->y, (float)P->z};
			if (out.write((const char*)wBuff,3*sizeof(float)) < 0)
			{
				result = CC_FERR_WRITING;
				break;
			}
		}
			
		//write scalar value
		if (hasSF)
			val = static_cast<float>(theCloud->getPointScalarValue(i));
		if (out.write((const char*)&val,sizeof(float)) < 0)
		{
			result = CC_FERR_WRITING;
			break;
		}

		if (!nprogress.oneStep())
		{
			result = CC_FERR_CANCELED_BY_USER;
			break;
		}
	}

	out.close();

	return result;
}
Пример #17
0
CC_FILE_ERROR PTXFilter::loadFile(	QString filename,
									ccHObject& container,
									LoadParameters& parameters)
{
	//open ASCII file for reading
	QFile file(filename);
	if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
	{
		return CC_FERR_READING;
	}

	QTextStream inFile(&file);

	CCVector3d PshiftTrans(0,0,0);
	CCVector3d PshiftCloud(0,0,0);

	CC_FILE_ERROR result = CC_FERR_NO_LOAD;
	ScalarType minIntensity = 0;
	ScalarType maxIntensity = 0;

	//progress dialog
	ccProgressDialog pdlg(true, parameters.parentWidget);
	pdlg.setMethodTitle(QObject::tr("Loading PTX file"));
	pdlg.setAutoClose(false);

	//progress dialog (for normals computation)
	ccProgressDialog normalsProgressDlg(true, parameters.parentWidget);
	normalsProgressDlg.setAutoClose(false);

	for (unsigned cloudIndex = 0; result == CC_FERR_NO_ERROR || result == CC_FERR_NO_LOAD; cloudIndex++)
	{
		unsigned width = 0, height = 0;
		ccGLMatrixd sensorTransD, cloudTransD;

		//read header
		{
			QString line = inFile.readLine();
			if (line.isNull() && container.getChildrenNumber() != 0) //end of file?
				break;

			//read the width (number of columns) and the height (number of rows) on the two first lines
			//(DGM: we transpose the matrix right away)
			bool ok;
			height = line.toUInt(&ok);
			if (!ok)
				return CC_FERR_MALFORMED_FILE;
			line = inFile.readLine();
			width = line.toUInt(&ok);
			if (!ok)
				return CC_FERR_MALFORMED_FILE;

			ccLog::Print(QString("[PTX] Scan #%1 - grid size: %2 x %3").arg(cloudIndex+1).arg(height).arg(width));

			//read sensor transformation matrix
			for (int i=0; i<4; ++i)
			{
				line = inFile.readLine();
				QStringList tokens = line.split(" ",QString::SkipEmptyParts);
				if (tokens.size() != 3)
					return CC_FERR_MALFORMED_FILE;

				double* colDest = 0;
				if (i == 0)
				{
					//Translation
					colDest = sensorTransD.getTranslation();
				}
				else
				{
					//X, Y and Z axis
					colDest = sensorTransD.getColumn(i-1);
				}

				for (int j=0; j<3; ++j)
				{
					assert(colDest);
					colDest[j] = tokens[j].toDouble(&ok);
					if (!ok)
						return CC_FERR_MALFORMED_FILE;
				}
			}
			//make the transform a little bit cleaner (necessary as it's read from ASCII!)
			CleanMatrix(sensorTransD);

			//read cloud transformation matrix
			for (int i=0; i<4; ++i)
			{
				line = inFile.readLine();
				QStringList tokens = line.split(" ",QString::SkipEmptyParts);
				if (tokens.size() != 4)
					return CC_FERR_MALFORMED_FILE;

				double* col = cloudTransD.getColumn(i);
				for (int j=0; j<4; ++j)
				{
					col[j] = tokens[j].toDouble(&ok);
					if (!ok)
						return CC_FERR_MALFORMED_FILE;
				}
			}
			//make the transform a little bit cleaner (necessary as it's read from ASCII!)
			CleanMatrix(cloudTransD);

			//handle Global Shift directly on the first cloud's translation!
			if (cloudIndex == 0)
			{
				if (HandleGlobalShift(cloudTransD.getTranslationAsVec3D(),PshiftTrans,parameters))
				{
					ccLog::Warning("[PTXFilter::loadFile] Cloud has be recentered! Translation: (%.2f,%.2f,%.2f)",PshiftTrans.x,PshiftTrans.y,PshiftTrans.z);
				}
			}

			//'remove' global shift from the sensor and cloud transformation matrices
			cloudTransD.setTranslation(cloudTransD.getTranslationAsVec3D() + PshiftTrans);
			sensorTransD.setTranslation(sensorTransD.getTranslationAsVec3D() + PshiftTrans);
		}

		//now we can read the grid cells
		ccPointCloud* cloud = new ccPointCloud();
		if (container.getChildrenNumber() == 0)
		{
			cloud->setName("unnamed - Cloud");
		}
		else
		{
			if (container.getChildrenNumber() == 1)
				container.getChild(0)->setName("unnamed - Cloud 1"); //update previous cloud name!

			cloud->setName(QString("unnamed - Cloud %1").arg(container.getChildrenNumber()+1));
		}

		unsigned gridSize = width * height;
		if (!cloud->reserve(gridSize))
		{
			result = CC_FERR_NOT_ENOUGH_MEMORY;
			delete cloud;
			cloud = 0;
			break;
		}

		//set global shift
		cloud->setGlobalShift(PshiftTrans);

		//intensities
		ccScalarField* intensitySF = new ccScalarField(CC_PTX_INTENSITY_FIELD_NAME);
		if (!intensitySF->reserve(static_cast<unsigned>(gridSize)))
		{
			ccLog::Warning("[PTX] Not enough memory to load intensities!");
			intensitySF->release();
			intensitySF = 0;
		}

		//grid structure
		ccPointCloud::Grid::Shared grid(new ccPointCloud::Grid);
		grid->w = width;
		grid->h = height;
		bool hasIndexGrid = true;
		try
		{
			grid->indexes.resize(gridSize,-1); //-1 means no cell/point
		}
		catch (const std::bad_alloc&)
		{
			ccLog::Warning("[PTX] Not enough memory to load the grid structure");
			hasIndexGrid = false;
		}

		//read points
		{
			CCLib::NormalizedProgress nprogress(&pdlg, gridSize);
			pdlg.setInfo(qPrintable(QString("Number of cells: %1").arg(gridSize)));
			pdlg.start();

			bool firstPoint = true;
			bool hasColors = false;
			bool loadColors = false;
			bool loadGridColors = false;
			size_t gridIndex = 0;

			for (unsigned j=0; j<height; ++j)
			{
				for (unsigned i=0; i<width; ++i, ++gridIndex)
				{
					QString line = inFile.readLine();
					QStringList tokens = line.split(" ",QString::SkipEmptyParts);

					if (firstPoint)
					{
						hasColors = (tokens.size() == 7);
						if (hasColors)
						{
							loadColors = cloud->reserveTheRGBTable();
							if (!loadColors)
							{
								ccLog::Warning("[PTX] Not enough memory to load RGB colors!");
							}
							else if (hasIndexGrid)
							{
								//we also load the colors into the grid (as invalid/missing points can have colors!)
								try
								{
									grid->colors.resize(gridSize, ccColor::Rgb(0, 0, 0));
									loadGridColors = true;
								}
								catch (const std::bad_alloc&)
								{
									ccLog::Warning("[PTX] Not enough memory to load the grid colors");
								}
							}
						}
					}
					if ((hasColors && tokens.size() != 7) || (!hasColors && tokens.size() != 4))
					{
						result = CC_FERR_MALFORMED_FILE;
						//early stop
						j = height;
						break;
					}

					double values[4];
					for (int v=0; v<4; ++v)
					{
						bool ok;
						values[v] = tokens[v].toDouble(&ok);
						if (!ok)
						{
							result = CC_FERR_MALFORMED_FILE;
							//early stop
							j = height;
							break;
						}
					}

					//we skip "empty" cells
					bool pointIsValid = (CCVector3d::fromArray(values).norm2() != 0);
					if (pointIsValid)
					{
						const double* Pd = values;
						//first point: check for 'big' coordinates
						if (firstPoint)
						{
							if (cloudIndex == 0 && !cloud->isShifted()) //in case the trans. matrix was ok!
							{
								CCVector3d P(Pd);
								if (HandleGlobalShift(P,PshiftCloud,parameters))
								{
									cloud->setGlobalShift(PshiftCloud);
									ccLog::Warning("[PTXFilter::loadFile] Cloud has been recentered! Translation: (%.2f,%.2f,%.2f)",PshiftCloud.x,PshiftCloud.y,PshiftCloud.z);
								}
							}
							firstPoint = false;
						}

						//update index grid
						if (hasIndexGrid)
						{
							grid->indexes[gridIndex] = static_cast<int>(cloud->size()); // = index (default value = -1, means no point)
						}

						//add point
						cloud->addPoint(CCVector3(	static_cast<PointCoordinateType>(Pd[0] + PshiftCloud.x),
													static_cast<PointCoordinateType>(Pd[1] + PshiftCloud.y),
													static_cast<PointCoordinateType>(Pd[2] + PshiftCloud.z)) );

						//add intensity
						if (intensitySF)
						{
							intensitySF->addElement(static_cast<ScalarType>(values[3]));
						}
					}

					//color
					if (loadColors && (pointIsValid || loadGridColors))
					{
						ccColor::Rgb color;
						for (int c=0; c<3; ++c)
						{
							bool ok;
							unsigned temp = tokens[4+c].toUInt(&ok);
							ok &= (temp <= 255);
							if (ok)
							{
								color.rgb[c] = static_cast<unsigned char>(temp);
							}
							else
							{
								result = CC_FERR_MALFORMED_FILE;
								//early stop
								j = height;
								break;
							}
						}

						if (pointIsValid)
						{
							cloud->addRGBColor(color.rgb);
						}
						if (loadGridColors)
						{
							assert(!grid->colors.empty());
							grid->colors[gridIndex] = color;
						}
					}

					if (!nprogress.oneStep())
					{
						result = CC_FERR_CANCELED_BY_USER;
						break;
					}
				}
			}
		}

		//is there at least one valid point in this grid?
		if (cloud->size() == 0)
		{
			delete cloud;
			cloud = 0;
			if (intensitySF)
				intensitySF->release();

			ccLog::Warning(QString("[PTX] Scan #%1 is empty?!").arg(cloudIndex+1));
		}
		else
		{
			if (result == CC_FERR_NO_LOAD)
				result = CC_FERR_NO_ERROR; //to make clear that we have loaded at least something!
			
			cloud->resize(cloud->size());
			if (intensitySF)
			{
				assert(intensitySF->currentSize() == cloud->size());
				intensitySF->resize(cloud->size());
				intensitySF->computeMinAndMax();
				int intensitySFIndex = cloud->addScalarField(intensitySF);

				//keep track of the min and max intensity
				if (container.getChildrenNumber() == 0)
				{
					minIntensity = intensitySF->getMin();
					maxIntensity = intensitySF->getMax();
				}
				else
				{
					minIntensity = std::min(minIntensity,intensitySF->getMin());
					maxIntensity = std::max(maxIntensity,intensitySF->getMax());
				}

				cloud->showSF(true);
				cloud->setCurrentDisplayedScalarField(intensitySFIndex);
			}

			ccGBLSensor* sensor = 0;
			if (hasIndexGrid && result != CC_FERR_CANCELED_BY_USER)
			{
				//determine best sensor parameters (mainly yaw and pitch steps)
				ccGLMatrix cloudToSensorTrans((sensorTransD.inverse() * cloudTransD).data());
				sensor = ccGriddedTools::ComputeBestSensor(cloud, grid, &cloudToSensorTrans);
			}

			//we apply the transformation
			ccGLMatrix cloudTrans(cloudTransD.data());
			cloud->applyGLTransformation_recursive(&cloudTrans);
			
			if (sensor)
			{
				ccGLMatrix sensorTrans(sensorTransD.data());
				sensor->setRigidTransformation(sensorTrans); //after cloud->applyGLTransformation_recursive!
				cloud->addChild(sensor);
			}

			//scan grid
			if (hasIndexGrid)
			{
				grid->validCount = static_cast<unsigned>(cloud->size());
				grid->minValidIndex = 0;
				grid->maxValidIndex = grid->validCount-1;
				grid->sensorPosition = sensorTransD;
				cloud->addGrid(grid);

				//by default we don't compute normals without asking the user
				if (parameters.autoComputeNormals)
				{
					cloud->computeNormalsWithGrids(LS, 2, true, &normalsProgressDlg);
				}
			}

			cloud->setVisible(true);
			cloud->showColors(cloud->hasColors());
			cloud->showNormals(cloud->hasNormals());

			container.addChild(cloud);

#ifdef QT_DEBUG
			//break;
#endif
		}
	}

	//update scalar fields saturation (globally!)
	{
		bool validIntensityRange = true;
		if (minIntensity < 0 || maxIntensity > 1.0)
		{
			ccLog::Warning("[PTX] Intensity values are invalid (they should all fall in [0 ; 1])");
			validIntensityRange = false;
		}

		for (unsigned i=0; i<container.getChildrenNumber(); ++i)
		{
			ccHObject* obj = container.getChild(i);
			assert(obj && obj->isA(CC_TYPES::POINT_CLOUD));
			CCLib::ScalarField* sf = static_cast<ccPointCloud*>(obj)->getScalarField(0);
			if (sf)
			{
				ccScalarField* ccSF = static_cast<ccScalarField*>(sf);
				ccSF->setColorScale(ccColorScalesManager::GetDefaultScale(validIntensityRange ? ccColorScalesManager::ABS_NORM_GREY : ccColorScalesManager::GREY));
				ccSF->setSaturationStart(0/*minIntensity*/);
				ccSF->setSaturationStop(maxIntensity);
			}
		}
	}

	return result;
}
Пример #18
0
void TffdshowPageEnc::showPresets(void)
{
    if (!presets) {
        presets = new TpresetsEnc;
        presets->init();
    }
    enum {
        IDI_MNI_LOAD_ALL = 1000,
        IDI_MNI_LOAD_PAGE = 2000,
        IDI_MNI_SAVE_ALL = 3000,
        IDI_MNI_SAVE_PAGE = 4000,
        IDI_MNI_MANAGE   = 5000
    };
    HMENU hm = CreatePopupMenu();
    int ord = 0;
    insertSubmenu(hm, ord, _(IDC_BT_PRESET, _l("Load all")), createPresetsSubmenu(IDI_MNI_LOAD_ALL, false));
    insertSubmenu(hm, ord, _(IDC_BT_PRESET, _l("Load page")), createPresetsSubmenu(IDI_MNI_LOAD_PAGE, false));
    enable(hm, 1, pageIs && page->propsIDs ? true : false);
    insertSeparator(hm, ord);
    HMENU hmPresets = createPresetsSubmenu(IDI_MNI_SAVE_ALL, true);
    enable(hmPresets, 0, false);
    insertSubmenu(hm, ord, _(IDC_BT_PRESET, _l("Save all")), hmPresets);
    hmPresets = createPresetsSubmenu(IDI_MNI_SAVE_PAGE, true);
    enable(hmPresets, 0, false);
    insertSubmenu(hm, ord, _(IDC_BT_PRESET, _l("Save page")), hmPresets);
    enable(hm, 4, pageIs && page->propsIDs ? true : false);
    insertSeparator(hm, ord);
    insertMenuItem(hm, ord, IDI_MNI_MANAGE, _(IDC_BT_PRESET, _l("Manage presets...")), false);
    enable(hm, 6, presets->size() >= 2);
    RECT r;
    GetWindowRect(GetDlgItem(m_hwnd, IDC_BT_PRESET), &r);
    POINT p = {0, r.bottom - r.top};
    ClientToScreen(GetDlgItem(m_hwnd, IDC_BT_PRESET), &p);
    int cmd = TrackPopupMenu(hm, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, p.x, p.y, 0, m_hwnd, NULL);
    PostMessage(m_hwnd, WM_NULL, 0, 0);
    if (cmd != 0)
        if (cmd == 5000) {
            TpresetsEncDlg pdlg(m_hwnd, deci, *presets);
        } else {
            int presetnum = cmd % 1000;
            TpresetEnc *preset = NULL;
            if (presetnum == 999) {
                char_t presetName[MAX_PATH] = _l("");
                if (inputString(_(IDC_BT_PRESET, _l("Save as new preset")), _(IDC_BT_PRESET, _l("Preset name")), presetName, MAX_PATH) && presetName[0]) {
                    preset = presets->getPreset(presetName);
                    if (!preset) {
                        preset = presets->createPreset(presetName);
                    }
                }
            } else {
                preset = &(*presets)[presetnum];
            }
            if (preset)
                switch (cmd = cmd / 1000) {
                    case 1:
                    case 2:
                        preset->apply(&localCfg, cmd == 1 ? &*allPropsIDs.begin() : page->propsIDs);
                        setChange();
                        if (cmd == 1) {
                            codec2dlg();
                        }
                        selectPage(page);
                        break;
                    case 3:
                    case 4:
                        preset->store(&localCfg, cmd == 3 ? &*allPropsIDs.begin() : page->propsIDs);
                        selectPage(page);
                        presets->save();
                        break;
                }
        }
    DestroyMenu(hm);
}
Пример #19
0
CC_FILE_ERROR LASFilter::loadFile(const char* filename, ccHObject& container, bool alwaysDisplayLoadDialog/*=true*/, bool* coordinatesShiftEnabled/*=0*/, CCVector3d* coordinatesShift/*=0*/)
{
	//opening file
	std::ifstream ifs;
	ifs.open(filename, std::ios::in | std::ios::binary);

	if (ifs.fail())
		return CC_FERR_READING;

	liblas::Reader* reader = 0;
	unsigned nbOfPoints = 0;
	std::vector<std::string> dimensions;

	try
	{
		reader = new liblas::Reader(liblas::ReaderFactory().CreateWithStream(ifs));	//using factory for automatic and transparent
		//handling of compressed/uncompressed files
		liblas::Header const& header = reader->GetHeader();

		ccLog::PrintDebug(QString("[LAS FILE] %1 - signature: %2").arg(filename).arg(header.GetFileSignature().c_str()));

		//get fields present in file
		dimensions = header.GetSchema().GetDimensionNames();

		//and of course the number of points
		nbOfPoints = header.GetPointRecordsCount();
	}
	catch (...)
	{
		delete reader;
		ifs.close();
		return CC_FERR_READING;
	}

	if (nbOfPoints==0)
	{
		//strange file ;)
		delete reader;
		ifs.close();
		return CC_FERR_NO_LOAD;
	}

	//dialog to choose the fields to load
	if (!s_lasOpenDlg)
		s_lasOpenDlg = QSharedPointer<LASOpenDlg>(new LASOpenDlg());
	s_lasOpenDlg->setDimensions(dimensions);
	if (alwaysDisplayLoadDialog && !s_lasOpenDlg->autoSkipMode() && !s_lasOpenDlg->exec())
	{
		delete reader;
		ifs.close();
		return CC_FERR_CANCELED_BY_USER;
	}
	bool ignoreDefaultFields = s_lasOpenDlg->ignoreDefaultFieldsCheckBox->isChecked();

	//RGB color
	liblas::Color rgbColorMask; //(0,0,0) on construction
	if (s_lasOpenDlg->doLoad(LAS_RED))
		rgbColorMask.SetRed(~0);
	if (s_lasOpenDlg->doLoad(LAS_GREEN))
		rgbColorMask.SetGreen(~0);
	if (s_lasOpenDlg->doLoad(LAS_BLUE))
		rgbColorMask.SetBlue(~0);
	bool loadColor = (rgbColorMask[0] || rgbColorMask[1] || rgbColorMask[2]);

	//progress dialog
	ccProgressDialog pdlg(true); //cancel available
	CCLib::NormalizedProgress nprogress(&pdlg,nbOfPoints);
	pdlg.setMethodTitle("Open LAS file");
	pdlg.setInfo(qPrintable(QString("Points: %1").arg(nbOfPoints)));
	pdlg.start();

	//number of points read from the begining of the current cloud part
	unsigned pointsRead = 0;
	CCVector3d Pshift(0,0,0);

	//by default we read color as 8 bits integers and we will change this to 16 bits if it's not (16 bits is the standard!)
	unsigned char colorCompBitDec = 0;
	colorType rgb[3] = {0,0,0};

	ccPointCloud* loadedCloud = 0;
	std::vector<LasField> fieldsToLoad;

	//if the file is too big, we will chunck it in multiple parts
	unsigned int fileChunkPos = 0;
	unsigned int fileChunkSize = 0;

	while (true)
	{
		//if we reach the end of the file, or the max. cloud size limit (in which case we cerate a new chunk)
		bool newPointAvailable = (nprogress.oneStep() && reader->ReadNextPoint());

		if (!newPointAvailable || pointsRead == fileChunkPos+fileChunkSize)
		{
			if (loadedCloud)
			{
				if (loadedCloud->size())
				{
					bool thisChunkHasColors = loadedCloud->hasColors();
					loadedCloud->showColors(thisChunkHasColors);
					if (loadColor && !thisChunkHasColors)
						ccLog::Warning("[LAS FILE] Color field was all black! We ignored it...");

					while (!fieldsToLoad.empty())
					{
						LasField& field = fieldsToLoad.back();
						if (field.sf)
						{
							field.sf->computeMinAndMax();

							if (field.type == LAS_CLASSIFICATION
								|| field.type == LAS_RETURN_NUMBER
								|| field.type == LAS_NUMBER_OF_RETURNS)
							{
								int cMin = (int)field.sf->getMin();
								int cMax = (int)field.sf->getMax();
								field.sf->setColorRampSteps(std::min<int>(cMax-cMin+1,256));
								//classifSF->setMinSaturation(cMin);
							}
							else if (field.type == LAS_INTENSITY)
							{
								field.sf->setColorScale(ccColorScalesManager::GetDefaultScale(ccColorScalesManager::GREY));
							}

							int sfIndex = loadedCloud->addScalarField(field.sf);
							if (!loadedCloud->hasDisplayedScalarField())
							{
								loadedCloud->setCurrentDisplayedScalarField(sfIndex);
								loadedCloud->showSF(!thisChunkHasColors);
							}
							field.sf->release();
							field.sf=0;
						}
						else
						{
							ccLog::Warning(QString("[LAS FILE] All '%1' values were the same (%2)! We ignored them...").arg(LAS_FIELD_NAMES[field.type]).arg(field.firstValue));
						}

						fieldsToLoad.pop_back();
					}

					//if we have reserved too much memory
					if (loadedCloud->size() < loadedCloud->capacity())
						loadedCloud->resize(loadedCloud->size());

					QString chunkName("unnamed - Cloud");
					unsigned n = container.getChildrenNumber();
					if (n!=0) //if we have more than one cloud, we append an index
					{
						if (n==1)  //we must also update the first one!
							container.getChild(0)->setName(chunkName+QString(" #1"));
						chunkName += QString(" #%1").arg(n+1);
					}
					loadedCloud->setName(chunkName);

					container.addChild(loadedCloud);
					loadedCloud=0;
				}
				else
				{
					//empty cloud?!
					delete loadedCloud;
					loadedCloud=0;
				}
			}

			if (!newPointAvailable)
				break; //end of the file (or cancel requested)

			//otherwise, we must create a new cloud
			fileChunkPos = pointsRead;
			fileChunkSize = std::min(nbOfPoints-pointsRead,CC_MAX_NUMBER_OF_POINTS_PER_CLOUD);
			loadedCloud = new ccPointCloud();
			if (!loadedCloud->reserveThePointsTable(fileChunkSize))
			{
				ccLog::Warning("[LASFilter::loadFile] Not enough memory!");
				delete loadedCloud;
				delete reader;
				ifs.close();
				return CC_FERR_NOT_ENOUGH_MEMORY;
			}
			loadedCloud->setGlobalShift(Pshift);

			//DGM: from now on, we only enable scalar fields when we detect a valid value!
			if (s_lasOpenDlg->doLoad(LAS_CLASSIFICATION))
					fieldsToLoad.push_back(LasField(LAS_CLASSIFICATION,0,0,255)); //unsigned char: between 0 and 255
			if (s_lasOpenDlg->doLoad(LAS_CLASSIF_VALUE))
				fieldsToLoad.push_back(LasField(LAS_CLASSIF_VALUE,0,0,31)); //5 bits: between 0 and 31
			if (s_lasOpenDlg->doLoad(LAS_CLASSIF_SYNTHETIC))
				fieldsToLoad.push_back(LasField(LAS_CLASSIF_SYNTHETIC,0,0,1)); //1 bit: 0 or 1
			if (s_lasOpenDlg->doLoad(LAS_CLASSIF_KEYPOINT))
				fieldsToLoad.push_back(LasField(LAS_CLASSIF_KEYPOINT,0,0,1)); //1 bit: 0 or 1
			if (s_lasOpenDlg->doLoad(LAS_CLASSIF_WITHHELD))
				fieldsToLoad.push_back(LasField(LAS_CLASSIF_WITHHELD,0,0,1)); //1 bit: 0 or 1
			if (s_lasOpenDlg->doLoad(LAS_INTENSITY))
				fieldsToLoad.push_back(LasField(LAS_INTENSITY,0,0,65535)); //16 bits: between 0 and 65536
			if (s_lasOpenDlg->doLoad(LAS_TIME))
				fieldsToLoad.push_back(LasField(LAS_TIME,0,0,-1.0)); //8 bytes (double)
			if (s_lasOpenDlg->doLoad(LAS_RETURN_NUMBER))
				fieldsToLoad.push_back(LasField(LAS_RETURN_NUMBER,1,1,7)); //3 bits: between 1 and 7
			if (s_lasOpenDlg->doLoad(LAS_NUMBER_OF_RETURNS))
				fieldsToLoad.push_back(LasField(LAS_NUMBER_OF_RETURNS,1,1,7)); //3 bits: between 1 and 7
			if (s_lasOpenDlg->doLoad(LAS_SCAN_DIRECTION))
				fieldsToLoad.push_back(LasField(LAS_SCAN_DIRECTION,0,0,1)); //1 bit: 0 or 1
			if (s_lasOpenDlg->doLoad(LAS_FLIGHT_LINE_EDGE))
				fieldsToLoad.push_back(LasField(LAS_FLIGHT_LINE_EDGE,0,0,1)); //1 bit: 0 or 1
			if (s_lasOpenDlg->doLoad(LAS_SCAN_ANGLE_RANK))
				fieldsToLoad.push_back(LasField(LAS_SCAN_ANGLE_RANK,0,-90,90)); //signed char: between -90 and +90
			if (s_lasOpenDlg->doLoad(LAS_USER_DATA))
				fieldsToLoad.push_back(LasField(LAS_USER_DATA,0,0,255)); //unsigned char: between 0 and 255
			if (s_lasOpenDlg->doLoad(LAS_POINT_SOURCE_ID))
				fieldsToLoad.push_back(LasField(LAS_POINT_SOURCE_ID,0,0,65535)); //16 bits: between 0 and 65536
		}

		assert(newPointAvailable);
		const liblas::Point& p = reader->GetPoint();

		//first point: check for 'big' coordinates
		if (pointsRead == 0)
		{
			CCVector3d P( p.GetX(),p.GetY(),p.GetZ() );
			bool shiftAlreadyEnabled = (coordinatesShiftEnabled && *coordinatesShiftEnabled && coordinatesShift);
			if (shiftAlreadyEnabled)
				Pshift = *coordinatesShift;
			bool applyAll = false;
			if (	sizeof(PointCoordinateType) < 8
				&&	ccCoordinatesShiftManager::Handle(P.u,0,alwaysDisplayLoadDialog,shiftAlreadyEnabled,Pshift,0,applyAll))
			{
				loadedCloud->setGlobalShift(Pshift);
				ccLog::Warning("[LASFilter::loadFile] Cloud has been recentered! Translation: (%.2f,%.2f,%.2f)",Pshift.x,Pshift.y,Pshift.z);

				//we save coordinates shift information
				if (applyAll && coordinatesShiftEnabled && coordinatesShift)
				{
					*coordinatesShiftEnabled = true;
					*coordinatesShift = Pshift;
				}
			}
		}

		CCVector3 P(static_cast<PointCoordinateType>(p.GetX()+Pshift.x),
					static_cast<PointCoordinateType>(p.GetY()+Pshift.y),
					static_cast<PointCoordinateType>(p.GetZ()+Pshift.z));
		loadedCloud->addPoint(P);

		//color field
		if (loadColor)
		{
			//Warning: LAS colors are stored on 16 bits!
			liblas::Color col = p.GetColor();
			col[0] &= rgbColorMask[0];
			col[1] &= rgbColorMask[1];
			col[2] &= rgbColorMask[2];

			//if we don't have reserved a color field yet, we check first that color is not black
			bool pushColor = true;
			if (!loadedCloud->hasColors())
			{
				//if the color is not black, we are sure it's a valid color field!
				if (col[0] || col[1] || col[2])
				{
					if (loadedCloud->reserveTheRGBTable())
					{
						//we must set the color (black) of all the precedently skipped points
						for (unsigned i=0;i<loadedCloud->size()-1;++i)
							loadedCloud->addRGBColor(ccColor::black);
					}
					else
					{
						ccLog::Warning("[LAS FILE] Not enough memory: color field will be ignored!");
						loadColor = false; //no need to retry with the other chunks anyway
						pushColor = false;
					}
				}
				else //otherwise we ignore it for the moment (we'll add it later if necessary)
				{
					pushColor = false;
				}
			}

			//do we need to push this color?
			if (pushColor)
			{
				//we test if the color components are on 16 bits (standard) or only on 8 bits (it happens ;)
				if (colorCompBitDec==0)
				{
					if (	(col[0] & 0xFF00)
						||  (col[1] & 0xFF00)
						||  (col[2] & 0xFF00))
					{
						//the color components are on 16 bits!
						ccLog::Print("[LAS FILE] Color components are coded on 16 bits");
						colorCompBitDec = 8;
						//we fix all the precedently read colors
						for (unsigned i=0;i<loadedCloud->size()-1;++i)
							loadedCloud->setPointColor(i,ccColor::black); //255 >> 8 = 0!
					}
				}

				rgb[0]=(colorType)(col[0]>>colorCompBitDec);
				rgb[1]=(colorType)(col[1]>>colorCompBitDec);
				rgb[2]=(colorType)(col[2]>>colorCompBitDec);

				loadedCloud->addRGBColor(rgb);
			}
		}
		
		//additional fields
		for (std::vector<LasField>::iterator it = fieldsToLoad.begin(); it != fieldsToLoad.end(); ++it)
		{
			double value = 0.0;
			switch (it->type)
			{
			case LAS_X:
			case LAS_Y:
			case LAS_Z:
				assert(false);
				break;
			case LAS_INTENSITY:
				value = (double)p.GetIntensity();
				break;
			case LAS_RETURN_NUMBER:
				value = (double)p.GetReturnNumber();
				break;
			case LAS_NUMBER_OF_RETURNS:
				value = (double)p.GetNumberOfReturns();
				break;
			case LAS_SCAN_DIRECTION:
				value = (double)p.GetScanDirection();
				break;
			case LAS_FLIGHT_LINE_EDGE:
				value = (double)p.GetFlightLineEdge();
				break;
			case LAS_CLASSIFICATION:
				value = (double)p.GetClassification().GetClass();
				break;
			case LAS_SCAN_ANGLE_RANK:
				value = (double)p.GetScanAngleRank();
				break;
			case LAS_USER_DATA:
				value = (double)p.GetUserData();
				break;
			case LAS_POINT_SOURCE_ID:
				value = (double)p.GetPointSourceID();
				break;
			case LAS_RED:
			case LAS_GREEN:
			case LAS_BLUE:
				assert(false);
				break;
			case LAS_TIME:
				value = p.GetTime();
				break;
			case LAS_CLASSIF_VALUE:
				value = (double)(p.GetClassification().GetClass() & 31); //5 bits
				break;
			case LAS_CLASSIF_SYNTHETIC:
				value = (double)(p.GetClassification().GetClass() & 32); //bit #6
				break;
			case LAS_CLASSIF_KEYPOINT:
				value = (double)(p.GetClassification().GetClass() & 64); //bit #7
				break;
			case LAS_CLASSIF_WITHHELD:
				value = (double)(p.GetClassification().GetClass() & 128); //bit #8
				break;
			case LAS_INVALID:
			default:
				assert(false);
				break;
			}

			if (it->sf)
			{
				ScalarType s = static_cast<ScalarType>(value);
				it->sf->addElement(s);
			}
			else
			{
				//first point? we track its value
				if (loadedCloud->size() == 1)
				{
					it->firstValue = value;
				}
				
				if (!ignoreDefaultFields || value != it->firstValue || it->firstValue != it->defaultValue)
				{
					it->sf = new ccScalarField(it->getName());
					if (it->sf->reserve(fileChunkSize))
					{
						it->sf->link();
						//we must set the value (firstClassifValue) of all the precedently skipped points
						ScalarType firstS = static_cast<ScalarType>(it->firstValue);
						for (unsigned i=0; i<loadedCloud->size()-1; ++i)
							it->sf->addElement(firstS);

						ScalarType s = static_cast<ScalarType>(value);
						it->sf->addElement(s);
					}
					else
					{
						ccLog::Warning(QString("[LAS FILE] Not enough memory: '%1' field will be ignored!").arg(LAS_FIELD_NAMES[it->type]));
						it->sf->release();
						it->sf = 0;
					}
				}
			}
		}

		++pointsRead;
	}

	if (reader)
		delete reader;
	reader=0;
	ifs.close();

	return CC_FERR_NO_ERROR;
}
Пример #20
0
CC_FILE_ERROR ObjFilter::saveToFile(ccHObject* entity, QString filename, SaveParameters& parameters)
{
	if (!entity)
		return CC_FERR_BAD_ARGUMENT;

	if (!entity->isKindOf(CC_TYPES::MESH))
	{
		ccLog::Warning("[OBJ] This filter can only save one mesh (optionally with sub-meshes) at a time!");
		return CC_FERR_BAD_ENTITY_TYPE;
	}

	//mesh
	ccGenericMesh* mesh = ccHObjectCaster::ToGenericMesh(entity);
	if (!mesh || mesh->size() == 0)
	{
		ccLog::Warning("[OBJ] Input mesh is empty!");
		return CC_FERR_NO_SAVE;
	}

	//vertices
	ccGenericPointCloud* vertices = mesh->getAssociatedCloud();
	if (!vertices || vertices->size() == 0)
	{
		ccLog::Warning("[OBJ] Input mesh has no vertices?!");
		return CC_FERR_NO_SAVE;
	}
	unsigned nbPoints = vertices->size();

	//try to open file for saving
	QFile file(filename);
	if (!file.open(QFile::Text | QFile::WriteOnly))
		return CC_FERR_WRITING;

	//progress
	ccProgressDialog pdlg(true);
	unsigned numberOfTriangles = mesh->size();
	CCLib::NormalizedProgress nprogress(&pdlg,numberOfTriangles);
	pdlg.setMethodTitle(qPrintable(QString("Saving mesh [%1]").arg(mesh->getName())));
	pdlg.setInfo(qPrintable(QString("Triangles: %1").arg(numberOfTriangles)));
	pdlg.start();
	
	QTextStream stream(&file);
	stream.setRealNumberPrecision(sizeof(PointCoordinateType) == 4 ? 8 : 12);

	stream << "#OBJ Generated by CloudCompare (TELECOM PARISTECH/EDF R&D)" << endl;
	if (file.error() != QFile::NoError)
		return CC_FERR_WRITING;

	for (unsigned i=0; i<nbPoints; ++i)
	{
		const CCVector3* P = vertices->getPoint(i);
		CCVector3d Pglobal = vertices->toGlobal3d<PointCoordinateType>(*P);
		stream << "v " << Pglobal.x << " " << Pglobal.y << " " << Pglobal.z << endl;
		if (file.error() != QFile::NoError)
			return CC_FERR_WRITING;
	}

	//normals
	bool withTriNormals = mesh->hasTriNormals();
	bool withVertNormals = vertices->hasNormals();
	bool withNormals = withTriNormals || withVertNormals;
	if (withNormals)
	{
		//per-triangle normals
		if (withTriNormals)
		{
			NormsIndexesTableType* normsTable = mesh->getTriNormsTable();
			if (normsTable)
			{
				for (unsigned i=0; i<normsTable->currentSize(); ++i)
				{
					const CCVector3& normalVec = ccNormalVectors::GetNormal(normsTable->getValue(i));
					stream << "vn " << normalVec.x << " " << normalVec.y << " " << normalVec.z << endl;
					if (file.error() != QFile::NoError)
						return CC_FERR_WRITING;
				}
			}
			else
			{
				assert(false);
				withTriNormals = false;
			}
		}
		//per-vertices normals
		else //if (withVertNormals)
		{
			for (unsigned i=0; i<nbPoints; ++i)
			{
				const CCVector3& normalVec = vertices->getPointNormal(i);
				stream << "vn " << normalVec.x << " " << normalVec.y << " " << normalVec.z << endl;
				if (file.error() != QFile::NoError)
					return CC_FERR_WRITING;
			}
		}
	}

	//materials
	const ccMaterialSet* materials = mesh->getMaterialSet();
	bool withMaterials = (materials && mesh->hasMaterials());
	if (withMaterials)
	{
		//save mtl file
		QStringList errors;
		QString baseName = QFileInfo(filename).baseName();
		if (materials->saveAsMTL(QFileInfo(filename).absolutePath(),baseName,errors))
		{
			stream << "mtllib " << baseName << ".mtl" << endl;
			if (file.error() != QFile::NoError)
				return CC_FERR_WRITING;
		}
		else
		{
			materials = 0;
			withMaterials = false;
		}

		//display potential 'errors'
		for (int i=0; i<errors.size(); ++i)
		{
			ccLog::Warning(QString("[OBJ][Material file writer] ")+errors[i]);
		}
	}

	//save texture coordinates
	bool withTexCoordinates = withMaterials && mesh->hasPerTriangleTexCoordIndexes();
	if (withTexCoordinates)
	{
		TextureCoordsContainer* texCoords = mesh->getTexCoordinatesTable();
		if (texCoords)
		{
			for (unsigned i=0; i<texCoords->currentSize(); ++i)
			{
				const float* tc = texCoords->getValue(i);
				stream << "vt " << tc[0] << " " << tc[1] << endl;
				if (file.error() != QFile::NoError)
					return CC_FERR_WRITING;
			}
		}
		else
		{
			withTexCoordinates = false;
		}
	}

	ccHObject::Container subMeshes;
	//look for sub-meshes
	mesh->filterChildren(subMeshes,false,CC_TYPES::SUB_MESH);
	//check that the number of facets is the same as the full mesh!
	{
		unsigned faceCount = 0;
		for (ccHObject::Container::const_iterator it = subMeshes.begin(); it != subMeshes.end(); ++it)
			faceCount += static_cast<ccSubMesh*>(*it)->size();

		//if there's no face (i.e. no sub-mesh) or less face than the total mesh, we save the full mesh!
		if (faceCount < mesh->size())
		{
			subMeshes.clear();
			subMeshes.push_back(mesh);
		}
	}

	//mesh or sub-meshes
	unsigned indexShift = 0;
	for (ccHObject::Container::const_iterator it = subMeshes.begin(); it != subMeshes.end(); ++it)
	{
		ccGenericMesh* st = static_cast<ccGenericMesh*>(*it);

		stream << "g " << (st->getName().isNull() ? "mesh" : st->getName()) << endl;
		if (file.error() != QFile::NoError)
			return CC_FERR_WRITING;

		unsigned triNum = st->size();
		st->placeIteratorAtBegining();

		int lastMtlIndex = -1;
		int t1 = -1, t2 = -1, t3 = -1;

		for (unsigned i=0; i<triNum; ++i)
		{
			if (withMaterials)
			{
				int mtlIndex = mesh->getTriangleMtlIndex(indexShift+i);
				if (mtlIndex != lastMtlIndex)
				{
					if (mtlIndex >= 0 && mtlIndex < static_cast<int>(materials->size()))
					{
						ccMaterial::CShared mat = materials->at(mtlIndex);
						stream << "usemtl " << mat->getName() << endl;
					}
					else
					{
						stream << "usemtl " << endl;
					}
					if (file.error() != QFile::NoError)
						return CC_FERR_WRITING;
					lastMtlIndex = mtlIndex;
				}

				if (withTexCoordinates)
				{
					mesh->getTriangleTexCoordinatesIndexes(indexShift+i,t1,t2,t3);
					if (t1 >= 0) ++t1;
					if (t2 >= 0) ++t2;
					if (t3 >= 0) ++t3;
				}
			}

			const CCLib::VerticesIndexes* tsi = st->getNextTriangleVertIndexes();
			//for per-triangle normals
			unsigned i1 = tsi->i1 + 1;
			unsigned i2 = tsi->i2 + 1;
			unsigned i3 = tsi->i3 + 1;

			stream << "f";
			if (withNormals)
			{
				int n1 = static_cast<int>(i1);
				int n2 = static_cast<int>(i2);
				int n3 = static_cast<int>(i3);
				if (withTriNormals)
				{
					st->getTriangleNormalIndexes(i,n1,n2,n3);
					if (n1 >= 0) ++n1;
					if (n2 >= 0) ++n2;
					if (n3 >= 0) ++n3;
				}

				if (withTexCoordinates)
				{
					stream << " " << i1 << "/" << t1 << "/" << n1;
					stream << " " << i2 << "/" << t2 << "/" << n2;
					stream << " " << i3 << "/" << t3 << "/" << n3;
				}
				else
				{
					stream << " " << i1 << "//" << n1;
					stream << " " << i2 << "//" << n2;
					stream << " " << i3 << "//" << n3;
				}
			}
			else
			{
				if (withTexCoordinates)
				{
					stream << " " << i1 << "/" << t1;
					stream << " " << i2 << "/" << t2;
					stream << " " << i3 << "/" << t3;
				}
				else
				{
					stream << " " << i1;
					stream << " " << i2;
					stream << " " << i3;
				}
			}
			stream << endl;

			if (file.error() != QFile::NoError)
				return CC_FERR_WRITING;

			if (!nprogress.oneStep()) //cancel requested
				return CC_FERR_CANCELED_BY_USER;
		}

		stream << "#" << triNum << " faces" << endl;
		if (file.error() != QFile::NoError)
			return CC_FERR_WRITING;

		indexShift += triNum;
	}

	return CC_FERR_NO_ERROR;
}
Пример #21
0
CC_FILE_ERROR MAFilter::saveToFile(ccHObject* entity, const char* filename)
{
	if (!entity || !filename)
        return CC_FERR_BAD_ARGUMENT;

	ccHObject::Container meshes;
	if (entity->isKindOf(CC_MESH))
        meshes.push_back(entity);
    else
        entity->filterChildren(meshes, true, CC_MESH);

    if (meshes.empty())
    {
        ccConsole::Error("No mesh in input selection!");
        return CC_FERR_BAD_ENTITY_TYPE;
    }
    else if (meshes.size()>1)
    {
        ccConsole::Error("Can't save more than one mesh per MA file!");
        return CC_FERR_BAD_ENTITY_TYPE;
    }

    //we extract the (short) filename from the whole path
	QString baseFilename = QFileInfo(filename).fileName();

    //the mesh to save
    ccGenericMesh* theMesh = static_cast<ccGenericMesh*>(meshes[0]);
    //and its vertices
    ccGenericPointCloud* theCloud = theMesh->getAssociatedCloud();

	unsigned numberOfTriangles = theMesh->size();
	unsigned numberOfVertexes = theCloud->size();

	if (numberOfTriangles==0 || numberOfVertexes==0)
	{
        ccConsole::Error("Mesh is empty!");
        return CC_FERR_BAD_ENTITY_TYPE;
	}

	bool hasColors = false;
	if (theCloud->isA(CC_POINT_CLOUD))
	    static_cast<ccPointCloud*>(theCloud)->hasColors();

    //and its scalar field
	/*CCLib::ScalarField* sf = 0;
	if (theCloud->isA(CC_POINT_CLOUD))
	    sf = static_cast<ccPointCloud*>(theCloud)->getCurrentDisplayedScalarField();

    if (!sf)
        ccConsole::Warning("No displayed scalar field! Values will all be 0!\n");

	//*/

    //open ASCII file for writing
	FILE* fp = fopen(filename , "wt");

	if (!fp)
        return CC_FERR_WRITING;

	//progress dialog
	ccProgressDialog pdlg(true); //cancel available
    unsigned palierModifier = (hasColors ? 1 : 0);
	CCLib::NormalizedProgress nprogress(&pdlg,unsigned(float((2+palierModifier)*numberOfTriangles+(3+palierModifier)*numberOfVertexes)));
	pdlg.setMethodTitle("Save MA file");
	char buffer[256];
    sprintf(buffer,"Triangles = %i",numberOfTriangles);
	pdlg.setInfo(buffer);
	pdlg.start();

	//header
	if (fprintf(fp,"//Maya ASCII 7.0 scene\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (fprintf(fp,"//Name: %s\n",qPrintable(baseFilename)) < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (fprintf(fp,"//Last modified: Sat, Mai 10, 2008 00:00:00 PM\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (fprintf(fp,"requires maya \"4.0\";\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (fprintf(fp,"currentUnit -l %s -a degree -t film;\n","centimeter") < 0)
		{fclose(fp);return CC_FERR_WRITING;}


    //for multiple meshes handling (does not work yet)
    unsigned char currentMesh = 0;

	//NOEUD DE TRANSFORMATION
	if (fprintf(fp,"createNode transform -n \"Mesh%i\";\n",currentMesh+1) < 0)
		{fclose(fp);return CC_FERR_WRITING;}

    //NOEUD "PRINCIPAL"
	if (fprintf(fp,"createNode mesh -n \"MeshShape%i\" -p \"Mesh%i\";\n",currentMesh+1,currentMesh+1) < 0)
		{fclose(fp);return CC_FERR_WRITING;}

	if (fprintf(fp,"\tsetAttr -k off \".v\";\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}

	if (fprintf(fp,"\tsetAttr \".uvst[0].uvsn\" -type \"string\" \"map1\";\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (fprintf(fp,"\tsetAttr \".cuvs\" -type \"string\" \"map1\";\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (hasColors)
	{
		if (fprintf(fp,"\tsetAttr \".dcol\" yes;\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}
	}
	if (fprintf(fp,"\tsetAttr \".dcc\" -type \"string\" \"Ambient+Diffuse\";\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (fprintf(fp,"\tsetAttr \".ccls\" -type \"string\" \"colorSet%i\";\n",currentMesh+1) < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (fprintf(fp,"\tsetAttr \".clst[0].clsn\" -type \"string\" \"colorSet%i\";\n",currentMesh+1) < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (hasColors)
	{
		if (fprintf(fp,"\tsetAttr \".ndt\" 0;\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"\tsetAttr \".tgsp\" 1;\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}

		//ON INSERE UN NOEUD "SECONDAIRE"
		if (fprintf(fp,"createNode mesh -n \"polySurfaceShape%i\" -p \"Mesh%i\";\n",currentMesh+1,currentMesh+1) < 0)
			{fclose(fp);return CC_FERR_WRITING;}

		if (fprintf(fp,"\tsetAttr -k off \".v\";\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"\tsetAttr \".io\" yes;\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"\tsetAttr \".uvst[0].uvsn\" -type \"string\" \"map1\";\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"\tsetAttr \".cuvs\" -type \"string\" \"map1\";\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"\tsetAttr \".dcol\" yes;\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"\tsetAttr \".dcc\" -type \"string\" \"Ambient+Diffuse\";\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"\tsetAttr \".ccls\" -type \"string\" \"colorSet%i\";\n",currentMesh+1) < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"\tsetAttr \".clst[0].clsn\" -type \"string\" \"colorSet%i\";\n",currentMesh+1) < 0)
			{fclose(fp);return CC_FERR_WRITING;}
	}

	//ecriture des "vertexes"
	if (fprintf(fp,"\tsetAttr -s %i \".vt[0:%i]\"\n",numberOfVertexes,numberOfVertexes-1) < 0)
		{fclose(fp);return CC_FERR_WRITING;}

	const double* shift = theCloud->getOriginalShift();

	unsigned i;
	for (i=0;i<numberOfVertexes;++i)
	{
		const CCVector3* P = theCloud->getPoint(i);
		if (fprintf(fp,(i+1==numberOfVertexes ? "\t\t%f %f %f;\n" : "\t\t%f %f %f\n"),
				-shift[0]+(double)P->x,
				-shift[2]+(double)P->z,
				shift[1]-(double)P->y) < 0)
			{fclose(fp);return CC_FERR_WRITING;}

		nprogress.oneStep();
	}

	//ectitures des "edges"
	//structure permettant la gestion des indexs uniques des edges
	edge** theEdges = new edge*[numberOfVertexes];
	memset(theEdges,0,sizeof(edge*)*numberOfVertexes);
	unsigned ind[3],a,b;
	int currentEdgeIndex=0,lastEdgeIndexPushed=-1;

	int hard=0; //les arrêtes dans Maya peuvent être "hard" ou "soft" ...

	theMesh->placeIteratorAtBegining();
	for (i=0;i<numberOfTriangles;++i)
	{
		const CCLib::TriangleSummitsIndexes* tsi = theMesh->getNextTriangleIndexes(); //DGM: getNextTriangleIndexes is faster for mesh groups!

		ind[0] = tsi->i1;
		ind[1] = tsi->i2;
		ind[2] = tsi->i3;

		uchar k,l;
		for (k=0;k<3;++k)
		{
			l=(k<2 ? k+1 : 0);
			a = (ind[k]<ind[l] ? ind[k] : ind[l]);
			b = (a==ind[k] ? ind[l] : ind[k]);

			currentEdgeIndex = -1;
			edge* e = theEdges[a];
			while (e)
			{
				if (e->theOtherPoint == b)
				{
					currentEdgeIndex = e->edgeIndex;
					break;
				}
				e = e->nextEdge;
			}

			if (currentEdgeIndex<0) //on cree une nouvelle "edge"
			{
				edge* newEdge = new edge;
				newEdge->nextEdge = NULL;
				newEdge->theOtherPoint = b;
				newEdge->positif = (a==ind[k]);
				//newEdge->edgeIndex = ++lastEdgeIndexPushed; //non ! On n'ecrit pas l'arrête maintenant, donc ce n'est plus vrai
				newEdge->edgeIndex = 0;
				++lastEdgeIndexPushed;
				//currentEdgeIndex = lastEdgeIndexPushed;

				//on doit rajoute le noeud a la fin !!!
				if (theEdges[a])
				{
					e = theEdges[a];
					while (e->nextEdge) e=e->nextEdge;
					e->nextEdge = newEdge;
				}
				else theEdges[a]=newEdge;

				/*if (fprintf(fp,"\n \t\t%i %i %i",a,b,hard) < 0)
					return CC_FERR_WRITING;*/
			}
		}

		nprogress.oneStep();
	}

	//ecriture effective des edges
	unsigned numberOfEdges = unsigned(lastEdgeIndexPushed+1);
	if (fprintf(fp,"\tsetAttr -s %i \".ed[0:%i]\"",numberOfEdges,numberOfEdges-1) < 0)
		{fclose(fp);return CC_FERR_WRITING;}

	lastEdgeIndexPushed=0;
	for (i=0;i<numberOfVertexes;++i)
	{
		if (theEdges[i])
		{
			edge* e = theEdges[i];
			while (e)
			{
				e->edgeIndex = lastEdgeIndexPushed++;
				if (fprintf(fp,"\n \t\t%i %i %i",i,e->theOtherPoint,hard) < 0)
					{fclose(fp);return CC_FERR_WRITING;}
				e=e->nextEdge;
			}
		}

		nprogress.oneStep();
	}

	if (fprintf(fp,";\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}

	//ectitures des "faces"
	if (fprintf(fp,"\tsetAttr -s %i \".fc[0:%i]\" -type \"polyFaces\"\n",numberOfTriangles,numberOfTriangles-1) < 0)
		{fclose(fp);return CC_FERR_WRITING;}

	theMesh->placeIteratorAtBegining();
	for (i=0;i<numberOfTriangles;++i)
	{
		if (fprintf(fp,"\t\tf 3") < 0) {fclose(fp);return CC_FERR_WRITING;}

		CCLib::TriangleSummitsIndexes* tsi = theMesh->getNextTriangleIndexes(); //DGM: getNextTriangleIndexes is faster for mesh groups!
		ind[0] = tsi->i1;
		ind[1] = tsi->i2;
		ind[2] = tsi->i3;

		uchar k,l;
		for (k=0;k<3;++k)
		{
			l=(k<2 ? k+1 : 0);
			a = (ind[k]<ind[l] ? ind[k] : ind[l]);
			b = (a==ind[k] ? ind[l] : ind[k]);

			edge* e = theEdges[a];
			while (e->theOtherPoint != b) e=e->nextEdge;

			if (fprintf(fp," %i",((e->positif && a==ind[k]) || (!e->positif && a==ind[l]) ? e->edgeIndex : -(e->edgeIndex+1))) < 0) {fclose(fp);return CC_FERR_WRITING;}
		}

		if (fprintf(fp,(i+1==numberOfTriangles ? ";\n" : "\n")) < 0) {fclose(fp);return CC_FERR_WRITING;}

		nprogress.oneStep();
	}

	//on libere la memoire
	for (i=0;i<numberOfVertexes;++i)
	{
		if (theEdges[i])
		{
			edge* e = theEdges[i]->nextEdge;
			edge* nextE;
			while (e)
			{
				nextE=e->nextEdge;
				delete e;
				e=nextE;
			}
			delete theEdges[i];
		}

		nprogress.oneStep();
	}

	//cadeaux bonux 2
	if (fprintf(fp,"\tsetAttr \".cd\" -type \"dataPolyComponent\" Index_Data Edge 0 ;\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (fprintf(fp,"\tsetAttr \".ndt\" 0;\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}
	if (fprintf(fp,"\tsetAttr \".tgsp\" 1;\n") < 0)
		{fclose(fp);return CC_FERR_WRITING;}

	//NOEUD DES VERTEX COLORS
	if (hasColors)
	{
	    assert(theCloud->isA(CC_POINT_CLOUD));
        ccPointCloud* pc = static_cast<ccPointCloud*>(theCloud);

		if (fprintf(fp,"createNode polyColorPerVertex -n \"polyColorPerVertex%i\";\n",currentMesh+1) < 0)
			{fclose(fp);return CC_FERR_WRITING;}

		if (fprintf(fp,"\tsetAttr \".uopa\" yes;\n") < 0)
			{fclose(fp);return CC_FERR_WRITING;}

		if (fprintf(fp,"\tsetAttr -s %i \".vclr\";\n",numberOfVertexes) < 0)
			{fclose(fp);return CC_FERR_WRITING;}

		//on construit une structure qui associe chaque vertex aux faces auxquelles elle appartient
		faceIndexes** theFacesIndexes = new faceIndexes*[numberOfVertexes];
		memset(theFacesIndexes,0,sizeof(faceIndexes*)*numberOfVertexes);
		theMesh->placeIteratorAtBegining();
		for (i=0;i<numberOfTriangles;++i)
		{
			CCLib::TriangleSummitsIndexes* tsi = theMesh->getNextTriangleIndexes(); //DGM: getNextTriangleIndexes is faster for mesh groups!
			ind[0] = tsi->i1;
			ind[1] = tsi->i2;
			ind[2] = tsi->i3;

			for (uchar j=0;j<3;++j)
			{
				if (!theFacesIndexes[ind[j]])
				{
					faceIndexes* f = new faceIndexes;
					f->faceIndex = i;
					f->nextFace = NULL;
					theFacesIndexes[ind[j]] = f;
				}
				else
				{
					faceIndexes* f = theFacesIndexes[ind[j]];
					while (f->nextFace) f=f->nextFace;
					f->nextFace = new faceIndexes;
					f->nextFace->faceIndex = i;
					f->nextFace->nextFace = NULL;
				}
			}

			nprogress.oneStep();
		}

		//pour chaque vertex
		float col[3],coef=1.0/float(MAX_COLOR_COMP);
		for (i=0;i<numberOfVertexes;++i)
		{
			const colorType* c = pc->getPointColor(i);
			col[0]=float(c[0])*coef;
			col[1]=float(c[1])*coef;
			col[2]=float(c[2])*coef;

			//on compte le nombre de faces
			int nf = 0;
			faceIndexes* f = theFacesIndexes[i];
			while (f)
			{
				++nf;
				f=f->nextFace;
			}

			if (nf>0)
			{
				if (fprintf(fp,"\tsetAttr -s %i \".vclr[%i].vfcl\";\n",nf,i) < 0)
					{fclose(fp);return CC_FERR_WRITING;}

				faceIndexes *oldf,*f = theFacesIndexes[i];
				while (f)
				{
					if (fprintf(fp,"\tsetAttr \".vclr[%i].vfcl[%i].frgb\" -type \"float3\" %f %f %f;\n",i,f->faceIndex,col[0],col[1],col[2]) < 0)
					{fclose(fp);return CC_FERR_WRITING;}

					oldf = f;
					f=f->nextFace;
					delete oldf;
				}
				theFacesIndexes[i]=NULL;
			}

			nprogress.oneStep();
		}
		delete[] theFacesIndexes;

		if (fprintf(fp,"\tsetAttr \".cn\" -type \"string\" \"colorSet%i\";\n",currentMesh+1) < 0)
			{fclose(fp);return CC_FERR_WRITING;}
	}

	//Maya connections
	if (hasColors)
	{
		if (fprintf(fp,"connectAttr \"polyColorPerVertex%i.out\" \"MeshShape%i.i\";\n",currentMesh+1,currentMesh+1) < 0)
			{fclose(fp);return CC_FERR_WRITING;}
		if (fprintf(fp,"connectAttr \"polySurfaceShape%i.o\" \"polyColorPerVertex%i.ip\";\n",currentMesh+1,currentMesh+1) < 0)
			{fclose(fp);return CC_FERR_WRITING;}
	}
	if (fprintf(fp,"connectAttr \"MeshShape%i.iog\" \":initialShadingGroup.dsm\" -na;\n",currentMesh+1) < 0)
		{fclose(fp);return CC_FERR_WRITING;}

	//fin du fichier
	if (fprintf(fp,"//End of %s\n",qPrintable(baseFilename)) < 0)
		{fclose(fp);return CC_FERR_WRITING;}

	fclose(fp);

	return CC_FERR_NO_ERROR;
}
Пример #22
0
CC_FILE_ERROR PNFilter::loadFile(const char* filename, ccHObject& container, bool alwaysDisplayLoadDialog/*=true*/, bool* coordinatesShiftEnabled/*=0*/, double* coordinatesShift/*=0*/)
{
	//opening file
	QFile in(filename);
	if (!in.open(QIODevice::ReadOnly))
		return CC_FERR_READING;

    //we deduce the points number from the file size
	qint64 fileSize = in.size();
	qint64 singlePointSize = 6*sizeof(float);
	//check that size is ok
	if (fileSize == 0)
		return CC_FERR_NO_LOAD;
	if ((fileSize % singlePointSize) != 0)
		return CC_FERR_MALFORMED_FILE;
	unsigned numberOfPoints = (unsigned) (fileSize  / singlePointSize);

	//progress dialog
	ccProgressDialog pdlg(true); //cancel available
	CCLib::NormalizedProgress nprogress(&pdlg,numberOfPoints);
	pdlg.setMethodTitle("Open PN file");
	pdlg.setInfo(qPrintable(QString("Points: %1").arg(numberOfPoints)));
	pdlg.start();

	ccPointCloud* loadedCloud = 0;
    //if the file is too big, it will be chuncked in multiple parts
	unsigned chunkIndex = 0;
	unsigned fileChunkPos = 0;
	unsigned fileChunkSize = 0;
    //number of points read for the current cloud part
	unsigned pointsRead = 0;
	CC_FILE_ERROR result = CC_FERR_NO_ERROR;

	for (unsigned i=0;i<numberOfPoints;i++)
	{
        //if we reach the max. cloud size limit, we cerate a new chunk
		if (pointsRead == fileChunkPos+fileChunkSize)
		{
			if (loadedCloud)
				container.addChild(loadedCloud);
			fileChunkPos = pointsRead;
			fileChunkSize = std::min<unsigned>(numberOfPoints-pointsRead,CC_MAX_NUMBER_OF_POINTS_PER_CLOUD);
			loadedCloud = new ccPointCloud(QString("unnamed - Cloud #%1").arg(++chunkIndex));
            if (!loadedCloud || !loadedCloud->reserveThePointsTable(fileChunkSize) || !loadedCloud->reserveTheNormsTable())
			{
				result = CC_FERR_NOT_ENOUGH_MEMORY;
				if (loadedCloud)
					delete loadedCloud;
				loadedCloud=0;
				break;
			}
			loadedCloud->showNormals(true);
		}

        //we read the 3 coordinates of the point
		float rBuff[3];
		if (in.read((char*)rBuff,3*sizeof(float))>=0)
		{
		    //conversion to CCVector3
		    CCVector3 P((PointCoordinateType)rBuff[0],
						(PointCoordinateType)rBuff[1],
						(PointCoordinateType)rBuff[2]);
			loadedCloud->addPoint(P);
		}
		else
		{
			result = CC_FERR_READING;
			break;
		}

        //then the 3 components of the normal vector
		if (in.read((char*)rBuff,3*sizeof(float))>=0)
		{
		    //conversion to PointCoordinateType[3]
			PointCoordinateType N[3] = {(PointCoordinateType)rBuff[0],
										(PointCoordinateType)rBuff[1],
										(PointCoordinateType)rBuff[2]};
			loadedCloud->addNorm(N);
		}
		else
		{
			//add fake normal for consistency then break
			loadedCloud->addNorm(s_defaultNorm);
			result = CC_FERR_READING;
			break;
		}

		++pointsRead;

		if (!nprogress.oneStep())
		{
			result = CC_FERR_CANCELED_BY_USER;
			break;
		}
    }

	in.close();

	if (loadedCloud)
	{
		if (loadedCloud->size() < loadedCloud->capacity())
			loadedCloud->resize(loadedCloud->size());
		container.addChild(loadedCloud);
	}

	return result;
}
Пример #23
0
CC_FILE_ERROR AsciiFilter::saveToFile(ccHObject* entity, QString filename, SaveParameters& parameters)
{
	assert(entity && !filename.isEmpty());

	AsciiSaveDlg* saveDialog = GetSaveDialog(parameters.parentWidget);
	assert(saveDialog);

	//if the dialog shouldn't be shown, we'll simply take the default values!
	if (parameters.alwaysDisplaySaveDialog && saveDialog->autoShow() && !saveDialog->exec())
	{
		return CC_FERR_CANCELED_BY_USER;
	}

	if (!entity->isKindOf(CC_TYPES::POINT_CLOUD))
	{
		if (entity->isA(CC_TYPES::HIERARCHY_OBJECT)) //multiple clouds?
		{
			QFileInfo fi(filename);
			QString extension = fi.suffix();
			QString baseName = fi.completeBaseName();
			QString path = fi.path();

			unsigned count = entity->getChildrenNumber();
			//we count the number of clouds first
			unsigned cloudCount = 0;
			{
				for (unsigned i=0; i<count; ++i)
				{
					ccHObject* child = entity->getChild(i);
					if (child->isKindOf(CC_TYPES::POINT_CLOUD))
						++cloudCount;
				}
			}
			
			//we can now create the corresponding file(s)
			if (cloudCount > 1)
			{
				unsigned counter = 0;
				//disable the save dialog so that it doesn't appear again!
				AsciiSaveDlg* saveDialog = GetSaveDialog();
				assert(saveDialog);

				bool autoShow = saveDialog->autoShow();
				saveDialog->setAutoShow(false);

				for (unsigned i=0; i<count; ++i)
				{
					ccHObject* child = entity->getChild(i);
					if (child->isKindOf(CC_TYPES::POINT_CLOUD))
					{
						QString subFilename = path+QString("/");
						subFilename += QString(baseName).replace("cloudname",child->getName(),Qt::CaseInsensitive);
						counter++;
						assert(counter <= cloudCount);
						subFilename += QString("_%1").arg(cloudCount-counter,6,10,QChar('0'));
						if (!extension.isEmpty())
							subFilename += QString(".") + extension;
						
						CC_FILE_ERROR result = saveToFile(entity->getChild(i),subFilename,parameters);
						if (result != CC_FERR_NO_ERROR)
						{
							return result;
						}
						else
						{
							ccLog::Print(QString("[ASCII] Cloud '%1' has been saved in: %2").arg(child->getName()).arg(subFilename));
						}
					}
					else
					{
						ccLog::Warning(QString("[ASCII] Entity '%1' can't be saved this way!").arg(child->getName()));
					}
				}

				//restore previous state
				saveDialog->setAutoShow(autoShow);

				return CC_FERR_NO_ERROR;
			}
		}
		else
		{
			return CC_FERR_BAD_ARGUMENT;
		}
	}

	QFile file(filename);
	if (!file.open(QFile::WriteOnly | QFile::Truncate))
		return CC_FERR_WRITING;
	QTextStream stream(&file);

	ccGenericPointCloud* cloud = ccHObjectCaster::ToGenericPointCloud(entity);

	unsigned numberOfPoints = cloud->size();
	bool writeColors = cloud->hasColors();
	bool writeNorms = cloud->hasNormals();
	std::vector<ccScalarField*> theScalarFields;
	if (cloud->isKindOf(CC_TYPES::POINT_CLOUD))
	{
		ccPointCloud* ccCloud = static_cast<ccPointCloud*>(cloud);
		for (unsigned i=0; i<ccCloud->getNumberOfScalarFields(); ++i)
			theScalarFields.push_back(static_cast<ccScalarField*>(ccCloud->getScalarField(i)));
	}
	bool writeSF = (theScalarFields.size() != 0);

	//progress dialog
	ccProgressDialog pdlg(true);
	CCLib::NormalizedProgress nprogress(&pdlg,numberOfPoints);
	pdlg.setMethodTitle(qPrintable(QString("Saving cloud [%1]").arg(cloud->getName())));
	pdlg.setInfo(qPrintable(QString("Number of points: %1").arg(numberOfPoints)));
	pdlg.start();

	//output precision
	const int s_coordPrecision = saveDialog->coordsPrecision();
	const int s_sfPrecision = saveDialog->sfPrecision(); 
	const int s_nPrecision = 2+sizeof(PointCoordinateType);

	//other parameters
	bool saveColumnsHeader = saveDialog->saveColumnsNamesHeader();
	bool savePointCountHeader = saveDialog->savePointCountHeader();
	bool swapColorAndSFs = saveDialog->swapColorAndSF();
	QChar separator(saveDialog->getSeparator());
	bool saveFloatColors = saveDialog->saveFloatColors();

	if (saveColumnsHeader)
	{
		QString header("//");
		header.append(AsciiHeaderColumns::X());
		header.append(separator);
		header.append(AsciiHeaderColumns::Y());
		header.append(separator);
		header.append(AsciiHeaderColumns::Z());

		if (writeColors && !swapColorAndSFs)
		{
			header.append(separator);
			header.append(saveFloatColors ? AsciiHeaderColumns::Rf() : AsciiHeaderColumns::R());
			header.append(separator);
			header.append(saveFloatColors ? AsciiHeaderColumns::Gf() : AsciiHeaderColumns::G());
			header.append(separator);
			header.append(saveFloatColors ? AsciiHeaderColumns::Bf() : AsciiHeaderColumns::B());
		}

		if (writeSF)
		{
			//add each associated SF name
			for (std::vector<ccScalarField*>::const_iterator it = theScalarFields.begin(); it != theScalarFields.end(); ++it)
			{
				QString sfName((*it)->getName());
				sfName.replace(separator,'_');
				header.append(separator);
				header.append(sfName);
			}
		}

		if (writeColors && swapColorAndSFs)
		{
			header.append(separator);
			header.append(saveFloatColors ? AsciiHeaderColumns::Rf() : AsciiHeaderColumns::R());
			header.append(separator);
			header.append(saveFloatColors ? AsciiHeaderColumns::Gf() : AsciiHeaderColumns::G());
			header.append(separator);
			header.append(saveFloatColors ? AsciiHeaderColumns::Bf() : AsciiHeaderColumns::B());
		}

		if (writeNorms)
		{
			header.append(separator);
			header.append(AsciiHeaderColumns::Nx());
			header.append(separator);
			header.append(AsciiHeaderColumns::Ny());
			header.append(separator);
			header.append(AsciiHeaderColumns::Nz());
		}
		
		stream << header << "\n";
	}

	if (savePointCountHeader)
	{
		stream << QString::number(numberOfPoints) << "\n";
	}

	CC_FILE_ERROR result = CC_FERR_NO_ERROR;
	for (unsigned i=0; i<numberOfPoints; ++i)
	{
		//line for the current point
		QString line;

		//write current point coordinates
		const CCVector3* P = cloud->getPoint(i);
		CCVector3d Pglobal = cloud->toGlobal3d<PointCoordinateType>(*P);
		line.append(QString::number(Pglobal.x,'f',s_coordPrecision));
		line.append(separator);
		line.append(QString::number(Pglobal.y,'f',s_coordPrecision));
		line.append(separator);
		line.append(QString::number(Pglobal.z,'f',s_coordPrecision));

		QString colorLine;
		if (writeColors)
		{
			//add rgb color
			const ColorCompType* col = cloud->getPointColor(i);
			if (saveFloatColors)
			{
				colorLine.append(separator);
				colorLine.append(QString::number(static_cast<double>(col[0])/ccColor::MAX));
				colorLine.append(separator);
				colorLine.append(QString::number(static_cast<double>(col[1])/ccColor::MAX));
				colorLine.append(separator);
				colorLine.append(QString::number(static_cast<double>(col[2])/ccColor::MAX));
			}
			else
			{
				colorLine.append(separator);
				colorLine.append(QString::number(col[0]));
				colorLine.append(separator);
				colorLine.append(QString::number(col[1]));
				colorLine.append(separator);
				colorLine.append(QString::number(col[2]));
			}

			if (!swapColorAndSFs)
				line.append(colorLine);
		}

		if (writeSF)
		{
			//add each associated SF values
			for (std::vector<ccScalarField*>::const_iterator it = theScalarFields.begin(); it != theScalarFields.end(); ++it)
			{
				line.append(separator);
				double sfVal = (*it)->getGlobalShift() + (*it)->getValue(i);
				line.append(QString::number(sfVal,'f',s_sfPrecision));
			}
		}

		if (writeColors && swapColorAndSFs)
			line.append(colorLine);

		if (writeNorms)
		{
			//add normal vector
			const CCVector3& N = cloud->getPointNormal(i);
			line.append(separator);
			line.append(QString::number(N.x,'f',s_nPrecision));
			line.append(separator);
			line.append(QString::number(N.y,'f',s_nPrecision));
			line.append(separator);
			line.append(QString::number(N.z,'f',s_nPrecision));
		}

		stream << line << "\n";

		if (!nprogress.oneStep())
		{
			result = CC_FERR_CANCELED_BY_USER;
			break;
		}
	}

	return result;
}
Пример #24
0
CC_FILE_ERROR PNFilter::saveToFile(ccHObject* entity, const char* filename)
{
	if (!entity || !filename)
        return CC_FERR_BAD_ARGUMENT;

	ccHObject::Container clouds;
	if (entity->isKindOf(CC_POINT_CLOUD))
        clouds.push_back(entity);
    else
        entity->filterChildren(clouds, true, CC_POINT_CLOUD);

    if (clouds.empty())
    {
        ccLog::Error("No point cloud in input selection!");
        return CC_FERR_BAD_ENTITY_TYPE;
    }
    else if (clouds.size()>1)
    {
        ccLog::Error("Can't save more than one cloud per PN file!");
        return CC_FERR_BAD_ENTITY_TYPE;
    }

    //the cloud to save
    ccGenericPointCloud* theCloud = ccHObjectCaster::ToGenericPointCloud(clouds[0]);
	unsigned numberOfPoints = theCloud->size();

	if (numberOfPoints==0)
	{
        ccLog::Error("Cloud is empty!");
        return CC_FERR_BAD_ENTITY_TYPE;
	}

    //open binary file for writing
	QFile out(filename);
	if (!out.open(QIODevice::WriteOnly))
		return CC_FERR_WRITING;

    //Has the cloud been recentered?
	const double* shift = theCloud->getOriginalShift();
	if (fabs(shift[0])+fabs(shift[0])+fabs(shift[0])>0.0)
        ccLog::Warning(QString("[PNFilter::save] Can't recenter cloud '%1' when saving it in a PN file!").arg(theCloud->getName()));

	bool hasNorms = theCloud->hasNormals();
	if (!hasNorms)
        ccLog::Warning(QString("[PNFilter::save] Cloud '%1' has no normal (we will save points with a default normal)!").arg(theCloud->getName()));
	float norm[3] = {(float)s_defaultNorm[0], (float)s_defaultNorm[1], (float)s_defaultNorm[2]};

	//progress dialog
	ccProgressDialog pdlg(true); //cancel available
	CCLib::NormalizedProgress nprogress(&pdlg,numberOfPoints);
	pdlg.setMethodTitle("Save PN file");
	pdlg.setInfo(qPrintable(QString("Points: %1").arg(numberOfPoints)));
	pdlg.start();

	CC_FILE_ERROR result = CC_FERR_NO_ERROR;

	for (unsigned i=0;i<numberOfPoints;i++)
	{
		//write point
		{
			const CCVector3* P = theCloud->getPoint(i);
			
			//conversion to float
			float wBuff[3] = {(float)P->x, (float)P->y, (float)P->z};
			if (out.write((const char*)wBuff,3*sizeof(float))<0)
			{
				result = CC_FERR_WRITING;
				break;
			}
		}
			
		//write normal
		if (hasNorms)
		{
            const PointCoordinateType* N = theCloud->getPointNormal(i);
			//conversion to float
            norm[0] = (float)N[0];
            norm[1] = (float)N[1];
            norm[2] = (float)N[2];
		}
		if (out.write((const char*)norm,3*sizeof(float))<0)
		{
			result = CC_FERR_WRITING;
			break;
		}

		if (!nprogress.oneStep())
		{
			result = CC_FERR_CANCELED_BY_USER;
			break;
		}
	}

	out.close();

	return result;
}
Пример #25
0
CC_FILE_ERROR LASFilter::saveToFile(ccHObject* entity, const char* filename)
{
	if (!entity || !filename)
		return CC_FERR_BAD_ARGUMENT;

	ccHObject::Container clouds;
	if (entity->isKindOf(CC_POINT_CLOUD))
		clouds.push_back(entity);
	else
		entity->filterChildren(clouds, true, CC_POINT_CLOUD);

	if (clouds.empty())
	{
		ccConsole::Error("No point cloud in input selection!");
		return CC_FERR_BAD_ENTITY_TYPE;
	}
	else if (clouds.size()>1)
	{
		ccConsole::Error("Can't save more than one cloud per LAS file!");
		return CC_FERR_BAD_ENTITY_TYPE;
	}

	//the cloud to save
	ccGenericPointCloud* theCloud = static_cast<ccGenericPointCloud*>(clouds[0]);
	unsigned numberOfPoints = theCloud->size();

	if (numberOfPoints==0)
	{
		ccConsole::Error("Cloud is empty!");
		return CC_FERR_BAD_ENTITY_TYPE;
	}

	//colors
	bool hasColor = theCloud->hasColors();

	//additional fields (as scalar fields)
	CCLib::ScalarField* classifSF = 0;
	CCLib::ScalarField* intensitySF = 0;
	CCLib::ScalarField* timeSF = 0;
	CCLib::ScalarField* returnNumberSF = 0;

	if (theCloud->isA(CC_POINT_CLOUD))
	{
		ccPointCloud* pc = static_cast<ccPointCloud*>(theCloud);

		//Classification
		{
			int sfIdx = pc->getScalarFieldIndexByName(CC_LAS_CLASSIFICATION_FIELD_NAME);
			if (sfIdx>=0)
			{
				classifSF = pc->getScalarField(sfIdx);
				assert(classifSF);
				if ((int)classifSF->getMin()<0 || (int)classifSF->getMax()>255) //outbounds unsigned char?
				{
					ccConsole::Warning("[LASFilter] Found a 'Classification' scalar field, but its values outbound LAS specifications (0-255)...");
					classifSF = 0;
				}
			}
		}
		//Classification end

		//intensity (as a scalar field)
		{
			int sfIdx = pc->getScalarFieldIndexByName(CC_SCAN_INTENSITY_FIELD_NAME);
			if (sfIdx>=0)
			{
				intensitySF = pc->getScalarField(sfIdx);
				assert(intensitySF);
				if ((int)intensitySF->getMin()<0 || (int)intensitySF->getMax()>65535) //outbounds unsigned short?
				{
					ccConsole::Warning("[LASFilter] Found a 'Intensity' scalar field, but its values outbound LAS specifications (0-65535)...");
					intensitySF = 0;
				}
			}
		}
		//Intensity end

		//Time (as a scalar field)
		{
			int sfIdx = pc->getScalarFieldIndexByName(CC_SCAN_TIME_FIELD_NAME);
			if (sfIdx>=0)
			{
				timeSF = pc->getScalarField(sfIdx);
				assert(timeSF);
			}
		}
		//Time end

		//Return number (as a scalar field)
		{
			int sfIdx = pc->getScalarFieldIndexByName(CC_SCAN_RETURN_INDEX_FIELD_NAME);
			if (sfIdx>=0)
			{
				returnNumberSF = pc->getScalarField(sfIdx);
				assert(returnNumberSF);
				if ((int)returnNumberSF->getMin()<0 || (int)returnNumberSF->getMax()>7) //outbounds 3 bits?
				{
					ccConsole::Warning("[LASFilter] Found a 'Return number' scalar field, but its values outbound LAS specifications (0-7)...");
					returnNumberSF = 0;
				}
			}
		}
		//Return number end
	}

	//open binary file for writing
	std::ofstream ofs;
	ofs.open(filename, std::ios::out | std::ios::binary);

	if (ofs.fail())
		return CC_FERR_WRITING;

	const double* shift = theCloud->getOriginalShift();

	liblas::Writer* writer = 0;
	try
	{
		liblas::Header header;

		//LAZ support based on extension!
		if (QFileInfo(filename).suffix().toUpper() == "LAZ")
		{
			header.SetCompressed(true);
		}

		//header.SetDataFormatId(liblas::ePointFormat3);
		ccBBox bBox = theCloud->getBB();
		if (bBox.isValid())
		{
			header.SetMin(-shift[0]+(double)bBox.minCorner().x,-shift[1]+(double)bBox.minCorner().y,-shift[2]+(double)bBox.minCorner().z);
			header.SetMax(-shift[0]+(double)bBox.maxCorner().x,-shift[1]+(double)bBox.maxCorner().y,-shift[2]+(double)bBox.maxCorner().z);
			CCVector3 diag = bBox.getDiagVec();

			//Set offset & scale, as points will be stored as boost::int32_t values (between 0 and 4294967296)
			//int_value = (double_value-offset)/scale
			header.SetOffset(-shift[0]+(double)bBox.minCorner().x,-shift[1]+(double)bBox.minCorner().y,-shift[2]+(double)bBox.minCorner().z);
			header.SetScale(1.0e-9*std::max<double>(diag.x,ZERO_TOLERANCE), //result must fit in 32bits?!
				1.0e-9*std::max<double>(diag.y,ZERO_TOLERANCE),
				1.0e-9*std::max<double>(diag.z,ZERO_TOLERANCE));
		}
		header.SetPointRecordsCount(numberOfPoints);
		//header.SetDataFormatId(Header::ePointFormat1);

		writer = new liblas::Writer(ofs, header);
	}
	catch (...)
	{
		return CC_FERR_WRITING;
	}

	//progress dialog
	ccProgressDialog pdlg(true); //cancel available
	CCLib::NormalizedProgress nprogress(&pdlg,numberOfPoints);
	pdlg.setMethodTitle("Save LAS file");
	char buffer[256];
	sprintf(buffer,"Points: %i",numberOfPoints);
	pdlg.setInfo(buffer);
	pdlg.start();

	//liblas::Point point(boost::shared_ptr<liblas::Header>(new liblas::Header(writer->GetHeader())));
	liblas::Point point(&writer->GetHeader());

	for (unsigned i=0; i<numberOfPoints; i++)
	{
		const CCVector3* P = theCloud->getPoint(i);
		{
			double x=-shift[0]+(double)P->x;
			double y=-shift[1]+(double)P->y;
			double z=-shift[2]+(double)P->z;
			point.SetCoordinates(x, y, z);
		}
		if (hasColor)
		{
			const colorType* rgb = theCloud->getPointColor(i);
			point.SetColor(liblas::Color(rgb[0]<<8,rgb[1]<<8,rgb[2]<<8)); //DGM: LAS colors are stored on 16 bits!
		}

		if (classifSF)
		{
			liblas::Classification classif;
			classif.SetClass((boost::uint32_t)classifSF->getValue(i));
			point.SetClassification(classif);
		}

		if (intensitySF)
		{
			point.SetIntensity((boost::uint16_t)intensitySF->getValue(i));
		}

		if (timeSF)
		{
			point.SetTime((double)timeSF->getValue(i));
		}

		if (returnNumberSF)
		{
			point.SetReturnNumber((boost::uint16_t)returnNumberSF->getValue(i));
			point.SetNumberOfReturns((boost::uint16_t)returnNumberSF->getMax());
		}

		writer->WritePoint(point);

		if (!nprogress.oneStep())
			break;
	}

	delete writer;
	//ofs.close();

	return CC_FERR_NO_ERROR;
}
Пример #26
0
CC_FILE_ERROR PNFilter::saveToFile(ccHObject* entity, QString filename)
{
	if (!entity || filename.isEmpty())
		return CC_FERR_BAD_ARGUMENT;

	//the cloud to save
	ccGenericPointCloud* theCloud = ccHObjectCaster::ToGenericPointCloud(entity);
	if (!theCloud)
	{
		ccLog::Warning("[PN] This filter can only save one cloud at a time!");
		return CC_FERR_BAD_ENTITY_TYPE;
	}
	unsigned numberOfPoints = theCloud->size();

	if (numberOfPoints == 0)
	{
		ccLog::Warning("[PN] Input cloud is empty!");
		return CC_FERR_NO_SAVE;
	}

	//open binary file for writing
	QFile out(filename);
	if (!out.open(QIODevice::WriteOnly))
		return CC_FERR_WRITING;

	//Has the cloud been recentered?
	if (theCloud->isShifted())
		ccLog::Warning(QString("[PNFilter::save] Can't recenter or rescale cloud '%1' when saving it in a PN file!").arg(theCloud->getName()));

	bool hasNorms = theCloud->hasNormals();
	if (!hasNorms)
		ccLog::Warning(QString("[PNFilter::save] Cloud '%1' has no normal (we will save points with a default normal)!").arg(theCloud->getName()));
	float norm[3] = {(float)s_defaultNorm[0], (float)s_defaultNorm[1], (float)s_defaultNorm[2]};

	//progress dialog
	ccProgressDialog pdlg(true); //cancel available
	CCLib::NormalizedProgress nprogress(&pdlg,numberOfPoints);
	pdlg.setMethodTitle("Save PN file");
	pdlg.setInfo(qPrintable(QString("Points: %1").arg(numberOfPoints)));
	pdlg.start();

	CC_FILE_ERROR result = CC_FERR_NO_ERROR;

	for (unsigned i=0; i<numberOfPoints; i++)
	{
		//write point
		{
			const CCVector3* P = theCloud->getPoint(i);
			
			//conversion to float
			Vector3Tpl<float> Pfloat = Vector3Tpl<float>::fromArray(P->u);
			if (out.write(reinterpret_cast<const char*>(Pfloat.u),3*sizeof(float)) < 0)
			{
				result = CC_FERR_WRITING;
				break;
			}
		}
			
		//write normal
		if (hasNorms)
		{
			const CCVector3& N = theCloud->getPointNormal(i);
			//conversion to float
			norm[0] = static_cast<float>(N.x);
			norm[1] = static_cast<float>(N.y);
			norm[2] = static_cast<float>(N.z);
		}
		if (out.write(reinterpret_cast<const char*>(norm),3*sizeof(float)) < 0)
		{
			result = CC_FERR_WRITING;
			break;
		}

		if (!nprogress.oneStep())
		{
			result = CC_FERR_CANCELED_BY_USER;
			break;
		}
	}

	out.close();

	return result;
}
Пример #27
0
CC_FILE_ERROR BinFilter::loadFileV2(QFile& in, ccHObject& container)
{
	assert(in.isOpen());

	uint32_t binVersion = 20;
	if (in.read((char*)&binVersion,4)<0)
		return CC_FERR_READING;

	if (binVersion<20) //should be superior to 2.0!
		return CC_FERR_MALFORMED_FILE;

	ccLog::Print(QString("[BIN] Version %1.%2").arg(binVersion/10).arg(binVersion%10));

	ccProgressDialog pdlg(true);
	pdlg.setMethodTitle(qPrintable(QString("Open Bin file (V%1.%2)").arg(binVersion/10).arg(binVersion%10)));

	//we keep track of the last unique ID before load
	unsigned lastUniqueIDBeforeLoad = ccObject::GetLastUniqueID();

	//we read first entity type
	unsigned classID=0;
	if (!ccObject::ReadClassIDFromFile(classID, in, binVersion))
		return CC_FERR_CONSOLE_ERROR;

	ccHObject* root = ccHObject::New(classID);
	if (!root)
		return CC_FERR_MALFORMED_FILE;

	if (!root->fromFile(in,binVersion))
	{
		//DGM: can't delete it, too dangerous (bad pointers ;)
		//delete root;
		return CC_FERR_CONSOLE_ERROR;
	}

	CC_FILE_ERROR result = CC_FERR_NO_ERROR;

	//re-link objects
	ccHObject::Container toCheck;
	toCheck.push_back(root);
	while (!toCheck.empty())
	{
		ccHObject* currentObject = toCheck.back();
		toCheck.pop_back();

		assert(currentObject);
		//we check objects that have links to other entities (meshes, polylines, etc.)
		if (currentObject->isKindOf(CC_MESH))
		{
			ccGenericMesh* mesh = static_cast<ccGenericMesh*>(currentObject);
			//vertices
			//special case: if the parent is a mesh group, then the job has already be done once and for all!
			if (!mesh->getParent() || !mesh->getParent()->isA(CC_MESH_GROUP))
			{
				intptr_t cloudID = (intptr_t)mesh->getAssociatedCloud();
				if (cloudID>0)
				{
					ccHObject* cloud = root->find(cloudID);
					if (cloud && cloud->isKindOf(CC_POINT_CLOUD))
						mesh->setAssociatedCloud(static_cast<ccGenericPointCloud*>(cloud));
					else
					{
						//we have a problem here ;)
						mesh->setAssociatedCloud(0);
						if (mesh->getMaterialSet())
							mesh->setMaterialSet(0,false);
						//DGM: can't delete it, too dangerous (bad pointers ;)
						//delete root;
						ccLog::Warning(QString("[BinFilter::loadFileV2] Couldn't find vertices (ID=%1) for mesh '%2' in the file!").arg(cloudID).arg(mesh->getName()));
						return CC_FERR_MALFORMED_FILE;
					}
				}
			}
			//materials
			intptr_t matSetID = (intptr_t)mesh->getMaterialSet();
			if (matSetID>0)
			{
				ccHObject* materials = root->find(matSetID);
				if (materials && materials->isA(CC_MATERIAL_SET))
					mesh->setMaterialSet(static_cast<ccMaterialSet*>(materials),false);
				else
				{
					//we have a (less severe) problem here ;)
					mesh->setMaterialSet(0,false);
					mesh->showMaterials(false);
					ccLog::Warning(QString("[BinFilter::loadFileV2] Couldn't find shared materials set (ID=%1) for mesh '%2' in the file!").arg(matSetID).arg(mesh->getName()));
					result = CC_FERR_BROKEN_DEPENDENCY_ERROR;
				}
			}
			//per-triangle normals
			intptr_t triNormsTableID = (intptr_t)mesh->getTriNormsTable();
			if (triNormsTableID>0)
			{
				ccHObject* triNormsTable = root->find(triNormsTableID);
				if (triNormsTable && triNormsTable->isA(CC_NORMAL_INDEXES_ARRAY))
					mesh->setTriNormsTable(static_cast<NormsIndexesTableType*>(triNormsTable),false);
				else
				{
					//we have a (less severe) problem here ;)
					mesh->setTriNormsTable(0,false);
					mesh->showTriNorms(false);
					ccLog::Warning(QString("[BinFilter::loadFileV2] Couldn't find shared normals (ID=%1) for mesh '%2' in the file!").arg(matSetID).arg(mesh->getName()));
					result = CC_FERR_BROKEN_DEPENDENCY_ERROR;
				}
			}
			//per-triangle texture coordinates
			intptr_t texCoordArrayID = (intptr_t)mesh->getTexCoordinatesTable();
			if (texCoordArrayID>0)
			{
				ccHObject* texCoordsTable = root->find(texCoordArrayID);
				if (texCoordsTable && texCoordsTable->isA(CC_TEX_COORDS_ARRAY))
					mesh->setTexCoordinatesTable(static_cast<TextureCoordsContainer*>(texCoordsTable),false);
				else
				{
					//we have a (less severe) problem here ;)
					mesh->setTexCoordinatesTable(0,false);
					ccLog::Warning(QString("[BinFilter::loadFileV2] Couldn't find shared texture coordinates (ID=%1) for mesh '%2' in the file!").arg(matSetID).arg(mesh->getName()));
					result = CC_FERR_BROKEN_DEPENDENCY_ERROR;
				}
			}
		}
		else if (currentObject->isKindOf(CC_POLY_LINE))
		{
			ccPolyline* poly = static_cast<ccPolyline*>(currentObject);
			intptr_t cloudID = (intptr_t)poly->getAssociatedCloud();
			ccHObject* cloud = root->find(cloudID);
			if (cloud && cloud->isKindOf(CC_POINT_CLOUD))
				poly->setAssociatedCloud(static_cast<ccGenericPointCloud*>(cloud));
			else
			{
				//we have a problem here ;)
				poly->setAssociatedCloud(0);
				//DGM: can't delete it, too dangerous (bad pointers ;)
				//delete root;
				ccLog::Warning(QString("[BinFilter::loadFileV2] Couldn't find vertices (ID=%1) for polyline '%2' in the file!").arg(cloudID).arg(poly->getName()));
				return CC_FERR_MALFORMED_FILE;
			}
		}
		else if (currentObject->isA(CC_2D_LABEL))
		{
			cc2DLabel* label = static_cast<cc2DLabel*>(currentObject);
			std::vector<cc2DLabel::PickedPoint> correctedPickedPoints;
			//we must check all label 'points'!
			for (unsigned i=0;i<label->size();++i)
			{
				const cc2DLabel::PickedPoint& pp = label->getPoint(i);
				intptr_t cloudID = (intptr_t)pp.cloud;
				ccHObject* cloud = root->find(cloudID);
				if (cloud && cloud->isKindOf(CC_POINT_CLOUD))
				{
					ccGenericPointCloud* genCloud = static_cast<ccGenericPointCloud*>(cloud);
					assert(genCloud->size()>pp.index);
					correctedPickedPoints.push_back(cc2DLabel::PickedPoint(genCloud,pp.index));
				}
				else
				{
					//we have a problem here ;)
					ccLog::Warning(QString("[BinFilter::loadFileV2] Couldn't find cloud (ID=%1) associated to label '%2' in the file!").arg(cloudID).arg(label->getName()));
					if (label->getParent())
						label->getParent()->removeChild(label);
					if (!label->getFlagState(CC_FATHER_DEPENDANT))
					{
						//DGM: can't delete it, too dangerous (bad pointers ;)
						//delete label;
					}
					label=0;
					break;
				}
			}

			if (label) //correct label data
			{
				assert(correctedPickedPoints.size() == label->size());
				bool visible = label->isVisible();
				QString originalName(label->getRawName());
				label->clear();
				for (unsigned i=0;i<correctedPickedPoints.size();++i)
					label->addPoint(correctedPickedPoints[i].cloud,correctedPickedPoints[i].index);
				label->setVisible(visible);
				label->setName(originalName);
			}
		}

		for (unsigned i=0;i<currentObject->getChildrenNumber();++i)
			toCheck.push_back(currentObject->getChild(i));
	}

	//update 'unique IDs'
	toCheck.push_back(root);
	while (!toCheck.empty())
	{
		ccHObject* currentObject = toCheck.back();
		toCheck.pop_back();

		currentObject->setUniqueID(lastUniqueIDBeforeLoad+currentObject->getUniqueID());

		for (unsigned i=0;i<currentObject->getChildrenNumber();++i)
			toCheck.push_back(currentObject->getChild(i));
	}

	if (root->isA(CC_HIERARCHY_OBJECT))
	{
		//transfer children to container
		root->transferChildren(container,true);
	}
	else
	{
		container.addChild(root);
	}

	return result;
}
Пример #28
0
CC_FILE_ERROR SoiFilter::loadFile(QString filename, ccHObject& container, LoadParameters& parameters)
{
	//open the file
	FILE *fp = fopen(qPrintable(filename), "rt");
	if (!fp)
		return CC_FERR_READING;

	std::string line;
	line.resize(MAX_ASCII_FILE_LINE_LENGTH);
	unsigned nbScansTotal = 0;
	unsigned nbPointsTotal = 0;

	//we read the first line
	char* eof = fgets ((char*)line.c_str(), MAX_ASCII_FILE_LINE_LENGTH , fp);
	char* pEnd;

	//header
	while ((strcmp((char*)line.substr(0,4).c_str(),"#CC#") != 0)&&(eof != NULL))
	{
		if (strcmp(line.substr(0,4).c_str(),"#NP#")==0)
		{
			std::string numPoints (line,4,line.size()-4);
			nbPointsTotal=strtol(numPoints.c_str(),&pEnd,0);
			//ccLog::Print("[SoiFilter::loadFile] Total number of points: %i",nbPointsTotal);
		}
		else if (strcmp(line.substr(0,4).c_str(),"#NS#")==0)
		{
			std::string numScans (line,4,line.size()-4);
			nbScansTotal=strtol(numScans.c_str(),&pEnd,0);
			//ccLog::Print("[SoiFilter::loadFile] Total number of scans: %i",nbScansTotal);
		}

		eof = fgets ((char*)line.c_str(), MAX_ASCII_FILE_LINE_LENGTH , fp);
	}

	if ((nbScansTotal == 0)||(nbPointsTotal == 0))
	{
		ccLog::Warning("[SoiFilter::loadFile] No points or scans defined in this file!");
		fclose(fp);
		return CC_FERR_NO_LOAD;
	}

	//Progress dialog
	ccProgressDialog pdlg(false); //cancel is not supported
	pdlg.setMethodTitle("Open SOI file");
	char buffer[256];
	sprintf(buffer,"%u scans / %u points\n",nbScansTotal,nbPointsTotal);
	CCLib::NormalizedProgress nprogress(&pdlg,nbPointsTotal);
	pdlg.setInfo(buffer);
	pdlg.start();

	//Scan by scan
	for (unsigned k=0; k<nbScansTotal; k++)
	{
		char* eof = fgets ((char*)line.c_str(), MAX_ASCII_FILE_LINE_LENGTH , fp);

		//we only look for points (we ignore the rest)
		while ((strcmp(line.substr(0,4).c_str(),"#pt#")!=0)&&(eof != NULL))
			eof = fgets ((char*)line.c_str(), MAX_ASCII_FILE_LINE_LENGTH , fp);

		unsigned nbOfPoints = 0;

		if (strcmp(line.substr(0,4).c_str(),"#pt#")==0)
		{
			std::string numPoints(line,4,line.size()-4);
			nbOfPoints = strtol(numPoints.c_str(),&pEnd,0);
			//ccLog::Print("[SoiFilter::loadFile] Scan %i - points: %i",k+1,nbOfPoints);
		}
		else
		{
			ccLog::Warning("[SoiFilter::loadFile] Can't find marker '#pt#'!");
			fclose(fp);
			return CC_FERR_WRONG_FILE_TYPE;
		}
		
		if (nbOfPoints == 0)
		{
			ccLog::Warning("[SoiFilter::loadFile] Scan #%i is empty!",k);
			continue;
		}

		//Creation de la liste de points
		QString name = QString("unnamed - Scan #%1").arg(k);

		ccPointCloud* loadedCloud = new ccPointCloud(name);
		if ( !loadedCloud->reserveThePointsTable(nbOfPoints) || !loadedCloud->reserveTheRGBTable() )
		{
			fclose(fp);
			delete loadedCloud;
			return CC_FERR_NOT_ENOUGH_MEMORY;
		}
		loadedCloud->showColors(true);

		//we can read points now
		for (unsigned i=0; i<nbOfPoints; i++)
		{
			float P[3];
			int c = 0;
			fscanf(fp,"%f %f %f %i",P,P+1,P+2,&c);

			loadedCloud->addPoint(CCVector3::fromArray(P));
			loadedCloud->addGreyColor(static_cast<colorType>(c<<3)); //<<2 ? <<3 ? we lack some info. here ...

			nprogress.oneStep();
		}

		container.addChild(loadedCloud);
	}

	fclose(fp);

	return CC_FERR_NO_ERROR;
}
Пример #29
0
CC_FILE_ERROR BinFilter::LoadFileV1(QFile& in, ccHObject& container, unsigned nbScansTotal, const LoadParameters& parameters)
{
	ccLog::Print("[BIN] Version 1.0");

	if (nbScansTotal > 99)
	{
		if (QMessageBox::question(0, QString("Oups"), QString("Hum, do you really expect %1 point clouds?").arg(nbScansTotal), QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
			return CC_FERR_WRONG_FILE_TYPE;
	}
	else if (nbScansTotal == 0)
	{
		return CC_FERR_NO_LOAD;
	}

	ccProgressDialog pdlg(true, parameters.parentWidget);
	pdlg.setMethodTitle(QObject::tr("Open Bin file (old style)"));

	for (unsigned k=0; k<nbScansTotal; k++)
	{
		HeaderFlags header;
		unsigned nbOfPoints = 0;
		if (ReadEntityHeader(in, nbOfPoints, header) < 0)
		{
			return CC_FERR_READING;
		}

		//Console::print("[BinFilter::loadModelFromBinaryFile] Entity %i : %i points, color=%i, norms=%i, dists=%i\n",k,nbOfPoints,color,norms,distances);

		if (nbOfPoints == 0)
		{
			//Console::print("[BinFilter::loadModelFromBinaryFile] rien a faire !\n");
			continue;
		}

		//progress for this cloud
		CCLib::NormalizedProgress nprogress(&pdlg, nbOfPoints);
		if (parameters.alwaysDisplayLoadDialog)
		{
			pdlg.reset();
			pdlg.setInfo(QObject::tr("cloud %1/%2 (%3 points)").arg(k + 1).arg(nbScansTotal).arg(nbOfPoints));
			pdlg.start();
			QApplication::processEvents();
		}

		//Cloud name
		char cloudName[256] = "unnamed";
		if (header.name)
		{
			for (int i=0; i<256; ++i)
			{
				if (in.read(cloudName+i,1) < 0)
				{
					//Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the cloud name!\n");
					return CC_FERR_READING;
				}
				if (cloudName[i] == 0)
				{
					break;
				}
			}
			//we force the end of the name in case it is too long!
			cloudName[255] = 0;
		}
		else
		{
			sprintf(cloudName,"unnamed - Cloud #%u",k);
		}

		//Cloud name
		char sfName[1024] = "unnamed";
		if (header.sfName)
		{
			for (int i=0; i<1024; ++i)
			{
				if (in.read(sfName+i,1) < 0)
				{
					//Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the cloud name!\n");
					return CC_FERR_READING;
				}
				if (sfName[i] == 0)
					break;
			}
			//we force the end of the name in case it is too long!
			sfName[1023] = 0;
		}
		else
		{
			strcpy(sfName,"Loaded scalar field");
		}
		
		//Creation
		ccPointCloud* loadedCloud = new ccPointCloud(cloudName);
		if (!loadedCloud)
			return CC_FERR_NOT_ENOUGH_MEMORY;

		unsigned fileChunkPos = 0;
		unsigned fileChunkSize = std::min(nbOfPoints,CC_MAX_NUMBER_OF_POINTS_PER_CLOUD);

		loadedCloud->reserveThePointsTable(fileChunkSize);
		if (header.colors)
		{
			loadedCloud->reserveTheRGBTable();
			loadedCloud->showColors(true);
		}
		if (header.normals)
		{
			loadedCloud->reserveTheNormsTable();
			loadedCloud->showNormals(true);
		}
		if (header.scalarField)
			loadedCloud->enableScalarField();

		unsigned lineRead = 0;
		int parts = 0;

		const ScalarType FORMER_HIDDEN_POINTS = (ScalarType)-1.0;

		//lecture du fichier
		for (unsigned i=0; i<nbOfPoints; ++i)
		{
			if (lineRead == fileChunkPos+fileChunkSize)
			{
				if (header.scalarField)
					loadedCloud->getCurrentInScalarField()->computeMinAndMax();

				container.addChild(loadedCloud);
				fileChunkPos = lineRead;
				fileChunkSize = std::min(nbOfPoints-lineRead,CC_MAX_NUMBER_OF_POINTS_PER_CLOUD);
				char partName[64];
				++parts;
				sprintf(partName,"%s.part_%i",cloudName,parts);
				loadedCloud = new ccPointCloud(partName);
				loadedCloud->reserveThePointsTable(fileChunkSize);

				if (header.colors)
				{
					loadedCloud->reserveTheRGBTable();
					loadedCloud->showColors(true);
				}
				if (header.normals)
				{
					loadedCloud->reserveTheNormsTable();
					loadedCloud->showNormals(true);
				}
				if (header.scalarField)
					loadedCloud->enableScalarField();
			}

			float Pf[3];
			if (in.read((char*)Pf,sizeof(float)*3) < 0)
			{
				//Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the %ith entity point !\n",k);
				return CC_FERR_READING;
			}
			loadedCloud->addPoint(CCVector3::fromArray(Pf));

			if (header.colors)
			{
				unsigned char C[3];
				if (in.read((char*)C,sizeof(ColorCompType)*3) < 0)
				{
					//Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the %ith entity colors !\n",k);
					return CC_FERR_READING;
				}
				loadedCloud->addRGBColor(C);
			}

			if (header.normals)
			{
				CCVector3 N;
				if (in.read((char*)N.u,sizeof(float)*3) < 0)
				{
					//Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the %ith entity norms !\n",k);
					return CC_FERR_READING;
				}
				loadedCloud->addNorm(N);
			}

			if (header.scalarField)
			{
				double D;
				if (in.read((char*)&D,sizeof(double)) < 0)
				{
					//Console::print("[BinFilter::loadModelFromBinaryFile] Error reading the %ith entity distance!\n",k);
					return CC_FERR_READING;
				}
				ScalarType d = static_cast<ScalarType>(D);
				loadedCloud->setPointScalarValue(i,d);
			}

			lineRead++;

			if (parameters.alwaysDisplayLoadDialog && !nprogress.oneStep())
			{
				loadedCloud->resize(i+1-fileChunkPos);
				k=nbScansTotal;
				i=nbOfPoints;
			}
		}

		if (parameters.alwaysDisplayLoadDialog)
		{
			pdlg.stop();
			QApplication::processEvents();
		}

		if (header.scalarField)
		{
			CCLib::ScalarField* sf = loadedCloud->getCurrentInScalarField();
			assert(sf);
			sf->setName(sfName);

			//replace HIDDEN_VALUES by NAN_VALUES
			for (unsigned i=0; i<sf->currentSize(); ++i)
			{
				if (sf->getValue(i) == FORMER_HIDDEN_POINTS)
					sf->setValue(i,NAN_VALUE);
			}
			sf->computeMinAndMax();

			loadedCloud->setCurrentDisplayedScalarField(loadedCloud->getCurrentInScalarFieldIndex());
			loadedCloud->showSF(true);
		}

		container.addChild(loadedCloud);
	}

	return CC_FERR_NO_ERROR;
}
Пример #30
0
CC_FILE_ERROR PVFilter::loadFile(QString filename, ccHObject& container, LoadParameters& parameters)
{
	//opening file
	QFile in(filename);
	if (!in.open(QIODevice::ReadOnly))
		return CC_FERR_READING;

	//we deduce the points number from the file size
	qint64 fileSize = in.size();
	qint64 singlePointSize = 4*sizeof(float);
	//check that size is ok
	if (fileSize == 0)
		return CC_FERR_NO_LOAD;
	if ((fileSize % singlePointSize) != 0)
		return CC_FERR_MALFORMED_FILE;
	unsigned numberOfPoints = static_cast<unsigned>(fileSize  / singlePointSize);

	//progress dialog
	ccProgressDialog pdlg(true); //cancel available
	CCLib::NormalizedProgress nprogress(&pdlg,numberOfPoints);
	pdlg.setMethodTitle("Open PV file");
	pdlg.setInfo(qPrintable(QString("Points: %1").arg(numberOfPoints)));
	pdlg.start();

	ccPointCloud* loadedCloud = 0;
	//if the file is too big, it will be chuncked in multiple parts
	unsigned chunkIndex = 0;
	unsigned fileChunkPos = 0;
	unsigned fileChunkSize = 0;
	//number of points read for the current cloud part
	unsigned pointsRead = 0;
	CC_FILE_ERROR result = CC_FERR_NO_ERROR;

	for (unsigned i=0;i<numberOfPoints;i++)
	{
		//if we reach the max. cloud size limit, we cerate a new chunk
		if (pointsRead == fileChunkPos+fileChunkSize)
		{
			if (loadedCloud)
			{
				int sfIdx = loadedCloud->getCurrentInScalarFieldIndex();
				if (sfIdx>=0)
				{
					CCLib::ScalarField* sf = loadedCloud->getScalarField(sfIdx);
					sf->computeMinAndMax();
					loadedCloud->setCurrentDisplayedScalarField(sfIdx);
					loadedCloud->showSF(true);
				}
				container.addChild(loadedCloud);
			}
			fileChunkPos = pointsRead;
			fileChunkSize = std::min<unsigned>(numberOfPoints-pointsRead,CC_MAX_NUMBER_OF_POINTS_PER_CLOUD);
			loadedCloud = new ccPointCloud(QString("unnamed - Cloud #%1").arg(++chunkIndex));
			if (!loadedCloud || !loadedCloud->reserveThePointsTable(fileChunkSize) || !loadedCloud->enableScalarField())
			{
				result = CC_FERR_NOT_ENOUGH_MEMORY;
				if (loadedCloud)
					delete loadedCloud;
				loadedCloud=0;
				break;
			}
		}

		//we read the 3 coordinates of the point
		float rBuff[3];
		if (in.read((char*)rBuff,3*sizeof(float))>=0)
		{
			//conversion to CCVector3
			CCVector3 P((PointCoordinateType)rBuff[0],
						(PointCoordinateType)rBuff[1],
						(PointCoordinateType)rBuff[2]);
			loadedCloud->addPoint(P);
		}
		else
		{
			result = CC_FERR_READING;
			break;
		}

		//then the scalar value
		if (in.read((char*)rBuff,sizeof(float))>=0)
		{
			loadedCloud->setPointScalarValue(pointsRead,(ScalarType)rBuff[0]);
		}
		else
		{
			//add fake scalar value for consistency then break
			loadedCloud->setPointScalarValue(pointsRead,0);
			result = CC_FERR_READING;
			break;
		}

		++pointsRead;

		if (!nprogress.oneStep())
		{
			result = CC_FERR_CANCELED_BY_USER;
			break;
		}
	}

	in.close();

	if (loadedCloud)
	{
		if (loadedCloud->size() < loadedCloud->capacity())
			loadedCloud->resize(loadedCloud->size());
		int sfIdx = loadedCloud->getCurrentInScalarFieldIndex();
		if (sfIdx>=0)
		{
			CCLib::ScalarField* sf = loadedCloud->getScalarField(sfIdx);
			sf->computeMinAndMax();
			loadedCloud->setCurrentDisplayedScalarField(sfIdx);
			loadedCloud->showSF(true);
		}
		container.addChild(loadedCloud);
	}

	return result;
}