BOOL Ccoin_lookerDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	auto g_CoinList = LoadCoinList(GetAppDir());
	if (g_CoinList.size())
	{
		int idx = 0;
		for (auto it = g_CoinList.begin(); it != g_CoinList.end(); ++it)
		{
			shared_ptr<ICoinOption> pCoinOption = *it;
			shared_ptr<IUserContext> pWork = create_coin_work(pCoinOption);
			boost::thread th(boost::bind(&IUserContext::load_db, pWork));
			shared_ptr<CRecvDialog> pDlg(new CRecvDialog(pWork, &m_tab1));
			pDlg->Create(CRecvDialog::IDD);
			CRect r;
			pDlg->GetWindowRect(r);
			r.top += 18;
			r.left += 14;
			pDlg->MoveWindow(r);
			m_tab1.InsertItem(m_tab1.GetItemCount(), pCoinOption->prev_name.c_str());
			m_vlist.push_back(pDlg);
		}
		m_vlist[0]->ShowWindow(SW_SHOW);
	}

	
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}
Esempio n. 2
0
void DomainListView::changePressed()
{
    QListViewItem *index = domainSpecificLV->currentItem();
    if ( index == 0 )
    {
        KMessageBox::information( 0, i18n("You must first select a policy to be changed." ) );
        return;
    }

    Policies *pol = domainPolicies[index];
    // This must be copied because the policy dialog is allowed to change
    // the data even if the changes are rejected in the end.
    Policies *pol_copy = copyPolicies(pol);

    PolicyDialog pDlg( pol_copy, this );
    pDlg.setDisableEdit( true, index->text(0) );
    setupPolicyDlg(ChangeButton,pDlg,pol_copy);
    if( pDlg.exec() )
    {
        pol_copy->setDomain(pDlg.domain());
        domainPolicies[index] = pol_copy;
	pol_copy = pol;
        index->setText(0, pDlg.domain() );
        index->setText(1, pDlg.featureEnabledPolicyText());
        emit changed(true);
    }
    delete pol_copy;
}
Esempio n. 3
0
void ccNormalComputationDlg::autoEstimateRadius()
{
	if (!m_cloud)
	{
		assert(false);
		return;
	}

	if (!m_cloud->getOctree())
	{
		ccProgressDialog pDlg(true, this);
		if (!m_cloud->computeOctree(&pDlg))
		{
			ccLog::Error(QString("Could not compute octree for cloud '%1'").arg(m_cloud->getName()));
			autoRadiusToolButton->setVisible(false);
			return;
		}
	}

	PointCoordinateType radius = ccNormalVectors::GuessBestRadius(m_cloud, m_cloud->getOctree().data());
	if (radius > 0)
	{
		radiusDoubleSpinBox->setValue(radius);
	}
}
Esempio n. 4
0
CC_FILE_ERROR BinFilter::loadFile(const char* filename, ccHObject& container, bool alwaysDisplayLoadDialog/*=true*/, bool* coordinatesShiftEnabled/*=0*/, double* coordinatesShift/*=0*/)
{
	ccLog::Print("[BIN] Opening file '%s'...",filename);


	//opening file
	QFile in(filename);
	if (!in.open(QIODevice::ReadOnly))
		return CC_FERR_READING;

	uint32_t firstBytes = 0;
	if (in.read((char*)&firstBytes,4)<0)
		return CC_FERR_READING;
	bool v1 = (strncmp((char*)&firstBytes,"CCB2",4) != 0);

	if (v1)
	{
		return LoadFileV1(in,container,static_cast<unsigned>(firstBytes),alwaysDisplayLoadDialog); //firstBytes == number of scans for V1 files!
	}
	else
	{
		if (alwaysDisplayLoadDialog)
		{
			QProgressDialog pDlg(QString("Loading: %1").arg(QFileInfo(filename).fileName()),QString(),0,0/*static_cast<int>(in.size())*/);
			pDlg.setWindowTitle("BIN file");
			pDlg.show();

			//concurrent call in a separate thread
			s_file = &in;
			s_container = &container;

			QFuture<CC_FILE_ERROR> future = QtConcurrent::run(_LoadFileV2);

			while (!future.isFinished())
			{
	#if defined(CC_WINDOWS)
				::Sleep(500);
	#else
				usleep(500 * 1000);
	#endif
				if (alwaysDisplayLoadDialog)
				{
					pDlg.setValue(pDlg.value()+1);
					//pDlg.setValue(static_cast<int>(in.pos())); //DGM: in fact, the file reading part is just half of the work!
					QApplication::processEvents();
				}
			}
	
			s_file = 0;
			s_container = 0;

			return future.result();
		}
		else
		{
			return BinFilter::LoadFileV2(in,container);
		}
	}
}
Esempio n. 5
0
void CVideoRecvTestDlg::OnBnClickedButton3()
{
	if(*m_hDevice == NULL)
	{
		return;
	}
	CSetVideoEnahnceFlagDlg pDlg(m_hDevice, this);
	pDlg.DoModal();
}
Esempio n. 6
0
void CDialogMediaControl::OnBnClickedButtonMediaFullscreen()
{
	m_bFullScreen = !m_bFullScreen;
	CRect newWindowSize;
	CWnd *pDlg(m_pDialogPreviewMedia->GetParent());
	if (m_bFullScreen) {
		// Save current rect
		pDlg->GetWindowRect(&m_WindowSize);
		GetDesktopWindow()->GetWindowRect(&newWindowSize);
	}
	else {
		newWindowSize = m_WindowSize;
	}
	pDlg->SetWindowPos(&wndTopMost, newWindowSize.left, newWindowSize.top,
		newWindowSize.right-newWindowSize.left, newWindowSize.bottom-newWindowSize.top, 0);
		
}
Esempio n. 7
0
void DomainListView::addPressed()
{
//    JavaPolicies pol_copy(m_pConfig,m_groupname,false);
    Policies *pol = createPolicies();
    pol->defaults();
    PolicyDialog pDlg(pol, this);
    setupPolicyDlg(AddButton,pDlg,pol);
    if( pDlg.exec() ) {
        QListViewItem* index = new QListViewItem( domainSpecificLV, pDlg.domain(),
                                                  pDlg.featureEnabledPolicyText() );
	pol->setDomain(pDlg.domain());
        domainPolicies.insert(index, pol);
        domainSpecificLV->setCurrentItem( index );
        emit changed(true);
    } else {
        delete pol;
    }
    updateButton();
}
Esempio n. 8
0
CC_FILE_ERROR BinFilter::saveToFile(ccHObject* root, const char* filename)
{
	if (!root || !filename)
		return CC_FERR_BAD_ARGUMENT;

	QFile out(filename);
	if (!out.open(QIODevice::WriteOnly))
		return CC_FERR_WRITING;

	QProgressDialog pDlg(QString("Please wait... saving in progress"),QString(),0,0);
	pDlg.setWindowTitle("BIN file");
	pDlg.setModal(true);
	pDlg.show();

	//concurrent call
	s_file = &out;
	s_container = root;

	QFuture<CC_FILE_ERROR> future = QtConcurrent::run(_SaveFileV2);

	while (!future.isFinished())
	{
#if defined(CC_WINDOWS)
		::Sleep(500);
#else
        usleep(500 * 1000);
#endif
		pDlg.setValue(pDlg.value()+1);
		QApplication::processEvents();
	}
	
	s_file = 0;
	s_container = 0;

	CC_FILE_ERROR result = future.result();

	if (result == CC_FERR_NO_ERROR)
		ccLog::Print("[BIN] File %s saved successfully",filename);

	return result;
}
Esempio n. 9
0
CC_FILE_ERROR BinFilter::saveToFile(ccHObject* root, QString filename, SaveParameters& parameters)
{
	if (!root || filename.isNull())
		return CC_FERR_BAD_ARGUMENT;

	QFile out(filename);
	if (!out.open(QIODevice::WriteOnly))
		return CC_FERR_WRITING;

	ccProgressDialog pDlg(false, parameters.parentWidget);
	pDlg.setMethodTitle(QObject::tr("BIN file"));
	pDlg.setInfo(QObject::tr("Please wait... saving in progress"));
	pDlg.setRange(0, 0);
	pDlg.setModal(true);
	pDlg.show();

	//concurrent call
	s_file = &out;
	s_container = root;

	QFuture<CC_FILE_ERROR> future = QtConcurrent::run(_SaveFileV2);

	while (!future.isFinished())
	{
#if defined(CC_WINDOWS)
		::Sleep(500);
#else
		usleep(500 * 1000);
#endif
		pDlg.setValue(pDlg.value()+1);
		QApplication::processEvents();
	}
	
	s_file = 0;
	s_container = 0;

	CC_FILE_ERROR result = future.result();

	return result;
}
Esempio n. 10
0
BOOL CMainDlg::TestPrinter(LPTSTR printer)
{
    HANDLE p;
    PRINTER_INFO_2 *pInfo;
    DWORD need = 0;

    if (!::OpenPrinter(printer, &p, NULL))
        return FALSE;

    ::GetPrinter(p, 2, NULL, 0, &need);

    if (!need)
        return FALSE;

    pInfo = (PRINTER_INFO_2 *) new BYTE[need];

    ::GetPrinter(p, 2, (LPBYTE) pInfo, need, &need);

    CPInfoDlg pDlg(pInfo);
    pDlg.DoModal();
    delete pInfo;
    return TRUE;
}
Esempio n. 11
0
void ccAlignDlg::estimateDelta()
{
    unsigned i, nb;
    float meanDensity, meanSqrDensity, dev, value;
    ccProgressDialog pDlg(false,this);

    CCLib::ReferenceCloud *sampledData = getSampledData();
    //we have to work on a copy of the cloud in order to prevent the algorithms from modifying the original cloud.
    CCLib::ChunkedPointCloud* cloud = new CCLib::ChunkedPointCloud();
    cloud->reserve(sampledData->size());
    for(i=0; i<sampledData->size(); i++)
        cloud->addPoint(*sampledData->getPoint(i));
    cloud->enableScalarField();

    CCLib::GeometricalAnalysisTools::computeLocalDensity(cloud, &pDlg);
    nb = 0;
    meanDensity = 0.;
    meanSqrDensity = 0.;
    for(i=0; i<cloud->size(); i++)
    {
        value = cloud->getPointScalarValue(i);
        if(value > ZERO_TOLERANCE)
        {
            value = 1/value;
            meanDensity += value;
            meanSqrDensity += value*value;
            nb++;
        }
    }
    meanDensity /= (float)nb;
    meanSqrDensity /= (float)nb;
    dev = meanSqrDensity-(meanDensity*meanDensity);

    delta->setValue(meanDensity+dev);
    delete sampledData;
    delete cloud;
}
Esempio n. 12
0
CC_FILE_ERROR PNFilter::loadFile(const 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 = 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 = static_cast<unsigned>(fileSize  / singlePointSize);

	//progress dialog
	QScopedPointer<ccProgressDialog> pDlg(0);
	if (parameters.parentWidget)
	{
		pDlg.reset(new ccProgressDialog(true, parameters.parentWidget)); //cancel available
		pDlg->setMethodTitle(QObject::tr("Open PN file"));
		pDlg->setInfo(QObject::tr("Points: %L1").arg( numberOfPoints ));
		pDlg->start();
	}
	CCLib::NormalizedProgress nprogress(pDlg.data(), numberOfPoints);

	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 = CCVector3::fromArray(rBuff);
			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)
		{
			loadedCloud->addNorm(CCVector3::fromArray(rBuff));
		}
		else
		{
			//add fake normal for consistency then break
			loadedCloud->addNorm(s_defaultNorm);
			result = CC_FERR_READING;
			break;
		}

		++pointsRead;

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

	in.close();

	if (loadedCloud)
	{
		loadedCloud->shrinkToFit();
		container.addChild(loadedCloud);
	}

	return result;
}
Esempio n. 13
0
CC_FILE_ERROR PNFilter::saveToFile(ccHObject* entity, const QString& filename, const SaveParameters& parameters)
{
	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] = {	static_cast<float>(s_defaultNorm.x),
						static_cast<float>(s_defaultNorm.y),
						static_cast<float>(s_defaultNorm.z) };

	//progress dialog
	QScopedPointer<ccProgressDialog> pDlg(0);
	if (pDlg)
	{
		pDlg.reset(new ccProgressDialog(true, parameters.parentWidget)); //cancel available
		pDlg->setMethodTitle(QObject::tr("Save PN file"));
		pDlg->setInfo(QObject::tr("Points: %L1").arg( numberOfPoints ));
		pDlg->start();
	}
	CCLib::NormalizedProgress nprogress(pDlg.data(), numberOfPoints);

	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
			CCVector3f Pfloat = CCVector3f::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 (pDlg && !nprogress.oneStep())
		{
			result = CC_FERR_CANCELED_BY_USER;
			break;
		}
	}

	out.close();

	return result;
}
Esempio n. 14
0
bool ccRegistrationTools::ICP(	ccHObject* data,
								ccHObject* model,
								ccGLMatrix& transMat,
								double &finalScale,
								double& finalRMS,
								unsigned& finalPointCount,
								double minRMSDecrease,
								unsigned maxIterationCount,
								unsigned randomSamplingLimit,
								bool removeFarthestPoints,
								CCLib::ICPRegistrationTools::CONVERGENCE_TYPE method,
								bool adjustScale,
								double finalOverlapRatio/*=1.0*/,
								bool useDataSFAsWeights/*=false*/,
								bool useModelSFAsWeights/*=false*/,
								int filters/*=CCLib::ICPRegistrationTools::SKIP_NONE*/,
								int maxThreadCount/*=0*/,
								QWidget* parent/*=0*/)
{
	//progress bar
	ccProgressDialog pDlg(false, parent);

	Garbage<CCLib::GenericIndexedCloudPersist> cloudGarbage;

	//if the 'model' entity is a mesh, we need to sample points on it
	CCLib::GenericIndexedCloudPersist* modelCloud = 0;
	ccGenericMesh* modelMesh = 0;
	if (model->isKindOf(CC_TYPES::MESH))
	{
		modelMesh = ccHObjectCaster::ToGenericMesh(model);
		modelCloud = modelMesh->getAssociatedCloud();
	}
	else
	{
		modelCloud = ccHObjectCaster::ToGenericPointCloud(model);
	}

	//if the 'data' entity is a mesh, we need to sample points on it
	CCLib::GenericIndexedCloudPersist* dataCloud = 0;
	if (data->isKindOf(CC_TYPES::MESH))
	{
		dataCloud = CCLib::MeshSamplingTools::samplePointsOnMesh(ccHObjectCaster::ToGenericMesh(data), s_defaultSampledPointsOnDataMesh, &pDlg);
		if (!dataCloud)
		{
			ccLog::Error("[ICP] Failed to sample points on 'data' mesh!");
			return false;
		}
		cloudGarbage.add(dataCloud);
	}
	else
	{
		dataCloud = ccHObjectCaster::ToGenericPointCloud(data);
	}

	//we activate a temporary scalar field for registration distances computation
	CCLib::ScalarField* dataDisplayedSF = 0;
	int oldDataSfIdx = -1, dataSfIdx = -1;

	//if the 'data' entity is a real ccPointCloud, we can even create a proper temporary SF for registration distances
	if (data->isA(CC_TYPES::POINT_CLOUD))
	{
		ccPointCloud* pc = static_cast<ccPointCloud*>(data);
		dataDisplayedSF = pc->getCurrentDisplayedScalarField();
		oldDataSfIdx = pc->getCurrentInScalarFieldIndex();
		dataSfIdx = pc->getScalarFieldIndexByName(REGISTRATION_DISTS_SF);
		if (dataSfIdx < 0)
			dataSfIdx = pc->addScalarField(REGISTRATION_DISTS_SF);
		if (dataSfIdx >= 0)
			pc->setCurrentScalarField(dataSfIdx);
		else
		{
			ccLog::Error("[ICP] Couldn't create temporary scalar field! Not enough memory?");
			return false;
		}
	}
	else
	{
		if (!dataCloud->enableScalarField())
		{
			ccLog::Error("[ICP] Couldn't create temporary scalar field! Not enough memory?");
			return false;
		}
	}

	//add a 'safety' margin to input ratio
	static double s_overlapMarginRatio = 0.2;
	finalOverlapRatio = std::max(finalOverlapRatio, 0.01); //1% minimum
	//do we need to reduce the input point cloud (so as to be close
	//to the theoretical number of overlapping points - but not too
	//low so as we are not registered yet ;)
	if (finalOverlapRatio < 1.0 - s_overlapMarginRatio)
	{
		//DGM we can now use 'approximate' distances as SAITO algorithm is exact (but with a coarse resolution)
		//level = 7 if < 1.000.000
		//level = 8 if < 10.000.000
		//level = 9 if > 10.000.000
		int gridLevel = static_cast<int>(floor(log10(static_cast<double>(std::max(dataCloud->size(), modelCloud->size()))))) + 2;
			gridLevel = std::min(std::max(gridLevel,7),9);
		int result = -1;
		if (modelMesh)
		{
			CCLib::DistanceComputationTools::Cloud2MeshDistanceComputationParams c2mParams;
			c2mParams.octreeLevel = gridLevel;
			c2mParams.maxSearchDist = 0;
			c2mParams.useDistanceMap = true,
			c2mParams.signedDistances = false;
			c2mParams.flipNormals = false;
			c2mParams.multiThread = false;
			result = CCLib::DistanceComputationTools::computeCloud2MeshDistance(dataCloud, modelMesh, c2mParams, &pDlg);
		}
		else
		{
			result = CCLib::DistanceComputationTools::computeApproxCloud2CloudDistance(	dataCloud,
																						modelCloud,
																						gridLevel,
																						-1,
																						&pDlg);
		}

		if (result < 0)
		{
			ccLog::Error("Failed to determine the max (overlap) distance (not enough memory?)");
			return false;
		}

		//determine the max distance that (roughly) corresponds to the input overlap ratio
		ScalarType maxSearchDist = 0;
		{
			unsigned count = dataCloud->size();
			std::vector<ScalarType> distances;
			try
			{
				distances.resize(count);
			}
			catch (const std::bad_alloc&)
			{
				ccLog::Error("Not enough memory!");
				return false;
			}
			for (unsigned i=0; i<count; ++i)
			{
				distances[i] = dataCloud->getPointScalarValue(i);
			}
			SortAlgo(distances.begin(), distances.end());
			//now look for the max value at 'finalOverlapRatio+margin' percent
			maxSearchDist = distances[static_cast<unsigned>(std::max(1.0,count*(finalOverlapRatio+s_overlapMarginRatio)))-1];
		}

		//evntually select the points with distance below 'maxSearchDist'
		//(should roughly correspond to 'finalOverlapRatio + margin' percent)
		{
			CCLib::ReferenceCloud* refCloud = new CCLib::ReferenceCloud(dataCloud);
			cloudGarbage.add(refCloud);
			unsigned countBefore = dataCloud->size();
			unsigned baseIncrement = static_cast<unsigned>(std::max(100.0,countBefore*finalOverlapRatio*0.05));
			for (unsigned i=0; i<countBefore; ++i)
			{
				if (dataCloud->getPointScalarValue(i) <= maxSearchDist)
				{
					if (	refCloud->size() == refCloud->capacity()
						&&	!refCloud->reserve(refCloud->size() + baseIncrement) )
					{
						ccLog::Error("Not enough memory!");
						return false;
					}
					refCloud->addPointIndex(i);
				}
			}
			refCloud->resize(refCloud->size());
			dataCloud = refCloud;

			unsigned countAfter = dataCloud->size();
			double keptRatio = static_cast<double>(countAfter)/countBefore;
			ccLog::Print(QString("[ICP][Partial overlap] Selecting %1 points out of %2 (%3%) for registration").arg(countAfter).arg(countBefore).arg(static_cast<int>(100*keptRatio)));

			//update the relative 'final overlap' ratio
			finalOverlapRatio /= keptRatio;
		}
	}

	//weights
	CCLib::ScalarField* modelWeights = 0;
	CCLib::ScalarField* dataWeights = 0;
	{
		if (!modelMesh && useModelSFAsWeights)
		{
			if (modelCloud == dynamic_cast<CCLib::GenericIndexedCloudPersist*>(model) && model->isA(CC_TYPES::POINT_CLOUD))
			{
				ccPointCloud* pc = static_cast<ccPointCloud*>(model);
				modelWeights = pc->getCurrentDisplayedScalarField();
				if (!modelWeights)
					ccLog::Warning("[ICP] 'useDataSFAsWeights' is true but model has no displayed scalar field!");
			}
			else
			{
				ccLog::Warning("[ICP] 'useDataSFAsWeights' is true but only point clouds scalar fields can be used as weights!");
			}
		}

		if (useDataSFAsWeights)
		{
			if (!dataDisplayedSF)
			{
				if (dataCloud == (CCLib::GenericIndexedCloudPersist*)data && data->isA(CC_TYPES::POINT_CLOUD))
					ccLog::Warning("[ICP] 'useDataSFAsWeights' is true but data has no displayed scalar field!");
				else
					ccLog::Warning("[ICP] 'useDataSFAsWeights' is true but inly point clouds scalar fields can be used as weights!");
			}
			else
				dataWeights = dataDisplayedSF;
		}
	}

	CCLib::ICPRegistrationTools::RESULT_TYPE result;
	CCLib::PointProjectionTools::Transformation transform;
	CCLib::ICPRegistrationTools::Parameters params;
	{
		params.convType = method;
		params.minRMSDecrease = minRMSDecrease;
		params.nbMaxIterations = maxIterationCount;
		params.adjustScale = adjustScale;
		params.filterOutFarthestPoints = removeFarthestPoints;
		params.samplingLimit = randomSamplingLimit;
		params.finalOverlapRatio = finalOverlapRatio;
		params.modelWeights = modelWeights;
		params.dataWeights = dataWeights;
		params.transformationFilters = filters;
		params.maxThreadCount = maxThreadCount;
	}

	result = CCLib::ICPRegistrationTools::Register(	modelCloud,
													modelMesh,
													dataCloud,
													params,
													transform,
													finalRMS,
													finalPointCount,
													static_cast<CCLib::GenericProgressCallback*>(&pDlg));

	if (result >= CCLib::ICPRegistrationTools::ICP_ERROR)
	{
		ccLog::Error("Registration failed: an error occurred (code %i)",result);
	}
	else if (result == CCLib::ICPRegistrationTools::ICP_APPLY_TRANSFO)
	{
		transMat = FromCCLibMatrix<PointCoordinateType,float>(transform.R, transform.T, transform.s);
		finalScale = transform.s;
	}

	//remove temporary SF (if any)
	if (dataSfIdx >= 0)
	{
		assert(data->isA(CC_TYPES::POINT_CLOUD));
		ccPointCloud* pc = static_cast<ccPointCloud*>(data);
		pc->setCurrentScalarField(oldDataSfIdx);
		pc->deleteScalarField(dataSfIdx);
		dataSfIdx = -1;
	}

	return (result < CCLib::ICPRegistrationTools::ICP_ERROR);
}
Esempio n. 15
0
void ConnectionManager::addClient()
{
    NewProtocol pDlg(this);
    if (pDlg.exec())
        fill();
}
tbool CKSXML_Read_Project::Read_Project_From_Koblo(std::string sProject )
{
	// store project name
	std::string sProject_Name = gpApplication->Project_Name();
	
	// clean project
	Reset_Project();
	
	// clean parser
	Prepare_For_XML();
	
	// read xml file
	tchar* pszBuff = NULL;
	tint32 iOutLen = 0;
	ine::IINetUtil::GetWebFile(NULL, "koblo.com", sProject.c_str(), &iOutLen, &pszBuff);
	

	if ((pszBuff) && (iOutLen > 0)) {
		
		// parse XML file in to TinyXml object tree
		mpTinyXMLDoc->Parse(pszBuff);
		
		printf(pszBuff);
		
		// pass the TinyXML DOM in to the DAW data structure
		//Pass_The_Project_Tag( mpTinyXMLDoc );
		
		
		
		if(mbOpen_Dialog){
			// get the project name from the xml file
			if (!Get_Project_Name_From_XML( mpTinyXMLDoc ) )
				return false;
		
			tchar pszDefaultFolder[1024];
			gpApplication->GetDefaultProjectFolder(pszDefaultFolder);
			
			// get default folder
			tchar pszDefault_Folder[1024];
			gpApplication->GetDefaultProjectFolder(pszDefault_Folder);
			
			//std::string sProject_Name = gpApplication->Online_Project_Name();
			
			// open new project dialog
			tchar pszProject_Folder[1024];
			CAutoDelete<ge::ISaveAsDialog> pDlg(ge::ISaveAsDialog::Create());

			// Don't browse into OS X bundles (special kind of folders)
			pDlg->SetBundleBehaviour(1);

			pDlg->DoDialog(pszProject_Folder, pszDefault_Folder, "", "", msTemp_Online_Project_Name.c_str() );
			std::string sProject_Folder = pszProject_Folder;
			
			// user canceled operation
			if (pszProject_Folder[0] == 0){
				// User cancelled - clean
				Reset_Project();
				Prepare_For_XML();
			}
			// continue
			else {
				// now pass the xml file
				Pass_The_Project_Tag( mpTinyXMLDoc );
				
				// update path's and names for files and folders
				gpApplication->Update_Project_Name(sProject_Folder);

			//	tbool bExists = IFile::Exists(sProject.c_str() , &bIsFolder);
				
				// create new folders for the project
				gpApplication->Create_Folders();
					
				// create a new project file
				gpApplication->Create_Project_File();
				
				// save project 
				gpApplication->Write_XML_File_To_Disk(pszBuff);
				
				// prepare samples for download and decompression
				Prepare_Samples();
				
				// download takes
				Download_Takes();
				
				// decompress takes // How can samples be decompressed before they are downloaded?
				Decompress_Takes();
				
				

			}
		}
		else{
			
			// now pass the xml file
			Pass_The_Project_Tag( mpTinyXMLDoc );

			// restore project name
			gpApplication->Project_Name(sProject_Name);
			
			// save project to disk
			gpApplication->Write_XML_File_To_Disk(pszBuff);
			
			// prepare samples for download and decompression
			Prepare_Samples();
						
			// decompress takes
			Decompress_Takes();

			// download takes
			Download_Takes();
		}
			
			
	}
	else {
	// loading failed reload file from disk if any
		
	}
	ine::IINetUtil::ReleaseBuffer(&pszBuff);
	return true;
	
	

}
Esempio n. 17
0
void COldVideoRecvTestDlg::OnBnClickedButton3()
{
	COldSetVideoEnahnceFlagDlg pDlg(this);
	pDlg.DoModal();
}
Esempio n. 18
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,
															bool showLabelsIn2D/*=false*/)
{
	//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
	QScopedPointer<ccProgressDialog> pDlg(0);
	if (parameters.parentWidget)
	{
		pDlg.reset(new ccProgressDialog(true, parameters.parentWidget));
		pDlg->setMethodTitle(QObject::tr("Open ASCII file [%1]").arg(filename));
		pDlg->setInfo(QObject::tr("Approximate number of points: %1").arg(approximateNumberOfLines));
		pDlg->start();
	}
	CCLib::NormalizedProgress nprogress(pDlg.data(), approximateNumberOfLines);

	//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
			if (pDlg)
			{
				nprogress.scale(approximateNumberOfLines, 100, true);
				pDlg->setInfo(QObject::tr("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) //fake loop for easy break
		{
			//read the point coordinates
			bool lineIsCorrupted = true;
			for (int step = 0; step < 1; ++step) //fake loop for easy break
			{
				bool ok = true;
				if (cloudDesc.xCoordIndex >= 0)
				{
					P.x = parts[cloudDesc.xCoordIndex].toDouble(&ok);
					if (!ok)
					{
						break;
					}
				}
				if (cloudDesc.yCoordIndex >= 0)
				{
					P.y = parts[cloudDesc.yCoordIndex].toDouble(&ok);
					if (!ok)
					{
						break;
					}
				}
				if (cloudDesc.zCoordIndex >= 0)
				{
					P.z = parts[cloudDesc.zCoordIndex].toDouble(&ok);
					if (!ok)
					{
						break;
					}
				}

				lineIsCorrupted = false;
			}

			if (lineIsCorrupted)
			{
				ccLog::Warning("[AsciiFilter::Load] Line %i is corrupted (non numerical value found)", linesRead);
				continue;
			}

			//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);
			}
Esempio n. 19
0
void qRansacSD::doAction()
{
	assert(m_app);
	if (!m_app)
		return;

	const ccHObject::Container& selectedEntities = m_app->getSelectedEntities();
	size_t selNum = selectedEntities.size();
    if (selNum!=1)
	{
		m_app->dispToConsole("Select only one cloud!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
		return;
	}

    ccHObject* ent = selectedEntities[0];
	assert(ent);
	if (!ent || !ent->isA(CC_POINT_CLOUD))
	{
		m_app->dispToConsole("Select a real point cloud!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
		return;
	}

    ccPointCloud* pc = static_cast<ccPointCloud*>(ent);

	//input cloud
	size_t count = (size_t)pc->size();
	bool hasNorms = pc->hasNormals();
    PointCoordinateType bbMin[3],bbMax[3];
    pc->getBoundingBox(bbMin,bbMax);
	const CCVector3d& globalShift = pc->getGlobalShift();
	double globalScale = pc->getGlobalScale();

    //Convert CC point cloud to RANSAC_SD type
	PointCloud cloud;
	{
		try
		{
			cloud.reserve(count);
		}
		catch(...)
		{
			m_app->dispToConsole("Not enough memory!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
			return;
		}

		//default point & normal
		Point Pt;
		Pt.normal[0] = 0.0;
		Pt.normal[1] = 0.0;
		Pt.normal[2] = 0.0;
		for (unsigned i=0;i<(unsigned)count;++i)
		{
			const CCVector3* P = pc->getPoint(i);
			Pt.pos[0] = static_cast<float>(P->x);
			Pt.pos[1] = static_cast<float>(P->y);
			Pt.pos[2] = static_cast<float>(P->z);
			if (hasNorms)
			{
				const PointCoordinateType* N = pc->getPointNormal(i);
				Pt.normal[0] = static_cast<float>(N[0]);
				Pt.normal[1] = static_cast<float>(N[1]);
				Pt.normal[2] = static_cast<float>(N[2]);
			}
			cloud.push_back(Pt);
		}
		
		//manually set bounding box!
		Vec3f cbbMin,cbbMax;
		cbbMin[0] = static_cast<float>(bbMin[0]);
		cbbMin[1] = static_cast<float>(bbMin[1]);
		cbbMin[2] = static_cast<float>(bbMin[2]);
		cbbMax[0] = static_cast<float>(bbMax[0]);
		cbbMax[1] = static_cast<float>(bbMax[1]);
		cbbMax[2] = static_cast<float>(bbMax[2]);
		cloud.setBBox(cbbMin,cbbMax);
	}

    //cloud scale (useful for setting several parameters
	const float scale = cloud.getScale();

	//init dialog with default values
	ccRansacSDDlg rsdDlg(m_app->getMainWindow());
	rsdDlg.epsilonDoubleSpinBox->setValue(.01f * scale);		// set distance threshold to .01f of bounding box width
																// NOTE: Internally the distance threshold is taken as 3 * ransacOptions.m_epsilon!!!
	rsdDlg.bitmapEpsilonDoubleSpinBox->setValue(.02f * scale);	// set bitmap resolution to .02f of bounding box width
																// NOTE: This threshold is NOT multiplied internally!
	rsdDlg.supportPointsSpinBox->setValue(s_supportPoints);
	rsdDlg.normThreshDoubleSpinBox->setValue(s_normThresh);
	rsdDlg.probaDoubleSpinBox->setValue(s_proba);
	rsdDlg.planeCheckBox->setChecked(s_primEnabled[0]);
	rsdDlg.sphereCheckBox->setChecked(s_primEnabled[1]);
	rsdDlg.cylinderCheckBox->setChecked(s_primEnabled[2]);
	rsdDlg.coneCheckBox->setChecked(s_primEnabled[3]);
	rsdDlg.torusCheckBox->setChecked(s_primEnabled[4]);

	if (!rsdDlg.exec())
		return;

	//for parameters persistence
	{
		s_supportPoints = rsdDlg.supportPointsSpinBox->value();
		s_normThresh = rsdDlg.normThreshDoubleSpinBox->value();
		s_proba = rsdDlg.probaDoubleSpinBox->value();

		//consistency check
		{
			unsigned char primCount = 0;
			for (unsigned char k=0;k<5;++k)
				primCount += (unsigned)s_primEnabled[k];
			if (primCount==0)
			{
				m_app->dispToConsole("No primitive type selected!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
				return;
			}
		}

		s_primEnabled[0] = rsdDlg.planeCheckBox->isChecked();
		s_primEnabled[1] = rsdDlg.sphereCheckBox->isChecked();
		s_primEnabled[2] = rsdDlg.cylinderCheckBox->isChecked();
		s_primEnabled[3] = rsdDlg.coneCheckBox->isChecked();
		s_primEnabled[4] = rsdDlg.torusCheckBox->isChecked();
	}

	//import parameters from dialog
	RansacShapeDetector::Options ransacOptions;
	{
		ransacOptions.m_epsilon			= static_cast<float>(rsdDlg.epsilonDoubleSpinBox->value());
		ransacOptions.m_bitmapEpsilon	= static_cast<float>(rsdDlg.bitmapEpsilonDoubleSpinBox->value());
		ransacOptions.m_normalThresh	= static_cast<float>(rsdDlg.normThreshDoubleSpinBox->value());
		ransacOptions.m_probability		= static_cast<float>(rsdDlg.probaDoubleSpinBox->value());
		ransacOptions.m_minSupport		= static_cast<unsigned>(rsdDlg.supportPointsSpinBox->value());
	}

	if (!hasNorms)
	{
		QProgressDialog pDlg("Computing normals (please wait)",QString(),0,0,m_app->getMainWindow());
		pDlg.setWindowTitle("Ransac Shape Detection");
		pDlg.show();
		QApplication::processEvents();

		cloud.calcNormals(.01f * scale);

		if (pc->reserveTheNormsTable())
		{
			for (size_t i=0; i<count; ++i)
			{
				Vec3f& Ni = cloud[i].normal;
				//normalize the vector in case of
				Vector3Tpl<float>::vnormalize(Ni);
				pc->addNorm(Ni[0],Ni[1],Ni[2]);
			}
			pc->showNormals(true);
			
			//currently selected entities appearance may have changed!
			pc->prepareDisplayForRefresh_recursive();
		}
		else
		{
			m_app->dispToConsole("Not enough memory to compute normals!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
			return;
		}
	}

    // set which primitives are to be detected by adding the respective constructors
    RansacShapeDetector detector(ransacOptions); // the detector object

	if (rsdDlg.planeCheckBox->isChecked())
		detector.Add(new PlanePrimitiveShapeConstructor());
	if (rsdDlg.sphereCheckBox->isChecked())
		detector.Add(new SpherePrimitiveShapeConstructor());
	if (rsdDlg.cylinderCheckBox->isChecked())
		detector.Add(new CylinderPrimitiveShapeConstructor());
	if (rsdDlg.coneCheckBox->isChecked())
		detector.Add(new ConePrimitiveShapeConstructor());
	if (rsdDlg.torusCheckBox->isChecked())
		detector.Add(new TorusPrimitiveShapeConstructor());

	size_t remaining = count;
	typedef std::pair< MiscLib::RefCountPtr< PrimitiveShape >, size_t > DetectedShape;
	MiscLib::Vector< DetectedShape > shapes; // stores the detected shapes

    // run detection
	// returns number of unassigned points
	// the array shapes is filled with pointers to the detected shapes
	// the second element per shapes gives the number of points assigned to that primitive (the support)
	// the points belonging to the first shape (shapes[0]) have been sorted to the end of pc,
	// i.e. into the range [ pc.size() - shapes[0].second, pc.size() )
	// the points of shape i are found in the range
	// [ pc.size() - \sum_{j=0..i} shapes[j].second, pc.size() - \sum_{j=0..i-1} shapes[j].second )

	{
		//progress dialog (Qtconcurrent::run can't be canceled!)
		QProgressDialog pDlg("Operation in progress (please wait)",QString(),0,0,m_app->getMainWindow());
		pDlg.setWindowTitle("Ransac Shape Detection");
		pDlg.show();
		QApplication::processEvents();

		//run in a separate thread
		s_detector = &detector;
		s_shapes = &shapes;
		s_cloud = &cloud;
		QFuture<void> future = QtConcurrent::run(doDetection);

		while (!future.isFinished())
		{
#if defined(CC_WINDOWS)
			::Sleep(500);
#else
			sleep(500);
#endif
			pDlg.setValue(pDlg.value()+1);
			QApplication::processEvents();
		}

		remaining = s_remainingPoints;

		pDlg.hide();
		QApplication::processEvents();
	}
	//else
	//{
	//	remaining = detector.Detect(cloud, 0, cloud.size(), &shapes);
	//}

#ifdef _DEBUG
	FILE* fp = fopen("RANS_SD_trace.txt","wt");

    fprintf(fp,"[Options]\n");
    fprintf(fp,"epsilon=%f\n",ransacOptions.m_epsilon);
    fprintf(fp,"bitmap epsilon=%f\n",ransacOptions.m_bitmapEpsilon);
    fprintf(fp,"normal thresh=%f\n",ransacOptions.m_normalThresh);
    fprintf(fp,"min support=%i\n",ransacOptions.m_minSupport);
    fprintf(fp,"probability=%f\n",ransacOptions.m_probability);

    fprintf(fp,"\n[Statistics]\n");
	fprintf(fp,"input points=%i\n",count);
	fprintf(fp,"segmented=%i\n",count-remaining);
	fprintf(fp,"remaining=%i\n",remaining);

    if (shapes.size()>0)
    {
        fprintf(fp,"\n[Shapes]\n");
        for (unsigned i=0;i<shapes.size();++i)
        {
            PrimitiveShape* shape = shapes[i].first;
            size_t shapePointsCount = shapes[i].second;

            std::string desc;
            shape->Description(&desc);
            fprintf(fp,"#%i - %s - %i points\n",i+1,desc.c_str(),shapePointsCount);
        }
    }
	fclose(fp);
#endif

	if (remaining == count)
	{
		m_app->dispToConsole("Segmentation failed...",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
        return;
	}

	if (shapes.size() > 0)
	{
		ccHObject* group = 0;
		for (MiscLib::Vector<DetectedShape>::const_iterator it = shapes.begin(); it != shapes.end(); ++it)
		{
			const PrimitiveShape* shape = it->first;
			size_t shapePointsCount = it->second;

			//too many points?!
			if (shapePointsCount > count)
			{
				m_app->dispToConsole("Inconsistent result!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
				break;
			}

			std::string desc;
			shape->Description(&desc);

			//new cloud for sub-part
			ccPointCloud* pcShape = new ccPointCloud(desc.c_str());

			//we fill cloud with sub-part points
			if (!pcShape->reserve((unsigned)shapePointsCount))
			{
				m_app->dispToConsole("Not enough memory!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
				delete pcShape;
				break;
			}			
			bool saveNormals = pcShape->reserveTheNormsTable();

			for (size_t j=0;j<shapePointsCount;++j)
			{
				pcShape->addPoint(CCVector3::fromArray(cloud[count-1-j].pos));
				if (saveNormals)
					pcShape->addNorm(CCVector3::fromArray(cloud[count-1-j].normal).u);
			}

			//random color
			colorType col[3];
			ccColor::Generator::Random(col);
			pcShape->setRGBColor(col);
			pcShape->showColors(true);
			pcShape->showNormals(saveNormals);
			pcShape->setVisible(true);
			pcShape->setGlobalShift(globalShift);
			pcShape->setGlobalScale(globalScale);

			//convert detected primitive into a CC primitive type
			ccGenericPrimitive* prim = 0;
			switch(shape->Identifier())
			{
			case 0: //plane
				{
				const PlanePrimitiveShape* plane = static_cast<const PlanePrimitiveShape*>(shape);
				Vec3f G = plane->Internal().getPosition();
				Vec3f N = plane->Internal().getNormal();
				Vec3f X = plane->getXDim();
				Vec3f Y = plane->getYDim();

				//we look for real plane extents
				float minX,maxX,minY,maxY;
				for (size_t j=0;j<shapePointsCount;++j)
				{
					std::pair<float,float> param;
					plane->Parameters(cloud[count-1-j].pos,&param);
					if (j!=0)
					{
						if (minX<param.first)
							minX=param.first;
						else if (maxX>param.first)
							maxX=param.first;
						if (minY<param.second)
							minY=param.second;
						else if (maxY>param.second)
							maxY=param.second;
					}
					else
					{
						minX=maxX=param.first;
						minY=maxY=param.second;
					}
				}

				//we recenter plane (as it is not always the case!)
				float dX = maxX-minX;
				float dY = maxY-minY;
				G += X * (minX+dX/2);
				G += Y * (minY+dY/2);

				//we build matrix from these vectors
				ccGLMatrix glMat(	CCVector3::fromArray(X.getValue()),
									CCVector3::fromArray(Y.getValue()),
									CCVector3::fromArray(N.getValue()),
									CCVector3::fromArray(G.getValue()) );

				//plane primitive
				prim = new ccPlane(dX,dY,&glMat);
			
				}
				break;

			case 1: //sphere
				{
				const SpherePrimitiveShape* sphere = static_cast<const SpherePrimitiveShape*>(shape);
				float radius = sphere->Internal().Radius();
				Vec3f CC = sphere->Internal().Center();

				pcShape->setName(QString("Sphere (r=%1)").arg(radius,0,'f'));

				//we build matrix from these vecctors
				ccGLMatrix glMat;
				glMat.setTranslation(CC.getValue());
				//sphere primitive
				prim = new ccSphere(radius,&glMat);
				prim->setEnabled(false);
			
				}
				break;

			case 2: //cylinder
				{
				const CylinderPrimitiveShape* cyl = static_cast<const CylinderPrimitiveShape*>(shape);
				Vec3f G = cyl->Internal().AxisPosition();
				Vec3f N = cyl->Internal().AxisDirection();
				Vec3f X = cyl->Internal().AngularDirection();
				Vec3f Y = N.cross(X);
				float r = cyl->Internal().Radius();
				float hMin = cyl->MinHeight();
				float hMax = cyl->MaxHeight();
				float h = hMax-hMin;
				G += N * (hMin+h/2);

				pcShape->setName(QString("Cylinder (r=%1/h=%2)").arg(r,0,'f').arg(h,0,'f'));

				//we build matrix from these vecctors
				ccGLMatrix glMat(	CCVector3::fromArray(X.getValue()),
									CCVector3::fromArray(Y.getValue()),
									CCVector3::fromArray(N.getValue()),
									CCVector3::fromArray(G.getValue()) );

				//cylinder primitive
				prim = new ccCylinder(r,h,&glMat);
				prim->setEnabled(false);

				}
				break;

			case 3: //cone
				{
				const ConePrimitiveShape* cone = static_cast<const ConePrimitiveShape*>(shape);
				Vec3f CC = cone->Internal().Center();
				Vec3f CA = cone->Internal().AxisDirection();
				float alpha = cone->Internal().Angle();

				//compute max height
				CCVector3 maxP = CCVector3::fromArray(CC.getValue());
				float maxHeight = 0;
				for (size_t j=0; j<shapePointsCount; ++j)
				{
					float h = cone->Internal().Height(cloud[count-1-j].pos);
					if (h > maxHeight)
					{
						maxHeight = h;
						maxP = CCVector3::fromArray(cloud[count-1-j].pos);
					}
				}

				pcShape->setName(QString("Cone (alpha=%1/h=%2)").arg(alpha,0,'f').arg(maxHeight,0,'f'));

				float radius = tan(alpha)*maxHeight;
				CCVector3 Z = CCVector3::fromArray(CA.getValue());
				CCVector3 C = CCVector3::fromArray(CC.getValue()); //cone apex

				//construct remaining of base
				Z.normalize();
				CCVector3 X = maxP - (C + maxHeight * Z);
				X.normalize();
				CCVector3 Y = Z * X;

				//we build matrix from these vecctors
				ccGLMatrix glMat(X,Y,Z,C+(maxHeight/2)*Z);

				//cone primitive
				prim = new ccCone(0,radius,maxHeight,0,0,&glMat);
				prim->setEnabled(false);

				}
				break;

			case 4: //torus
				{
				const TorusPrimitiveShape* torus = static_cast<const TorusPrimitiveShape*>(shape);
				if (torus->Internal().IsAppleShaped())
				{
					m_app->dispToConsole("[qRansacSD] Apple-shaped torus are not handled by CloudCompare!",ccMainAppInterface::WRN_CONSOLE_MESSAGE);
				}
				else
				{
					Vec3f CC = torus->Internal().Center();
					Vec3f CA = torus->Internal().AxisDirection();
					float minRadius = torus->Internal().MinorRadius();
					float maxRadius = torus->Internal().MajorRadius();

					pcShape->setName(QString("Torus (r=%1/R=%2)").arg(minRadius,0,'f').arg(maxRadius,0,'f'));

					CCVector3 Z = CCVector3::fromArray(CA.getValue());
					CCVector3 C = CCVector3::fromArray(CC.getValue());
					//construct remaining of base
					CCVector3 X = Z.orthogonal();
					CCVector3 Y = Z * X;

					//we build matrix from these vecctors
					ccGLMatrix glMat(X,Y,Z,C);

					//torus primitive
					prim = new ccTorus(maxRadius-minRadius,maxRadius+minRadius,M_PI*2.0,false,0,&glMat);
					prim->setEnabled(false);
				}

				}
				break;
			}

			//is there a primitive to add to part cloud?
			if (prim)
			{
				prim->applyGLTransformation_recursive();
				pcShape->addChild(prim);
				prim->setDisplay(pcShape->getDisplay());
				prim->setColor(col);
				prim->showColors(true);
				prim->setVisible(true);
			}

			if (!group)
			{
				group = new ccHObject(QString("Ransac Detected Shapes (%1)").arg(ent->getName()));
				m_app->addToDB(group,true,0,false);
			}
			group->addChild(pcShape);
			m_app->addToDB(pcShape,true,0,false);

			count -= shapePointsCount;

			QApplication::processEvents();
		}

		if (group)
		{
			assert(group->getChildrenNumber()!=0);
			
			//we hide input cloud
			pc->setEnabled(false);
			m_app->dispToConsole("[qRansacSD] Input cloud has been automtically hidden!",ccMainAppInterface::WRN_CONSOLE_MESSAGE);

			//we add new group to DB/display
			group->setVisible(true);
			group->setDisplay_recursive(pc->getDisplay());
			group->prepareDisplayForRefresh_recursive();
			m_app->refreshAll();		
		}
	}
}
Esempio n. 20
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(),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
	QScopedPointer<ccProgressDialog> pDlg(0);
	if (parameters.parentWidget)
	{
		pDlg.reset(new ccProgressDialog(true, parameters.parentWidget));
		pDlg->setMethodTitle(QObject::tr("Saving cloud [%1]").arg(cloud->getName()));
		pDlg->setInfo(QObject::tr("Number of points: %1").arg(numberOfPoints));
		pDlg->start();
	}
	CCLib::NormalizedProgress nprogress(pDlg.data(), numberOfPoints);

	//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 (pDlg && !nprogress.oneStep())
		{
			result = CC_FERR_CANCELED_BY_USER;
			break;
		}
	}

	return result;
}
Esempio n. 21
0
bool StereogramWidget::init(double angularStep_deg,
							ccHObject* entity,
							double resolution_deg/*=2.0*/)
{
	m_angularStep_deg = angularStep_deg;

	if (m_densityGrid)
		delete m_densityGrid;
	m_densityGrid = 0;

	if (!entity)
		return false;

	ccProgressDialog pDlg(true);
	pDlg.setMethodTitle("Stereogram");
	pDlg.setInfo("Preparing polar display...");
	pDlg.start();
	QApplication::processEvents();

	size_t count = 0;
	ccHObject::Container facets;
	ccPointCloud* cloud = 0;

	//a set of facets?
	if (entity->isA(CC_TYPES::HIERARCHY_OBJECT))
	{
		entity->filterChildren(facets,true,CC_TYPES::FACET);
		count = facets.size();
	}
	//or a cloud?
	else if (entity->isA(CC_TYPES::POINT_CLOUD))
	{
		cloud = static_cast<ccPointCloud*>(entity);
		if (cloud->hasNormals())
			count = cloud->size();
	}

	if (!count)
		return false;

	//pDlg.setMaximum(static_cast<int>(count));
	CCLib::NormalizedProgress nProgress(&pDlg,static_cast<unsigned>(count));

	//create the density grid
	FacetDensityGrid* densityGrid = new FacetDensityGrid();
	densityGrid->step_deg = resolution_deg;
	densityGrid->step_R = 0.02;

	//dip steps (dip in [0,90])
	//densityGrid->dSteps = static_cast<unsigned>(ceil(90.0 / densityGrid->step_deg));
	//R steps (R in [0,1])
	densityGrid->rSteps = static_cast<unsigned>(ceil(1.0 / densityGrid->step_R));
	//dip direction steps (dip dir. in [0,360])
	densityGrid->ddSteps = static_cast<unsigned>(ceil(360.0 / densityGrid->step_deg));

	unsigned cellCount = densityGrid->rSteps * densityGrid->ddSteps;
	densityGrid->grid = new double[cellCount];
	if (densityGrid->grid)
	{
		memset(densityGrid->grid,0,sizeof(double)*cellCount);

		CCVector3d Nmean(0,0,0);
		double surfaceSum = 0.0;

		for (size_t i=0; i<count; ++i)
		{
			CCVector3 N;
			double weight = 1.0;
			if (cloud)
			{
				N = cloud->getPointNormal(static_cast<unsigned>(i));
			}
			else
			{
				ccFacet* facet = static_cast<ccFacet*>(facets[i]);
				N = facet->getNormal();
				weight = facet->getSurface();
			}

			Nmean.x += static_cast<double>(N.x) * weight;
			Nmean.y += static_cast<double>(N.y) * weight;
			Nmean.z += static_cast<double>(N.z) * weight;
			surfaceSum += weight;

			PointCoordinateType dipDir = 0, dip = 0;
			ccNormalVectors::ConvertNormalToDipAndDipDir(N,dip,dipDir);

			//unsigned iDip = static_cast<unsigned>(floor(static_cast<double>(dip)/densityGrid->step_deg));
			//if (iDip == densityGrid->dSteps)
			//	iDip--;
			unsigned iDipDir = static_cast<unsigned>(floor(static_cast<double>(dipDir)/densityGrid->step_deg));
			if (iDipDir == densityGrid->ddSteps)
				iDipDir--;

			double dip_rad = dip * CC_DEG_TO_RAD;
			double R = sin(dip_rad) / (1.0 + cos(dip_rad));

			unsigned iR = static_cast<unsigned>(floor(static_cast<double>(R)/densityGrid->step_R));
			if (iR == densityGrid->rSteps)
				iR--;

			densityGrid->grid[iR + iDipDir * densityGrid->rSteps] += weight;

			//pDlg.setValue(static_cast<int>(i));
			if (!nProgress.oneStep())
			{
				//process cancelled by user
				delete densityGrid;
				return false;
			}
		}

		if (surfaceSum > 0)
		{
			Nmean.normalize();
			CCVector3 N(static_cast<PointCoordinateType>(Nmean.x),
				static_cast<PointCoordinateType>(Nmean.y),
				static_cast<PointCoordinateType>(Nmean.z));

			PointCoordinateType dipDir = 0, dip = 0;
			ccNormalVectors::ConvertNormalToDipAndDipDir(N,dip,dipDir);

			m_meanDipDir_deg = static_cast<double>(dipDir);
			m_meanDip_deg = static_cast<double>(dip);

			//set same value for the "filter" center
			m_clickDipDir_deg = m_meanDipDir_deg;
			m_clickDip_deg = m_meanDip_deg;
		}

		//compute min and max density
		{
			//DGM: only supported on C++x11!
			//std::pair<double*,double*> minmax = std::minmax_element(densityGrid->grid,densityGrid->grid+cellCount);
			//densityGrid->minMaxDensity[0] = *minmax.first;
			//densityGrid->minMaxDensity[1] = *minmax.second;

			densityGrid->minMaxDensity[0] = densityGrid->grid[0];
			densityGrid->minMaxDensity[1] = densityGrid->grid[0];
			for (unsigned j=1; j<cellCount; ++j)
			{
				if (densityGrid->grid[j] < densityGrid->minMaxDensity[0])
					densityGrid->minMaxDensity[0] = densityGrid->grid[j];
				else if (densityGrid->grid[j] > densityGrid->minMaxDensity[1])
					densityGrid->minMaxDensity[1] = densityGrid->grid[j];
			}
		}

		//pDlg.hide();
		pDlg.stop();
		QApplication::processEvents();
	}
	else
	{
		//not enough memory!
		delete densityGrid;
		densityGrid = 0;
	}

	//replace old grid by new one! (even in case of failure! See below)
	m_densityGrid = densityGrid;

	update();

	return true;
}
Esempio n. 22
0
void qCork::doAction()
{
	assert(m_app);
	if (!m_app)
		return;

	const ccHObject::Container& selectedEntities = m_app->getSelectedEntities();
	size_t selNum = selectedEntities.size();
	if (	selNum != 2
		||	!selectedEntities[0]->isKindOf(CC_TYPES::MESH)
		||	!selectedEntities[1]->isKindOf(CC_TYPES::MESH) )
	{
		assert(false);
		m_app->dispToConsole("Select two and only two meshes!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
		return;
	}

	ccMesh* meshA = static_cast<ccMesh*>(selectedEntities[0]);
	ccMesh* meshB = static_cast<ccMesh*>(selectedEntities[1]);

	//show dialog to let the user choose the operation to perform
	ccCorkDlg cDlg(m_app->getMainWindow());
	cDlg.setNames(meshA->getName(),meshB->getName());
	if (!cDlg.exec())
		return;
	if (cDlg.isSwapped())
		std::swap(meshA,meshB);

	//try to convert both meshes to CorkMesh structures
	CorkMesh corkA;
	if (!ToCorkMesh(meshA, corkA, m_app))
		return;
	CorkMesh corkB;
	if (!ToCorkMesh(meshB, corkB, m_app))
		return;

	//launch process
	{
		//run in a separate thread
		QProgressDialog pDlg("Operation in progress",QString(),0,0,m_app->getMainWindow());
		pDlg.setWindowTitle("Cork");
		pDlg.show();
		QApplication::processEvents();

		s_params.app = m_app;
		s_params.corkA = &corkA;
		s_params.corkB = &corkB;
		s_params.nameA = meshA->getName();
		s_params.nameB = meshB->getName();
		s_params.operation = cDlg.getSelectedOperation();
			
		QFuture<bool> future = QtConcurrent::run(doPerformBooleanOp);

		//wait until process is finished!
		while (!future.isFinished())
		{
#if defined(CC_WINDOWS)
			::Sleep(500);
#else
			usleep(500 * 1000);
#endif

			pDlg.setValue(pDlg.value()+1);
			QApplication::processEvents();
		}

		//just to be sure
		s_params.app = 0;
		s_params.corkA = s_params.corkB = 0;

		pDlg.hide();
		QApplication::processEvents();

		if (!future.result())
		{
			if (m_app)
				m_app->dispToConsole(s_params.meshesAreOk ? "Computation failed!" : "Computation failed! (check console)",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
			//an error occurred
			return;
		}
	}

	//convert the updated mesh (A) to a new ccMesh structure
	ccMesh* result = FromCorkMesh(corkA);

	if (result)
	{
		meshA->setEnabled(false);
		if (meshB->getDisplay() == meshA->getDisplay())
			meshB->setEnabled(false);

		//set name
		QString opName;
		switch(cDlg.getSelectedOperation())
		{
		case ccCorkDlg::UNION:
			opName = "union";
			break;
		case ccCorkDlg::INTERSECT:
			opName = "isect";
			break;
		case ccCorkDlg::DIFF:
			opName = "diff";
			break;
		case ccCorkDlg::SYM_DIFF:
			opName = "sym_diff";
			break;
		default:
			assert(false);
			break;
		}
		result->setName(QString("(%1).%2.(%3)").arg(meshA->getName()).arg(opName).arg(meshB->getName()));

		//normals
		bool hasNormals = false;
		if (meshA->hasTriNormals())
			hasNormals = result->computePerTriangleNormals();
		else if (meshA->hasNormals())
			hasNormals = result->computePerVertexNormals();
		meshA->showNormals(hasNormals && meshA->normalsShown());

		result->setDisplay(meshA->getDisplay());
		m_app->addToDB(result);
		result->redrawDisplay();
	}

	//currently selected entities appearance may have changed!
	m_app->refreshAll();
}
Esempio n. 23
0
ccHObject* qFacets::createFacets(	ccPointCloud* cloud,
								CCLib::ReferenceCloudContainer& components,
								unsigned minPointsPerComponent,
								double maxEdgeLength,
								bool randomColors,
								bool& error)
{
	if (!cloud)
		return 0;

	//we create a new group to store all input CCs as 'facets'
	ccHObject* ccGroup = new ccHObject(cloud->getName()+QString(" [facets]"));
	ccGroup->setDisplay(cloud->getDisplay());
	ccGroup->setVisible(true);

	bool cloudHasNormal = cloud->hasNormals();

	//number of input components
	size_t componentCount = components.size();

	//progress notification
	ccProgressDialog pDlg(true,m_app->getMainWindow());
	pDlg.setMethodTitle("Facets creation");
	pDlg.setInfo(qPrintable(QString("Components: %1").arg(componentCount)));
	pDlg.setMaximum(static_cast<int>(componentCount));
	pDlg.show();
	QApplication::processEvents();

	//for each component
	error = false;
	while (!components.empty())
	{
		CCLib::ReferenceCloud* compIndexes = components.back();
		components.pop_back();

		//if it has enough points
		if (compIndexes && compIndexes->size() >= minPointsPerComponent)
		{
			ccPointCloud* facetCloud = cloud->partialClone(compIndexes);
			if (!facetCloud)
			{
				//not enough  memory!
				error = true;
				delete facetCloud;
				facetCloud = 0;
			}
			else
			{
				ccFacet* facet = ccFacet::Create(facetCloud,static_cast<PointCoordinateType>(maxEdgeLength),true);
				if (facet)
				{
					QString facetName = QString("facet %1 (rms=%2)").arg(ccGroup->getChildrenNumber()).arg(facet->getRMS());
					facet->setName(facetName);
					if (facet->getPolygon())
					{
						facet->getPolygon()->enableStippling(false);
						facet->getPolygon()->showNormals(false);
					}
					if (facet->getContour())
					{
						facet->getContour()->setGlobalScale(facetCloud->getGlobalScale());
						facet->getContour()->setGlobalShift(facetCloud->getGlobalShift());
					}

					//check the facet normal sign
					if (cloudHasNormal)
					{
						CCVector3 N = ccOctree::ComputeAverageNorm(compIndexes,cloud);

						if (N.dot(facet->getNormal()) < 0)
							facet->invertNormal();
					}

#ifdef _DEBUG
					facet->showNormalVector(true);
#endif

					//shall we colorize it with a random color?
					ccColor::Rgb col, darkCol;
					if (randomColors)
					{
						col = ccColor::Generator::Random();
						assert(c_darkColorRatio <= 1.0);
						darkCol.r = static_cast<ColorCompType>(static_cast<double>(col.r) * c_darkColorRatio);
						darkCol.g = static_cast<ColorCompType>(static_cast<double>(col.g) * c_darkColorRatio);
						darkCol.b = static_cast<ColorCompType>(static_cast<double>(col.b) * c_darkColorRatio);
					}
					else
					{
						//use normal-based HSV coloring
						CCVector3 N = facet->getNormal();
						PointCoordinateType dip, dipDir;
						ccNormalVectors::ConvertNormalToDipAndDipDir(N, dip, dipDir);
						FacetsClassifier::GenerateSubfamilyColor(col,dip,dipDir,0,1,&darkCol);
					}
					facet->setColor(col);
					if (facet->getContour())
					{
						facet->getContour()->setColor(darkCol);
						facet->getContour()->setWidth(2);
					}
					ccGroup->addChild(facet);
				}
			}

			if (compIndexes)
				delete compIndexes;
			compIndexes = 0;
		}

		pDlg.setValue(static_cast<int>(componentCount-components.size()));
		//QApplication::processEvents();
	}

	if (ccGroup->getChildrenNumber() == 0)
	{
		delete ccGroup;
		ccGroup = 0;
	}

	return ccGroup;
}
Esempio n. 24
0
void qFacets::extractFacets(CellsFusionDlg::Algorithm algo)
{
	//disclaimer accepted?
	if (!ShowDisclaimer(m_app))
		return;

	assert(m_app);
	if (!m_app)
		return;

	//we expect a unique cloud as input
	const ccHObject::Container& selectedEntities = m_app->getSelectedEntities();
	ccPointCloud* pc = (selectedEntities.size() == 1 ? ccHObjectCaster::ToPointCloud(selectedEntities.back()) : 0);
	if (!pc)
	{
		m_app->dispToConsole("Select one and only one point cloud!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
		return;
	}

	if (algo != CellsFusionDlg::ALGO_FAST_MARCHING && algo != CellsFusionDlg::ALGO_KD_TREE)
	{
		m_app->dispToConsole("Internal error: invalid algorithm type!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
		return;
	}

	//first time: we compute the max edge length automatically
	if (s_lastCloud != pc)
	{
		s_maxEdgeLength = static_cast<double>(pc->getOwnBB().getMinBoxDim())/50;
		s_minPointsPerFacet = std::max<unsigned>(pc->size() / 100000, 10);
		s_lastCloud = pc;
	}

	CellsFusionDlg fusionDlg(algo,m_app->getMainWindow());
	if (algo == CellsFusionDlg::ALGO_FAST_MARCHING)
		fusionDlg.octreeLevelSpinBox->setCloud(pc);

	fusionDlg.octreeLevelSpinBox->setValue(s_octreeLevel);
	fusionDlg.useRetroProjectionCheckBox->setChecked(s_fmUseRetroProjectionError);
	fusionDlg.minPointsPerFacetSpinBox->setValue(s_minPointsPerFacet);
	fusionDlg.errorMeasureComboBox->setCurrentIndex(s_errorMeasureType);
	fusionDlg.maxRMSDoubleSpinBox->setValue(s_errorMaxPerFacet);
	fusionDlg.maxAngleDoubleSpinBox->setValue(s_kdTreeFusionMaxAngle_deg);
	fusionDlg.maxRelativeDistDoubleSpinBox->setValue(s_kdTreeFusionMaxRelativeDistance);
	fusionDlg.maxEdgeLengthDoubleSpinBox->setValue(s_maxEdgeLength);
	//"no normal" warning
	fusionDlg.noNormalWarningLabel->setVisible(!pc->hasNormals());

	if (!fusionDlg.exec())
		return;

	s_octreeLevel						= fusionDlg.octreeLevelSpinBox->value();
	s_fmUseRetroProjectionError			= fusionDlg.useRetroProjectionCheckBox->isChecked();
	s_minPointsPerFacet					= fusionDlg.minPointsPerFacetSpinBox->value();
	s_errorMeasureType					= fusionDlg.errorMeasureComboBox->currentIndex();
	s_errorMaxPerFacet					= fusionDlg.maxRMSDoubleSpinBox->value();
	s_kdTreeFusionMaxAngle_deg			= fusionDlg.maxAngleDoubleSpinBox->value();
	s_kdTreeFusionMaxRelativeDistance	= fusionDlg.maxRelativeDistDoubleSpinBox->value();
	s_maxEdgeLength						= fusionDlg.maxEdgeLengthDoubleSpinBox->value();

	//convert 'errorMeasureComboBox' index to enum
	CCLib::DistanceComputationTools::ERROR_MEASURES errorMeasure = CCLib::DistanceComputationTools::RMS;
	switch (s_errorMeasureType)
	{
	case 0:
		errorMeasure = CCLib::DistanceComputationTools::RMS;
		break;
	case 1:
		errorMeasure = CCLib::DistanceComputationTools::MAX_DIST_68_PERCENT;
		break;
	case 2:
		errorMeasure = CCLib::DistanceComputationTools::MAX_DIST_95_PERCENT;
		break;
	case 3:
		errorMeasure = CCLib::DistanceComputationTools::MAX_DIST_99_PERCENT;
		break;
	case 4:
		errorMeasure = CCLib::DistanceComputationTools::MAX_DIST;
		break;
	default:
		assert(false);
		break;
	}
	
	//create scalar field to host the fusion result
	const char c_defaultSFName[] = "facet indexes";
	int sfIdx = pc->getScalarFieldIndexByName(c_defaultSFName);
	if (sfIdx < 0)
		sfIdx = pc->addScalarField(c_defaultSFName);
	if (sfIdx < 0)
	{
		m_app->dispToConsole("Couldn't allocate a new scalar field for computing fusion labels! Try to free some memory ...",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
		return;
	}
	pc->setCurrentScalarField(sfIdx);
	
	//computation
	QElapsedTimer eTimer;
	eTimer.start();
	ccProgressDialog pDlg(true,m_app->getMainWindow());

	bool success = true;
	if (algo == CellsFusionDlg::ALGO_KD_TREE)
	{
		//we need a kd-tree
		QElapsedTimer eTimer;
		eTimer.start();
		ccKdTree kdtree(pc);

		if (kdtree.build(s_errorMaxPerFacet/2,errorMeasure,s_minPointsPerFacet,1000,&pDlg))
		{
			qint64 elapsedTime_ms = eTimer.elapsed();
			m_app->dispToConsole(QString("[qFacets] Kd-tree construction timing: %1 s").arg(static_cast<double>(elapsedTime_ms)/1.0e3,0,'f',3),ccMainAppInterface::STD_CONSOLE_MESSAGE);
		
			success = ccKdTreeForFacetExtraction::FuseCells(
				&kdtree,
				s_errorMaxPerFacet,
				errorMeasure,
				s_kdTreeFusionMaxAngle_deg,
				static_cast<PointCoordinateType>(s_kdTreeFusionMaxRelativeDistance),
				true,
				&pDlg);
		}
		else
		{
			m_app->dispToConsole("Failed to build Kd-tree! (not enough memory?)",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
			success = false;
		}
	}
	else if (algo == CellsFusionDlg::ALGO_FAST_MARCHING)
	{
		int result = FastMarchingForFacetExtraction::ExtractPlanarFacets(
			pc,
			static_cast<unsigned char>(s_octreeLevel),
			static_cast<ScalarType>(s_errorMaxPerFacet),
			errorMeasure,
			s_fmUseRetroProjectionError,
			&pDlg,
			pc->getOctree().data());

		success = (result >= 0);
	}

	if (success)
	{
		pc->setCurrentScalarField(sfIdx); //for AutoSegmentationTools::extractConnectedComponents
		
		CCLib::ReferenceCloudContainer components;
		if (!CCLib::AutoSegmentationTools::extractConnectedComponents(pc,components))
		{
			m_app->dispToConsole("Failed to extract fused components! (not enough memory?)",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
		}
		else
		{
			//we remove the temporary scalar field (otherwise it will be copied to the sub-clouds!)
			ccScalarField* indexSF = static_cast<ccScalarField*>(pc->getScalarField(sfIdx));
			indexSF->link(); //to prevent deletion below
			pc->deleteScalarField(sfIdx);
			sfIdx = -1;

			bool error = false;
			ccHObject* group = createFacets(pc,components,s_minPointsPerFacet,s_maxEdgeLength,false,error);

			if (group)
			{
				switch(algo)
				{
				case CellsFusionDlg::ALGO_KD_TREE:
					group->setName(group->getName() + QString(" [Kd-tree][error < %1][angle < %2 deg.]").arg(s_errorMaxPerFacet).arg(s_kdTreeFusionMaxAngle_deg));
					break;
				case CellsFusionDlg::ALGO_FAST_MARCHING:
					group->setName(group->getName() + QString(" [FM][level %2][error < %1]").arg(s_octreeLevel).arg(s_errorMaxPerFacet));
					break;
				default:
					break;
				}

				unsigned count = group->getChildrenNumber();
				m_app->dispToConsole(QString("[qFacets] %1 facet(s) where created from cloud '%2'").arg(count).arg(pc->getName()));

				if (error)
				{
					m_app->dispToConsole("Error(s) occurred during the generation of facets! Result may be incomplete",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
				}
				else
				{
					//we but back the scalar field
					if (indexSF)
						sfIdx = pc->addScalarField(indexSF);
				}

				//pc->setEnabled(false);
				m_app->addToDB(group);
				group->prepareDisplayForRefresh();
			}
			else if (error)
			{
				m_app->dispToConsole("An error occurred during the generation of facets!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
			}
			else
			{
				m_app->dispToConsole("No facet remains! Check the parameters (min size, etc.)",ccMainAppInterface::WRN_CONSOLE_MESSAGE);
			}
		}
	}
	else
	{
		m_app->dispToConsole("An error occurred during the fusion process!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
	}

	if (sfIdx >= 0)
	{
		pc->getScalarField(sfIdx)->computeMinAndMax();
#ifdef _DEBUG
		pc->setCurrentDisplayedScalarField(sfIdx);
		pc->showSF(true);
#endif
	}

	//currently selected entities appearance may have changed!
	m_app->redrawAll();
}
Esempio n. 25
0
bool ccVolumeCalcTool::ComputeVolume(	ccRasterGrid& grid,
										ccGenericPointCloud* ground,
										ccGenericPointCloud* ceil,
										const ccBBox& gridBox,
										unsigned char vertDim,
										double gridStep,
										unsigned gridWidth,
										unsigned gridHeight,
										ccRasterGrid::ProjectionType projectionType,
										ccRasterGrid::EmptyCellFillOption emptyCellFillStrategy,
										ccVolumeCalcTool::ReportInfo& reportInfo,
										double groundHeight = std::numeric_limits<double>::quiet_NaN(),
										double ceilHeight = std::numeric_limits<double>::quiet_NaN(),
										QWidget* parentWidget/*=0*/)
{
	if (	gridStep <= 1.0e-8
		||	gridWidth == 0
		||	gridHeight == 0
		||	vertDim > 2)
	{
		assert(false);
		ccLog::Warning("[Volume] Invalid input parameters");
		return false;
	}

	if (!ground && !ceil)
	{
		assert(false);
		ccLog::Warning("[Volume] No valid input cloud");
		return false;
	}

	if (!gridBox.isValid())
	{
		ccLog::Warning("[Volume] Invalid bounding-box");
		return false;
	}

	//grid size
	unsigned gridTotalSize = gridWidth * gridHeight;
	if (gridTotalSize == 1)
	{
		if (parentWidget && QMessageBox::question(parentWidget, "Unexpected grid size", "The generated grid will only have 1 cell! Do you want to proceed anyway?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
			return false;
	}
	else if (gridTotalSize > 10000000)
	{
		if (parentWidget && QMessageBox::question(parentWidget, "Big grid size", "The generated grid will have more than 10.000.000 cells! Do you want to proceed anyway?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
			return false;
	}

	//memory allocation
	CCVector3d minCorner = CCVector3d::fromArray(gridBox.minCorner().u);
	if (!grid.init(gridWidth, gridHeight, gridStep, minCorner))
	{
		//not enough memory
		return SendError("Not enough memory", parentWidget);
	}

	//progress dialog
	QScopedPointer<ccProgressDialog> pDlg(0);
	if (parentWidget)
	{
		pDlg.reset(new ccProgressDialog(true, parentWidget));
	}

	ccRasterGrid groundRaster;
	if (ground)
	{
		if (!groundRaster.init(gridWidth, gridHeight, gridStep, minCorner))
		{
			//not enough memory
			return SendError("Not enough memory", parentWidget);
		}

		if (groundRaster.fillWith(	ground,
									vertDim,
									projectionType,
									emptyCellFillStrategy == ccRasterGrid::INTERPOLATE,
									ccRasterGrid::INVALID_PROJECTION_TYPE,
									pDlg.data()))
		{
			groundRaster.fillEmptyCells(emptyCellFillStrategy, groundHeight);
			ccLog::Print(QString("[Volume] Ground raster grid: size: %1 x %2 / heights: [%3 ; %4]").arg(groundRaster.width).arg(groundRaster.height).arg(groundRaster.minHeight).arg(groundRaster.maxHeight));
		}
		else
		{
			return false;
		}
	}

	//ceil
	ccRasterGrid ceilRaster;
	if (ceil)
	{
		if (!ceilRaster.init(gridWidth, gridHeight, gridStep, minCorner))
		{
			//not enough memory
			return SendError("Not enough memory", parentWidget);
		}

		if (ceilRaster.fillWith(ceil,
								vertDim,
								projectionType,
								emptyCellFillStrategy == ccRasterGrid::INTERPOLATE,
								ccRasterGrid::INVALID_PROJECTION_TYPE,
								pDlg.data()))
		{
			ceilRaster.fillEmptyCells(emptyCellFillStrategy, ceilHeight);
			ccLog::Print(QString("[Volume] Ceil raster grid: size: %1 x %2 / heights: [%3 ; %4]").arg(ceilRaster.width).arg(ceilRaster.height).arg(ceilRaster.minHeight).arg(ceilRaster.maxHeight));
		}
		else
		{
			return false;
		}
	}

	//update grid and compute volume
	{
		if (pDlg)
		{
			pDlg->setMethodTitle(QObject::tr("Volume computation"));
			pDlg->setInfo(QObject::tr("Cells: %1 x %2").arg(grid.width).arg(grid.height));
			pDlg->start();
			pDlg->show();
			QCoreApplication::processEvents();
		}
		CCLib::NormalizedProgress nProgress(pDlg.data(), grid.width * grid.height);
		
		size_t ceilNonMatchingCount = 0;
		size_t groundNonMatchingCount = 0;
		size_t cellCount = 0;

		//at least one of the grid is based on a cloud
		grid.nonEmptyCellCount = 0;
		for (unsigned i = 0; i < grid.height; ++i)
		{
			for (unsigned j = 0; j < grid.width; ++j)
			{
				ccRasterCell& cell = grid.rows[i][j];

				bool validGround = true;
				cell.minHeight = groundHeight;
				if (ground)
				{
					cell.minHeight = groundRaster.rows[i][j].h;
					validGround = std::isfinite(cell.minHeight);
				}

				bool validCeil = true;
				cell.maxHeight = ceilHeight;
				if (ceil)
				{
					cell.maxHeight = ceilRaster.rows[i][j].h;
					validCeil = std::isfinite(cell.maxHeight);
				}

				if (validGround && validCeil)
				{
					cell.h = cell.maxHeight - cell.minHeight;
					cell.nbPoints = 1;

					reportInfo.volume += cell.h;
					if (cell.h < 0)
					{
						reportInfo.removedVolume -= cell.h;
					}
					else if (cell.h > 0)
					{
						reportInfo.addedVolume += cell.h;
					}
					reportInfo.surface += 1.0;
					++grid.nonEmptyCellCount; //= matching count
					++cellCount;
				}
				else
				{
					if (validGround)
					{
						++cellCount;
						++groundNonMatchingCount;
					}
					else if (validCeil)
					{
						++cellCount;
						++ceilNonMatchingCount;
					}
					cell.h = std::numeric_limits<double>::quiet_NaN();
					cell.nbPoints = 0;
				}

				cell.avgHeight = (groundHeight + ceilHeight) / 2;
				cell.stdDevHeight = 0;

				if (pDlg && !nProgress.oneStep())
				{
					ccLog::Warning("[Volume] Process cancelled by the user");
					return false;
				}
			}
		}
		grid.validCellCount = grid.nonEmptyCellCount;

		//count the average number of valid neighbors
		{
			size_t validNeighborsCount = 0;
			size_t count = 0;
			for (unsigned i = 1; i < grid.height - 1; ++i)
			{
				for (unsigned j = 1; j < grid.width - 1; ++j)
				{
					ccRasterCell& cell = grid.rows[i][j];
					if (cell.h == cell.h)
					{
						for (unsigned k = i - 1; k <= i + 1; ++k)
						{
							for (unsigned l = j - 1; l <= j + 1; ++l)
							{
								if (k != i || l != j)
								{
									ccRasterCell& otherCell = grid.rows[k][l];
									if (std::isfinite(otherCell.h))
									{
										++validNeighborsCount;
									}
								}
							}
						}

						++count;
					}
				}
			}

			if (count)
			{
				reportInfo.averageNeighborsPerCell = static_cast<double>(validNeighborsCount) / count;
			}
		}

		reportInfo.matchingPrecent = static_cast<float>(grid.validCellCount * 100) / cellCount;
		reportInfo.groundNonMatchingPercent = static_cast<float>(groundNonMatchingCount * 100) / cellCount;
		reportInfo.ceilNonMatchingPercent = static_cast<float>(ceilNonMatchingCount * 100) / cellCount;
		float cellArea = static_cast<float>(grid.gridStep * grid.gridStep);
		reportInfo.volume *= cellArea;
		reportInfo.addedVolume *= cellArea;
		reportInfo.removedVolume *= cellArea;
		reportInfo.surface *= cellArea;
	}

	grid.setValid(true);

	return true;
}
Esempio n. 26
0
void CMatchingDlg::Execute(void)
{
	int res;
	char msg[256];

	m_FrameID = 0;
	g_free(m_CatFile);
	m_CatFile = NULL;
	g_free(m_SelectionName);
	m_SelectionName = NULL;
	m_FileList = NULL;

	// Restore path to catalog files
	gchar *fpath = CConfig::GetStr("MakeCatDlg", "Folder", NULL);
	if (fpath && *fpath!='\0' && g_file_test(fpath, G_FILE_TEST_IS_DIR)) 
		gtk_entry_set_text(GTK_ENTRY(m_PathEntry), fpath);
	else {
		gchar *defpath = g_build_filename(get_user_data_dir(), "Catalog files", NULL);
		if (force_directory(defpath))
			gtk_entry_set_text(GTK_ENTRY(m_PathEntry), defpath);
		g_free(defpath);
	}
	g_free(fpath);

	// Update list of frames
	ReadFrames(false, g_Project->GetInt("MatchingDlg", "Frame", 0));

	// Update list of catalog files
	gchar *path = g_Project->GetStr("MatchingDlg", "File", NULL);
	if (!path)
		path = CConfig::GetStr("MatchingDlg", "File", NULL);
	ReadCatalogs(path);
	g_free(path);

	gtk_widget_show(m_UseFrame);

	// Check inputs
	if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(m_Frames), NULL)==0) {
		ShowError(m_pParent, "There are no frames usable as a reference frame.");
		return;
	}

	// Select reference frame or the first frame
	SetSelectMode(m_SelectMode);
	SetSortMode(m_FrameSort);
	UpdatePreview(true);
	UpdateControls();

	if (gtk_dialog_run(GTK_DIALOG(m_pDlg))!=GTK_RESPONSE_ACCEPT)
		return;
	gtk_widget_hide(m_pDlg);

	g_Project->SetInt("MatchingDlg", "Select", m_SelectMode);
	if (m_SelectMode == REFERENCE_FRAME)
		g_Project->SetInt("MatchingDlg", "Frame", m_FrameID);
	else {
		g_Project->SetStr("MatchingDlg", "File", m_CatFile);
		CConfig::SetStr("MatchingDlg", "File", m_CatFile);
	}
	g_Project->ClearReference();
	
	// Always all files
	gtk_tree_model_foreach(g_Project->FileList(), GtkTreeModelForeachFunc(make_list), &m_FileList);

	CProgressDlg pDlg(m_pParent, "Matching photometry files");
	pDlg.SetMinMax(0, g_list_length(m_FileList));
	res = pDlg.Execute(ExecuteProc, this);
	if (res!=0) {
		char *msg = cmpack_formaterror(res);
		ShowError(m_pParent, msg, true);
		cmpack_free(msg);
	} else if (m_OutFiles==0) {
		ShowError(m_pParent, "No file was successfully processed.", true);
	} else if (m_OutFiles!=m_InFiles) {
		sprintf(msg, "%d file(s) were successfully processed, %d file(s) failed.", 
			m_OutFiles, m_InFiles-m_OutFiles);
		ShowWarning(m_pParent, msg, true);
	} else {
		sprintf(msg, "All %d file(s) were successfully processed.", m_OutFiles);
		ShowInformation(m_pParent, msg, true);
	}

	// Free allocated memory
	g_list_foreach(m_FileList, (GFunc)gtk_tree_row_reference_free, NULL);
	g_list_free(m_FileList);
	m_FileList = NULL;
	g_free(m_CatFile);
	m_CatFile = NULL;
	g_free(m_SelectionName);
	m_SelectionName = NULL;
}
bool ccPointPairRegistrationDlg::convertToSphereCenter(CCVector3d& P, ccHObject* entity, PointCoordinateType& sphereRadius)
{
	sphereRadius = -PC_ONE;
	if (	!entity
		||	!useSphereToolButton->isChecked()
		||	!entity->isKindOf(CC_TYPES::POINT_CLOUD) ) //only works with cloud right now
	{
		//nothing to do
		return true;
	}

	//we'll now try to detect the sphere
	double searchRadius = radiusDoubleSpinBox->value();
	double maxRMSPercentage = maxRmsSpinBox->value() / 100.0;
	ccGenericPointCloud* cloud = static_cast<ccGenericPointCloud*>(entity);
	assert(cloud);

	//crop points inside a box centered on the current point
	ccBBox box;
	box.add(CCVector3::fromArray((P - CCVector3d(1,1,1)*searchRadius).u));
	box.add(CCVector3::fromArray((P + CCVector3d(1,1,1)*searchRadius).u));
	CCLib::ReferenceCloud* part = cloud->crop(box,true);

	bool success = false;
	if (part && part->size() > 16)
	{
		PointCoordinateType radius;
		CCVector3 C;
		double rms;
		ccProgressDialog pDlg(true, this);
		//first roughly search for the sphere
		if (CCLib::GeometricalAnalysisTools::detectSphereRobust(part,0.5,C,radius,rms,&pDlg,0.9))
		{
			if (radius / searchRadius < 0.5 || radius / searchRadius > 2.0)
			{
				ccLog::Warning(QString("[ccPointPairRegistrationDlg] Detected sphere radius (%1) is too far from search radius!").arg(radius));
			}
			else
			{
				//now look again (more precisely)
				{
					delete part;
					box.clear();
					box.add(C - CCVector3(1,1,1)*radius*static_cast<PointCoordinateType>(1.05)); //add 5%
					box.add(C + CCVector3(1,1,1)*radius*static_cast<PointCoordinateType>(1.05)); //add 5%
					part = cloud->crop(box,true);
					if (part && part->size() > 16)
						CCLib::GeometricalAnalysisTools::detectSphereRobust(part,0.5,C,radius,rms,&pDlg,0.99);
				}
				ccLog::Print(QString("[ccPointPairRegistrationDlg] Detected sphere radius = %1 (rms = %2)").arg(radius).arg(rms));
				if (radius / searchRadius < 0.5 || radius / searchRadius > 2.0)
				{
					ccLog::Warning("[ccPointPairRegistrationDlg] Sphere radius is too far from search radius!");
				}
				else if (rms / searchRadius >= maxRMSPercentage)
				{
					ccLog::Warning("[ccPointPairRegistrationDlg] RMS is too high!");
				}
				else
				{
					sphereRadius = radius;
					P = CCVector3d::fromArray(C.u);
					success = true;
				}
			}
		}
		else
		{
			ccLog::Warning("[ccPointPairRegistrationDlg] Failed to fit a sphere around the picked point!");
		}
	}
	else
	{
		//not enough memory? No points inside the 
		ccLog::Warning("[ccPointPairRegistrationDlg] Failed to crop points around the picked point?!");
	}

	if (part)
		delete part;

	return success;
}
Esempio n. 28
0
CC_FILE_ERROR ObjFilter::loadFile(QString filename, ccHObject& container, LoadParameters& parameters)
{
	ccLog::Print(QString("[OBJ] ") + filename);

	//open file
	QFile file(filename);
	if (!file.open(QFile::ReadOnly))
		return CC_FERR_READING;
	QTextStream stream(&file);

	//current vertex shift
	CCVector3d Pshift(0,0,0);

	//vertices
	ccPointCloud* vertices = new ccPointCloud("vertices");
	int pointsRead = 0;

	//facets
	unsigned int facesRead = 0;
	unsigned int totalFacesRead = 0;
	int maxVertexIndex = -1;

	//base mesh
	ccMesh* baseMesh = new ccMesh(vertices);
	baseMesh->setName(QFileInfo(filename).baseName());
	//we need some space already reserved!
	if (!baseMesh->reserve(128))
	{
		ccLog::Error("Not engouh memory!");
		return CC_FERR_NOT_ENOUGH_MEMORY;
	}

	//groups (starting index + name)
	std::vector<std::pair<unsigned,QString> > groups;

	//materials
	ccMaterialSet* materials = 0;
	bool hasMaterial = false;
	int currentMaterial = -1;
	bool currentMaterialDefined = false;
	bool materialsLoadFailed = true;

	//texture coordinates
	TextureCoordsContainer* texCoords = 0;
	bool hasTexCoords = false;
	int texCoordsRead = 0;
	int maxTexCoordIndex = -1;

	//normals
	NormsIndexesTableType* normals = 0;
	int normsRead = 0;
	bool normalsPerFacet = false;
	int maxTriNormIndex = -1;

	//progress dialog
	ccProgressDialog pDlg(true);
	pDlg.setMethodTitle("OBJ file");
	pDlg.setInfo("Loading in progress...");
	pDlg.setRange(0,static_cast<int>(file.size()));
	pDlg.show();
	QApplication::processEvents();

	//common warnings that can appear multiple time (we avoid to send too many messages to the console!)
	enum OBJ_WARNINGS {	INVALID_NORMALS		= 0,
						INVALID_INDEX		= 1,
						NOT_ENOUGH_MEMORY	= 2,
						INVALID_LINE		= 3,
						CANCELLED_BY_USER	= 4,
	};
	bool objWarnings[5] = { false, false, false, false, false };
	bool error = false;

	try
	{
		unsigned lineCount = 0;
		unsigned polyCount = 0;
		QString currentLine = stream.readLine();
		while (!currentLine.isNull())
		{
			if ((++lineCount % 2048) == 0)
			{
				if (pDlg.wasCanceled())
				{
					error = true;
					objWarnings[CANCELLED_BY_USER] = true;
					break;
				}
				pDlg.setValue(static_cast<int>(file.pos()));
				QApplication::processEvents();
			}

			QStringList tokens = QString(currentLine).split(QRegExp("\\s+"),QString::SkipEmptyParts);

			//skip comments & empty lines
			if( tokens.empty() || tokens.front().startsWith('/',Qt::CaseInsensitive) || tokens.front().startsWith('#',Qt::CaseInsensitive) )
			{
				currentLine = stream.readLine();
				continue;
			}

			/*** new vertex ***/
			if (tokens.front() == "v")
			{
				//reserve more memory if necessary
				if (vertices->size() == vertices->capacity())
				{
					if (!vertices->reserve(vertices->capacity()+MAX_NUMBER_OF_ELEMENTS_PER_CHUNK))
					{
						objWarnings[NOT_ENOUGH_MEMORY] = true;
						error = true;
						break;
					}
				}

				//malformed line?
				if (tokens.size() < 4)
				{
					objWarnings[INVALID_LINE] = true;
					error = true;
					break;
				}

				CCVector3d Pd( tokens[1].toDouble(), tokens[2].toDouble(), tokens[3].toDouble() );

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

				//shifted point
				CCVector3 P = CCVector3::fromArray((Pd + Pshift).u);
				vertices->addPoint(P);
				++pointsRead;
			}
			/*** new vertex texture coordinates ***/
			else if (tokens.front() == "vt")
			{
				//create and reserve memory for tex. coords container if necessary
				if (!texCoords)
				{
					texCoords = new TextureCoordsContainer();
					texCoords->link();
				}
				if (texCoords->currentSize() == texCoords->capacity())
				{
					if (!texCoords->reserve(texCoords->capacity() + MAX_NUMBER_OF_ELEMENTS_PER_CHUNK))
					{
						objWarnings[NOT_ENOUGH_MEMORY] = true;
						error = true;
						break;
					}
				}

				//malformed line?
				if (tokens.size() < 2)
				{
					objWarnings[INVALID_LINE] = true;
					error = true;
					break;
				}

				float T[2] = { T[0] = tokens[1].toFloat(), 0 };

				if (tokens.size() > 2) //OBJ specification allows for only one value!!!
				{
					T[1] = tokens[2].toFloat();
				}

				texCoords->addElement(T);
				++texCoordsRead;
			}
			/*** new vertex normal ***/
			else if (tokens.front() == "vn") //--> in fact it can also be a facet normal!!!
			{
				//create and reserve memory for normals container if necessary
				if (!normals)
				{
					normals = new NormsIndexesTableType;
					normals->link();
				}
				if (normals->currentSize() == normals->capacity())
				{
					if (!normals->reserve(normals->capacity() + MAX_NUMBER_OF_ELEMENTS_PER_CHUNK))
					{
						objWarnings[NOT_ENOUGH_MEMORY] = true;
						error = true;
						break;
					}
				}

				//malformed line?
				if (tokens.size() < 4)
				{
					objWarnings[INVALID_LINE] = true;
					error = true;
					break;
				}

				CCVector3 N(static_cast<PointCoordinateType>(tokens[1].toDouble()),
							static_cast<PointCoordinateType>(tokens[2].toDouble()),
							static_cast<PointCoordinateType>(tokens[3].toDouble()));

				if (fabs(N.norm2() - 1.0) > 0.005)
				{
					objWarnings[INVALID_NORMALS] = true;
					N.normalize();
				}
				CompressedNormType nIndex = ccNormalVectors::GetNormIndex(N.u);

				normals->addElement(nIndex); //we don't know yet if it's per-vertex or per-triangle normal...
				++normsRead;
			}
			/*** new group ***/
			else if (tokens.front() == "g" || tokens.front() == "o")
			{
				//update new group index
				facesRead = 0;
				//get the group name
				QString groupName = (tokens.size() > 1 && !tokens[1].isEmpty() ? tokens[1] : "default");
				for (int i=2; i<tokens.size(); ++i) //multiple parts?
					groupName.append(QString(" ")+tokens[i]);
				//push previous group descriptor (if none was pushed)
				if (groups.empty() && totalFacesRead > 0)
					groups.push_back(std::pair<unsigned,QString>(0,"default"));
				//push new group descriptor
				if (!groups.empty() && groups.back().first == totalFacesRead)
					groups.back().second = groupName; //simply replace the group name if the previous group was empty!
				else
					groups.push_back(std::pair<unsigned,QString>(totalFacesRead,groupName));
				polyCount = 0; //restart polyline count at 0!
			}
			/*** new face ***/
			else if (tokens.front().startsWith('f'))
			{
				//malformed line?
				if (tokens.size() < 4)
				{
					objWarnings[INVALID_LINE] = true;
					currentLine = stream.readLine();
					continue;
					//error = true;
					//break;
				}

				//read the face elements (singleton, pair or triplet)
				std::vector<facetElement> currentFace;
				{
					for (int i=1; i<tokens.size(); ++i)
					{
						QStringList vertexTokens = tokens[i].split('/');
						if (vertexTokens.size() == 0 || vertexTokens[0].isEmpty())
						{
							objWarnings[INVALID_LINE] = true;
							error = true;
							break;
						}
						else
						{
							//new vertex
							facetElement fe; //(0,0,0) by default
							
							fe.vIndex = vertexTokens[0].toInt();
							if (vertexTokens.size() > 1 && !vertexTokens[1].isEmpty())
								fe.tcIndex = vertexTokens[1].toInt();
							if (vertexTokens.size() > 2 && !vertexTokens[2].isEmpty())
								fe.nIndex = vertexTokens[2].toInt();
						
							currentFace.push_back(fe);
						}
					}
				}

				if (error)
					break;

				if (currentFace.size() < 3)
				{
					ccLog::Warning("[OBJ] Malformed file: polygon on line %1 has less than 3 vertices!",lineCount);
					error = true;
					break;
				}

				//first vertex
				std::vector<facetElement>::iterator A = currentFace.begin();

				//the very first vertex of the group tells us about the whole sequence
				if (facesRead == 0)
				{
					//we have a tex. coord index as second vertex element!
					if (!hasTexCoords && A->tcIndex != 0 && !materialsLoadFailed)
					{
						if (!baseMesh->reservePerTriangleTexCoordIndexes())
						{
							objWarnings[NOT_ENOUGH_MEMORY] = true;
							error = true;
							break;
						}
						for (unsigned int i=0; i<totalFacesRead; ++i)
							baseMesh->addTriangleTexCoordIndexes(-1, -1, -1);

						hasTexCoords = true;
					}

					//we have a normal index as third vertex element!
					if (!normalsPerFacet && A->nIndex != 0)
					{
						//so the normals are 'per-facet'
						if (!baseMesh->reservePerTriangleNormalIndexes())
						{
							objWarnings[NOT_ENOUGH_MEMORY] = true;
							error = true;
							break;
						}
						for (unsigned int i=0; i<totalFacesRead; ++i)
							baseMesh->addTriangleNormalIndexes(-1, -1, -1);
						normalsPerFacet = true;
					}
				}

				//we process all vertices accordingly
				for (std::vector<facetElement>::iterator it = currentFace.begin() ; it!=currentFace.end(); ++it)
				{
					facetElement& vertex = *it;

					//vertex index
					{
						if (!vertex.updatePointIndex(pointsRead))
						{
							objWarnings[INVALID_INDEX] = true;
							error = true;
							break;
						}
						if (vertex.vIndex > maxVertexIndex)
							maxVertexIndex = vertex.vIndex;
					}
					//should we have a tex. coord index as second vertex element?
					if (hasTexCoords && currentMaterialDefined)
					{
						if (!vertex.updateTexCoordIndex(texCoordsRead))
						{
							objWarnings[INVALID_INDEX] = true;
							error = true;
							break;
						}
						if (vertex.tcIndex > maxTexCoordIndex)
							maxTexCoordIndex = vertex.tcIndex;
					}

					//should we have a normal index as third vertex element?
					if (normalsPerFacet)
					{
						if (!vertex.updateNormalIndex(normsRead))
						{
							objWarnings[INVALID_INDEX] = true;
							error = true;
							break;
						}
						if (vertex.nIndex > maxTriNormIndex)
							maxTriNormIndex = vertex.nIndex;
					}
				}

				//don't forget material (common for all vertices)
				if (currentMaterialDefined && !materialsLoadFailed)
				{
					if (!hasMaterial)
					{
						if (!baseMesh->reservePerTriangleMtlIndexes())
						{
							objWarnings[NOT_ENOUGH_MEMORY] = true;
							error = true;
							break;
						}
						for (unsigned int i=0; i<totalFacesRead; ++i)
							baseMesh->addTriangleMtlIndex(-1);

						hasMaterial = true;
					}
				}

				if (error)
					break;

				//Now, let's tesselate the whole polygon
				//FIXME: yeah, we do very ulgy tesselation here!
				std::vector<facetElement>::const_iterator B = A+1;
				std::vector<facetElement>::const_iterator C = B+1;
				for ( ; C != currentFace.end(); ++B,++C)
				{
					//need more space?
					if (baseMesh->size() == baseMesh->capacity())
					{
						if (!baseMesh->reserve(baseMesh->size()+128))
						{
							objWarnings[NOT_ENOUGH_MEMORY] = true;
							error = true;
							break;
						}
					}

					//push new triangle
					baseMesh->addTriangle(A->vIndex, B->vIndex, C->vIndex);
					++facesRead;
					++totalFacesRead;

					if (hasMaterial)
						baseMesh->addTriangleMtlIndex(currentMaterial);

					if (hasTexCoords)
						baseMesh->addTriangleTexCoordIndexes(A->tcIndex, B->tcIndex, C->tcIndex);

					if (normalsPerFacet)
						baseMesh->addTriangleNormalIndexes(A->nIndex, B->nIndex, C->nIndex);
				}
			}
			/*** polyline ***/
			else if (tokens.front().startsWith('l'))
			{
				//malformed line?
				if (tokens.size() < 3)
				{
					objWarnings[INVALID_LINE] = true;
					currentLine = stream.readLine();
					continue;
				}

				//read the face elements (singleton, pair or triplet)
				ccPolyline* polyline = new ccPolyline(vertices);
				if (!polyline->reserve(static_cast<unsigned>(tokens.size()-1)))
				{
					//not enough memory
					objWarnings[NOT_ENOUGH_MEMORY] = true;
					delete polyline;
					polyline = 0;
					currentLine = stream.readLine();
					continue;
				}

				for (int i=1; i<tokens.size(); ++i)
				{
					//get next polyline's vertex index
					QStringList vertexTokens = tokens[i].split('/');
					if (vertexTokens.size() == 0 || vertexTokens[0].isEmpty())
					{
						objWarnings[INVALID_LINE] = true;
						error = true;
						break;
					}
					else
					{
						int index = vertexTokens[0].toInt(); //we ignore normal index (if any!)
						if (!UpdatePointIndex(index,pointsRead))
						{
							objWarnings[INVALID_INDEX] = true;
							error = true;
							break;
						}

						polyline->addPointIndex(index);
					}
				}

				if (error)
				{
					delete polyline;
					polyline = 0;
					break;
				}
			
				polyline->setVisible(true);
				QString name = groups.empty() ? QString("Line") : groups.back().second+QString(".line");
				polyline->setName(QString("%1 %2").arg(name).arg(++polyCount));
				vertices->addChild(polyline);

			}
			/*** material ***/
			else if (tokens.front() == "usemtl") //see 'MTL file' below
			{
				if (materials) //otherwise we have failed to load MTL file!!!
				{
					QString mtlName = currentLine.mid(7).trimmed();
					//DGM: in case there's space characters in the material name, we must read it again from the original line buffer
					//QString mtlName = (tokens.size() > 1 && !tokens[1].isEmpty() ? tokens[1] : "");
					currentMaterial = (!mtlName.isEmpty() ? materials->findMaterialByName(mtlName) : -1);
					currentMaterialDefined = true;
				}
			}
			/*** material file (MTL) ***/
			else if (tokens.front() == "mtllib")
			{
				//malformed line?
				if (tokens.size() < 2 || tokens[1].isEmpty())
				{
					objWarnings[INVALID_LINE] = true;
				}
				else
				{
					//we build the whole MTL filename + path
					//DGM: in case there's space characters in the filename, we must read it again from the original line buffer
					//QString mtlFilename = tokens[1];
					QString mtlFilename = currentLine.mid(7).trimmed();
					ccLog::Print(QString("[OBJ] Material file: ")+mtlFilename);
					QString mtlPath = QFileInfo(filename).canonicalPath();
					//we try to load it
					if (!materials)
					{
						materials = new ccMaterialSet("materials");
						materials->link();
					}

					size_t oldSize = materials->size();
					QStringList errors;
					if (ccMaterialSet::ParseMTL(mtlPath,mtlFilename,*materials,errors))
					{
						ccLog::Print("[OBJ] %i materials loaded",materials->size()-oldSize);
						materialsLoadFailed = false;
					}
					else
					{
						ccLog::Error(QString("[OBJ] Failed to load material file! (should be in '%1')").arg(mtlPath+'/'+QString(mtlFilename)));
						materialsLoadFailed = true;
					}

					if (!errors.empty())
					{
						for (int i=0; i<errors.size(); ++i)
							ccLog::Warning(QString("[OBJ::Load::MTL parser] ")+errors[i]);
					}
					if (materials->empty())
					{
						materials->release();
						materials=0;
						materialsLoadFailed = true;
					}
				}
			}
			///*** shading group ***/
			//else if (tokens.front() == "s")
			//{
			//	//ignored!
			//}

			if (error)
				break;

			currentLine = stream.readLine();
		}
	}
	catch (const std::bad_alloc&)
	{
		//not enough memory
		objWarnings[NOT_ENOUGH_MEMORY] = true;
		error = true;
	}

	file.close();

	//1st check
	if (!error && pointsRead == 0)
	{
		//of course if there's no vertex, that's the end of the story ...
		ccLog::Warning("[OBJ] Malformed file: no vertex in file!");
		error = true;
	}

	if (!error)
	{
		ccLog::Print("[OBJ] %i points, %u faces",pointsRead,totalFacesRead);
		if (texCoordsRead > 0 || normsRead > 0)
			ccLog::Print("[OBJ] %i tex. coords, %i normals",texCoordsRead,normsRead);

		//do some cleaning
		vertices->shrinkToFit();
		if (normals)
			normals->shrinkToFit();
		if (texCoords)
			texCoords->shrinkToFit();
		if (baseMesh->size() == 0)
		{
			delete baseMesh;
			baseMesh = 0;
		}
		else
		{
			baseMesh->shrinkToFit();
		}

		if (	maxVertexIndex >= pointsRead
			||	maxTexCoordIndex >= texCoordsRead
			||	maxTriNormIndex >= normsRead)
		{
			//hum, we've got a problem here
			ccLog::Warning("[OBJ] Malformed file: indexes go higher than the number of elements! (v=%i/tc=%i/n=%i)",maxVertexIndex,maxTexCoordIndex,maxTriNormIndex);
			if (maxVertexIndex >= pointsRead)
			{
				error = true;
			}
			else
			{
				objWarnings[INVALID_INDEX] = true;
				if (maxTexCoordIndex >= texCoordsRead)
				{
					texCoords->release();
					texCoords = 0;
					materials->release();
					materials = 0;
				}
				if (maxTriNormIndex >= normsRead)
				{
					normals->release();
					normals = 0;
				}
			}
		}
		
		if (!error && baseMesh)
		{
			if (normals && normalsPerFacet)
			{
				baseMesh->setTriNormsTable(normals);
				baseMesh->showTriNorms(true);
			}
			if (materials)
			{
				baseMesh->setMaterialSet(materials);
				baseMesh->showMaterials(true);
			}
			if (texCoords)
			{
				if (materials)
				{
					baseMesh->setTexCoordinatesTable(texCoords);
				}
				else
				{
					ccLog::Warning("[OBJ] Texture coordinates were defined but no material could be loaded!");
				}
			}

			//normals: if the obj file doesn't provide any, should we compute them?
			if (!normals)
			{
				//DGM: normals can be per-vertex or per-triangle so it's better to let the user do it himself later
				//Moreover it's not always good idea if the user doesn't want normals (especially in ccViewer!)
				//if (!materials && !baseMesh->hasColors()) //yes if no material is available!
				//{
				//	ccLog::Print("[OBJ] Mesh has no normal! We will compute them automatically");
				//	baseMesh->computeNormals();
				//	baseMesh->showNormals(true);
				//}
				//else
				{
					ccLog::Warning("[OBJ] Mesh has no normal! You can manually compute them (select it then call \"Edit > Normals > Compute\")");
				}
			}

			//create sub-meshes if necessary
			ccLog::Print("[OBJ] 1 mesh loaded - %i group(s)", groups.size());
			if (groups.size() > 1)
			{
				for (size_t i=0; i<groups.size(); ++i)
				{
					const QString& groupName = groups[i].second;
					unsigned startIndex = groups[i].first;
					unsigned endIndex = (i+1 == groups.size() ? baseMesh->size() : groups[i+1].first);

					if (startIndex == endIndex)
					{
						continue;
					}

					ccSubMesh* subTri = new ccSubMesh(baseMesh);
					if (subTri->reserve(endIndex-startIndex))
					{
						subTri->addTriangleIndex(startIndex,endIndex);
						subTri->setName(groupName);
						subTri->showMaterials(baseMesh->materialsShown());
						subTri->showNormals(baseMesh->normalsShown());
						subTri->showTriNorms(baseMesh->triNormsShown());
						//subTri->showColors(baseMesh->colorsShown());
						//subTri->showWired(baseMesh->isShownAsWire());
						baseMesh->addChild(subTri);
					}
					else
					{
						delete subTri;
						subTri = 0;
						objWarnings[NOT_ENOUGH_MEMORY] = true;
					}
				}
				baseMesh->setVisible(false);
				vertices->setLocked(true);
			}

			baseMesh->addChild(vertices);
			//DGM: we can't deactive the vertices if it has children! (such as polyline)
			if (vertices->getChildrenNumber() != 0)
				vertices->setVisible(false);
			else
				vertices->setEnabled(false);

			container.addChild(baseMesh);
		}

		if (!baseMesh && vertices->size() != 0)
		{
			//no (valid) mesh!
			container.addChild(vertices);
			//we hide the vertices if the entity has children (probably polylines!)
			if (vertices->getChildrenNumber() != 0)
			{
				vertices->setVisible(false);
			}
		}

		//special case: normals held by cloud!
		if (normals && !normalsPerFacet)
		{
			if (normsRead == pointsRead) //must be 'per-vertex' normals
			{
				vertices->setNormsTable(normals);
				if (baseMesh)
					baseMesh->showNormals(true);
			}
			else
			{
				ccLog::Warning("File contains normals which seem to be neither per-vertex nor per-face!!! We had to ignore them...");
			}
		}
	}

	if (error)
	{
		if (baseMesh)
			delete baseMesh;
		if (vertices)
			delete vertices;
	}

	//release shared structures
	if (normals)
	{
		normals->release();
		normals = 0;
	}
	if (texCoords)
	{
		texCoords->release();
		texCoords = 0;
	}
	if (materials)
	{
		materials->release();
		materials = 0;
	}

	pDlg.close();

	//potential warnings
	if (objWarnings[INVALID_NORMALS])
		ccLog::Warning("[OBJ] Some normals in file were invalid. You should re-compute them (select entity, then \"Edit > Normals > Compute\")");
	if (objWarnings[INVALID_INDEX])
		ccLog::Warning("[OBJ] File is malformed! Check indexes...");
	if (objWarnings[NOT_ENOUGH_MEMORY])
		ccLog::Warning("[OBJ] Not enough memory!");
	if (objWarnings[INVALID_LINE])
		ccLog::Warning("[OBJ] File is malformed! Missing data.");

	if (error)
	{
		if (objWarnings[NOT_ENOUGH_MEMORY])
			return CC_FERR_NOT_ENOUGH_MEMORY;
		else if (objWarnings[CANCELLED_BY_USER])
			return CC_FERR_CANCELED_BY_USER;
		else 
			return CC_FERR_MALFORMED_FILE;
	}
	else
	{
		return CC_FERR_NO_ERROR;
	}
}
Esempio n. 29
0
CC_FILE_ERROR BinFilter::loadFile(QString filename, ccHObject& container, LoadParameters& parameters)
{
	ccLog::Print(QString("[BIN] Opening file '%1'...").arg(filename));

	//opening file
	QFile in(filename);
	if (!in.open(QIODevice::ReadOnly))
		return CC_FERR_READING;

	uint32_t firstBytes = 0;
	if (in.read((char*)&firstBytes,4) < 0)
		return CC_FERR_READING;
	bool v1 = (strncmp((char*)&firstBytes,"CCB",3) != 0);

	if (v1)
	{
		return LoadFileV1(in, container, static_cast<unsigned>(firstBytes), parameters); //firstBytes == number of scans for V1 files!
	}
	else
	{
		//Since ver 2.5.2, the 4th character of the header corresponds to 'load flags'
		int flags = 0;
		{
			QChar c(reinterpret_cast<char*>(&firstBytes)[3]);
			bool ok;
			flags = QString(c).toInt(&ok);
			if (!ok || flags > 8)
			{
				ccLog::Error(QString("Invalid file header (4th byte is '%1'?!)").arg(c));
				return CC_FERR_WRONG_FILE_TYPE;
			}
		}

		//if (sizeof(PointCoordinateType) == 8 && strncmp((char*)&firstBytes,"CCB3",4) != 0)
		//{
		//	QMessageBox::information(0, QString("Wrong version"), QString("This file has been generated with the standard 'float' version!\nAt this time it cannot be read with the 'double' version."),QMessageBox::Ok);
		//	return CC_FERR_WRONG_FILE_TYPE;
		//}
		//else if (sizeof(PointCoordinateType) == 4 && strncmp((char*)&firstBytes,"CCB2",4) != 0)
		//{
		//	QMessageBox::information(0, QString("Wrong version"), QString("This file has been generated with the new 'double' version!\nAt this time it cannot be read with the standard 'float' version."),QMessageBox::Ok);
		//	return CC_FERR_WRONG_FILE_TYPE;
		//}

		if (parameters.alwaysDisplayLoadDialog)
		{
			ccProgressDialog pDlg(false, parameters.parentWidget);
			pDlg.setMethodTitle(QObject::tr("BIN file"));
			pDlg.setInfo(QObject::tr("Loading: %1").arg(QFileInfo(filename).fileName()));
			pDlg.setRange(0, 0);
			pDlg.show();

			//concurrent call in a separate thread
			s_file = &in;
			s_container = &container;
			s_flags = flags;

			QFuture<CC_FILE_ERROR> future = QtConcurrent::run(_LoadFileV2);

			while (!future.isFinished())
			{
	#if defined(CC_WINDOWS)
				::Sleep(500);
	#else
				usleep(500 * 1000);
	#endif
				pDlg.setValue(pDlg.value()+1);
				//pDlg.setValue(static_cast<int>(in.pos())); //DGM: in fact, the file reading part is just half of the work!
				QApplication::processEvents();
			}
	
			s_file = 0;
			s_container = 0;

			return future.result();
		}
		else
		{
			return BinFilter::LoadFileV2(in,container,flags);
		}
	}
}
Esempio n. 30
0
void CMatchingDlg::EditPreferences(void)
{
	CEditProjectDlg pDlg(GTK_WINDOW(m_pDlg));
	pDlg.Execute(PAGE_MATCHING);
}