예제 #1
0
void tst_QFuture::futureInterface()
{
    {
        QFuture<void> future;
        {
            QFutureInterface<void> i;
            i.reportStarted();
            future = i.future();
            i.reportFinished();
        }
    }
    {
        QFuture<int> future;
        {
            QFutureInterface<int> i;
            i.reportStarted();
            i.reportResult(10);
            future = i.future();
            i.reportFinished();
        }
        QCOMPARE(future.resultAt(0), 10);
    }

    {
        QFuture<int> intFuture;

        QCOMPARE(intFuture.isStarted(), true);
        QCOMPARE(intFuture.isFinished(), true);

        IntResult result;

        result.reportStarted();
        intFuture = result.future();

        QCOMPARE(intFuture.isStarted(), true);
        QCOMPARE(intFuture.isFinished(), false);

        result.reportFinished(&value);

        QCOMPARE(intFuture.isStarted(), true);
        QCOMPARE(intFuture.isFinished(), true);

        int e = intFuture.result();

        QCOMPARE(intFuture.isStarted(), true);
        QCOMPARE(intFuture.isFinished(), true);
        QCOMPARE(intFuture.isCanceled(), false);

        QCOMPARE(e, value);
        intFuture.waitForFinished();

        IntResult intAlgo;
        intFuture = intAlgo.run();
        QFuture<int> intFuture2(intFuture);
        QCOMPARE(intFuture.result(), value);
        QCOMPARE(intFuture2.result(), value);
        intFuture.waitForFinished();

        VoidResult a;
        a.run().waitForFinished();
    }
}
예제 #2
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);
		}
	}
}
예제 #3
0
파일: qRANSAC_SD.cpp 프로젝트: imight/trunk
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();		
		}
	}
}
예제 #4
0
void qPoissonRecon::doAction()
{
	assert(m_app);
	if (!m_app)
	{
		return;
	}

	const ccHObject::Container& selectedEntities = m_app->getSelectedEntities();

	//we need one point cloud
	size_t selNum = selectedEntities.size();
	if (selNum != 1)
	{
		m_app->dispToConsole("Select only one cloud!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
		return;
	}

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

	//with normals!
	ccPointCloud* pc = static_cast<ccPointCloud*>(ent);
	if (!pc->hasNormals())
	{
		m_app->dispToConsole("Cloud must have normals!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
		return;
	}

	bool cloudHasColors = pc->hasColors();
	PoissonReconParamDlg prpDlg(m_app->getMainWindow());
	prpDlg.importColorsCheckBox->setVisible(cloudHasColors);

	//init dialog with semi-persistent settings
	prpDlg.octreeLevelSpinBox->setValue(s_params.depth);
	prpDlg.weightDoubleSpinBox->setValue(s_params.pointWeight);
	prpDlg.fullDepthSpinBox->setValue(s_params.fullDepth);
	prpDlg.samplesPerNodeSpinBox->setValue(s_params.samplesPerNode);
	prpDlg.densityCheckBox->setChecked(s_params.density);
	prpDlg.importColorsCheckBox->setChecked(true);

	if (!prpDlg.exec())
		return;

	//set parameters with dialog settings
	s_params.depth = prpDlg.octreeLevelSpinBox->value();
	s_params.pointWeight = static_cast<float>(prpDlg.weightDoubleSpinBox->value());
	s_params.fullDepth = prpDlg.fullDepthSpinBox->value();
	s_params.samplesPerNode = static_cast<float>(prpDlg.samplesPerNodeSpinBox->value());
	s_params.density = prpDlg.densityCheckBox->isChecked();
	bool withColors = pc->hasColors() && prpDlg.importColorsCheckBox->isChecked();

	/*** RECONSTRUCTION PROCESS ***/

	PoissonMesh mesh;
	ColoredPoissonMesh coloredMesh;
	s_cloud = 0;
	s_mesh = 0;
	s_coloredMesh = 0;

	//run in a separate thread
	bool result = false;
	{
		//start message
		m_app->dispToConsole(QString("[PoissonRecon] Job started (level %1)").arg(s_params.depth),ccMainAppInterface::STD_CONSOLE_MESSAGE);

		//progress dialog (Qtconcurrent::run can't be canceled!)
		QProgressDialog pDlg("Initialization", QString(), 0, 0, m_app->getMainWindow());
		pDlg.setWindowTitle("Poisson Reconstruction");
		pDlg.show();
		//QApplication::processEvents();

		pDlg.setLabelText(QString("Reconstruction in progress\nlevel: %1 [%2 thread(s)]").arg(s_params.depth).arg(s_params.threads));
		QApplication::processEvents();

		QFuture<bool> future;
			
		//run in a separate thread
		s_cloud = pc;
		if (withColors)
		{
			s_coloredMesh = &coloredMesh;
			future = QtConcurrent::run(doReconstructWithColors);
		}
		else
		{
			s_mesh = &mesh;
			future = QtConcurrent::run(doReconstruct);
		}

		//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();
		}

		result = future.result();

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

	if (result
		&&	(!s_mesh || s_mesh->polygonCount() > 0)
		&&	(!s_coloredMesh || s_coloredMesh->polygonCount() > 0))
	{
		unsigned nic = 0, noc = 0, nr_faces = 0;
		if (s_coloredMesh)
		{
			s_coloredMesh->resetIterator();
			nic			= static_cast<unsigned>(s_coloredMesh->inCorePoints.size());
			noc			= static_cast<unsigned>(s_coloredMesh->outOfCorePointCount());
			nr_faces	= static_cast<unsigned>(s_coloredMesh->polygonCount());
		}
		else //if (s_mesh)
		{
			s_mesh->resetIterator();
			nic			= static_cast<unsigned>(s_mesh->inCorePoints.size());
			noc			= static_cast<unsigned>(s_mesh->outOfCorePointCount());
			nr_faces	= static_cast<unsigned>(s_mesh->polygonCount());
		}
		unsigned nr_vertices = nic+noc;

		//end message
		m_app->dispToConsole(QString("[PoissonRecon] Job finished (%1 triangles, %2 vertices)").arg(nr_faces).arg(nr_vertices),ccMainAppInterface::STD_CONSOLE_MESSAGE);

		ccPointCloud* newPC = new ccPointCloud("vertices");
		ccMesh* newMesh = new ccMesh(newPC);
		newMesh->addChild(newPC);

		if (newPC->reserve(nr_vertices) && newMesh->reserve(nr_faces))
		{
			ccScalarField* densitySF = 0;
			if (s_params.density)
			{
				densitySF = new ccScalarField("Density");
				if (!densitySF->reserve(nr_vertices))
				{
					m_app->dispToConsole(QString("[PoissonRecon] Failed to allocate memory for storing density!"),ccMainAppInterface::WRN_CONSOLE_MESSAGE);
					densitySF->release();
					densitySF = 0;
				}
			}

			if (s_coloredMesh)
			{
				bool importColors = newPC->reserveTheRGBTable();
				if (!importColors)
				{
					if (m_app)
						m_app->dispToConsole("Not enough memory to import colors!", ccMainAppInterface::ERR_CONSOLE_MESSAGE);
				}
				//add 'in core' points
				{
					for (unsigned i=0; i<nic; i++)
					{
						ColoredVertex& p = s_coloredMesh->inCorePoints[i];
						CCVector3 p2(	static_cast<PointCoordinateType>(p.point.coords[0]),
										static_cast<PointCoordinateType>(p.point.coords[1]),
										static_cast<PointCoordinateType>(p.point.coords[2]) );
						newPC->addPoint(p2);

						if (importColors)
						{
							newPC->addRGBColor(p.color);
						}

						if (densitySF)
						{
							ScalarType sf = static_cast<ScalarType>(p.value);
							densitySF->addElement(sf);
						}
					}
				}
				//add 'out of core' points
				{
					for (unsigned i=0; i<noc; i++)
					{
						ColoredVertex p;
						s_coloredMesh->nextOutOfCorePoint(p);
						CCVector3 p2(	static_cast<PointCoordinateType>(p.point.coords[0]),
										static_cast<PointCoordinateType>(p.point.coords[1]),
										static_cast<PointCoordinateType>(p.point.coords[2]) );
						newPC->addPoint(p2);

						if (importColors)
						{
							newPC->addRGBColor(p.color);
						}

						if (densitySF)
						{
							ScalarType sf = static_cast<ScalarType>(p.value);
							densitySF->addElement(sf);
						}
					}
				}

				newPC->showColors(importColors);
			}
			else
			{
				//add 'in core' points
				{
					for (unsigned i=0; i<nic; i++)
					{
						Vertex& p = s_mesh->inCorePoints[i];
						CCVector3 p2(	static_cast<PointCoordinateType>(p.point.coords[0]),
										static_cast<PointCoordinateType>(p.point.coords[1]),
										static_cast<PointCoordinateType>(p.point.coords[2]) );
						newPC->addPoint(p2);

						if (densitySF)
						{
							ScalarType sf = static_cast<ScalarType>(p.value);
							densitySF->addElement(sf);
						}
					}
				}
				//add 'out of core' points
				{
					for (unsigned i=0; i<noc; i++)
					{
						Vertex p;
						s_mesh->nextOutOfCorePoint(p);
						CCVector3 p2(	static_cast<PointCoordinateType>(p.point.coords[0]),
										static_cast<PointCoordinateType>(p.point.coords[1]),
										static_cast<PointCoordinateType>(p.point.coords[2]) );
						newPC->addPoint(p2);

						if (densitySF)
						{
							ScalarType sf = static_cast<ScalarType>(p.value);
							densitySF->addElement(sf);
						}
					}
				}
				newPC->showColors(false);
			}

			// density SF
			if (densitySF)
			{
				densitySF->computeMinAndMax();
				densitySF->showNaNValuesInGrey(false);
				int sfIdx = newPC->addScalarField(densitySF);
				newPC->setCurrentDisplayedScalarField(sfIdx);
				newPC->showSF(true);
				newMesh->showColors(newPC->colorsShown());
				newMesh->showSF(true);
			}

			//add faces
			{
				for (unsigned i=0; i<nr_faces; i++)
				{
					std::vector<CoredVertexIndex> triangleIndexes;
					if (s_mesh)
						s_mesh->nextPolygon(triangleIndexes);
					else
						s_coloredMesh->nextPolygon(triangleIndexes);

					if (triangleIndexes.size() == 3)
					{
						for (std::vector<CoredVertexIndex>::iterator it = triangleIndexes.begin(); it != triangleIndexes.end(); ++it)
							if (!it->inCore)
								it->idx += nic;

						newMesh->addTriangle(	triangleIndexes[0].idx,
												triangleIndexes[1].idx,
												triangleIndexes[2].idx );
					}
					else
					{
						//Can't handle anything else than triangles yet!
						assert(false);
					}
				}
			}

			newMesh->setName(QString("Mesh[%1] (level %2)").arg(pc->getName()).arg(s_params.depth));
			newPC->setEnabled(false);
			newMesh->setVisible(true);
			newMesh->computeNormals(true);
			newMesh->showColors(newMesh->hasColors());

			//copy Global Shift & Scale information
			newPC->setGlobalShift(pc->getGlobalShift());
			newPC->setGlobalScale(pc->getGlobalScale());

			//output mesh
			m_app->addToDB(newMesh);
		}
		else
		{
			delete newMesh;
			newMesh = 0;
			m_app->dispToConsole("Not enough memory!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
		}

		//currently selected entities parameters may have changed!
		m_app->updateUI();
		//currently selected entities appearance may have changed!
		m_app->refreshAll();
	}
	else
	{
		m_app->dispToConsole("Reconstruction failed!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
	}

	s_cloud = 0;
	s_mesh = 0;
	s_coloredMesh = 0;
}
예제 #5
0
//-------------------------------------------------------------------------------------------
Kst::Object::UpdateType AsciiSource::internalDataSourceUpdate(bool read_completely)
{
  //MeasureTime t("AsciiSource::internalDataSourceUpdate: " + _filename);
  if (_busy)
    return NoChange;

  // forget about cached data
  _fileBuffer.clear();

  if (!_haveHeader) {
    _haveHeader = initRowIndex();
    if (!_haveHeader) {
      return NoChange;
    }
  }
  updateLists();

  QFile file(_filename);
  if (!AsciiFileBuffer::openFile(file)) {
    // Qt: If the device is closed, the size returned will not reflect the actual size of the device.
    return NoChange;
  }

  if (_updatesDisabled) {
    _fileSize = 0;
  } else {
    _fileSize = file.size();
  }

  bool force_update = true;
  if (_fileSize == file.size()) {
    force_update = false;
  }

  _fileCreationTime_t = QFileInfo(file).created().toTime_t();

  int col_count = _fieldList.size() - 1; // minus INDEX

  bool new_data = false;
  // emit progress message if there are more than 100 MB to parse
  if (_fileSize - _lastFileSize > 100 * 1024 * 1024 && read_completely) {
    _showFieldProgress = true;
    emitProgress(1, tr("Parsing '%1' ...").arg(_filename));
    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
    QFuture<bool> future = QtConcurrent::run(&_reader, &AsciiDataReader::findAllDataRows, read_completely, &file, _fileSize, col_count);
    _busy = true;
    while (_busy) {
      if (future.isFinished()) {
        try {
          new_data = future;
        } catch ( const std::exception&) {
          // TODO out of memory?
        }
        _busy = false;
        emitProgress(50, tr("Finished parsing '%1'").arg(_filename));
      } else {
        ms::sleep(500);
        emitProgress(1 + 99.0 * _reader.progressValue() / 100.0, tr("Parsing '%1': %2 rows").arg(_filename).arg(QString::number(_reader.progressRows())));
        QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
      }
    }
  } else {
    _showFieldProgress = false;
    new_data = _reader.findAllDataRows(read_completely, &file, _fileSize, col_count);
  }

  _lastFileSize = _fileSize;

  return (!new_data && !force_update ? NoChange : Updated);
}
예제 #6
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();
}
예제 #7
0
    bool generateImagesAndXML()
    {
        QString baseDestDir=mInfo->destUrl().toLocalFile();
        if (!createDir(baseDestDir)) return false;

        mXMLFileName=baseDestDir + "/gallery.xml";
        XMLWriter xmlWriter;
        if (!xmlWriter.open(mXMLFileName))
        {
            logError(i18n("Could not create gallery.xml"));
            return false;
        }

        XMLElement collectionsX(xmlWriter, "collections");

        // Loop on collections
        QList<ImageCollection>::ConstIterator collectionIt=mInfo->mCollectionList.constBegin();
        QList<ImageCollection>::ConstIterator collectionEnd=mInfo->mCollectionList.constEnd();
        for (; collectionIt!=collectionEnd; ++collectionIt)
        {
            ImageCollection collection=*collectionIt;

            QString collectionFileName = webifyFileName(collection.name());
            QString destDir = baseDestDir + '/' + collectionFileName;
            if (!createDir(destDir)) return false;

            XMLElement collectionX(xmlWriter, "collection");
            xmlWriter.writeElement("name", collection.name());
            xmlWriter.writeElement("fileName", collectionFileName);
            xmlWriter.writeElement("comment", collection.comment());

            // Gather image element list
            KUrl::List imageList = collection.images();
            RemoteUrlHash remoteUrlHash;
            if (!downloadRemoteUrls(collection.name(), imageList, &remoteUrlHash))
            {
                return false;
            }
            QList<ImageElement> imageElementList;
            Q_FOREACH(const KUrl& url, imageList)
            {
                const QString path = remoteUrlHash.value(url, url.toLocalFile());
                if (path.isEmpty())
                {
                    continue;
                }
                KPImageInfo info(url);
                ImageElement element = ImageElement(info);
                element.mPath        = remoteUrlHash.value(url, url.toLocalFile());
                imageElementList << element;
            }

            // Generate images
            logInfo( i18n("Generating files for \"%1\"", collection.name()) );
            ImageGenerationFunctor functor(that, mInfo, destDir);
            QFuture<void> future = QtConcurrent::map(imageElementList, functor);
            QFutureWatcher<void> watcher;
            watcher.setFuture(future);
            connect(&watcher, SIGNAL(progressValueChanged(int)),
                    mProgressDialog->progressWidget(), SLOT(setProgress(int)));

            mProgressDialog->progressWidget()->setTotal(imageElementList.count());
            while (!future.isFinished())
            {
                qApp->processEvents();
                if (mProgressDialog->isHidden())
                {
                    future.cancel();
                    future.waitForFinished();
                    return false;
                }
            }

            // Generate xml
            Q_FOREACH(const ImageElement& element, imageElementList)
            {
                element.appendToXML(xmlWriter, mInfo->copyOriginalImage());
            }
        }
예제 #8
0
int qPoissonReconPlugin::doAction(ccHObject::Container& selectedEntities,
								  unsigned& uiModificationFlags,
								  ccProgressDialog* progressCb/*=NULL*/,
								  QWidget* parent/*=NULL*/)
{
	//we need one point cloud
    unsigned selNum = selectedEntities.size();
    if (selNum!=1)
        return -1;

	//a real point cloud
    ccHObject* ent = selectedEntities[0];
	if (!ent->isA(CC_POINT_CLOUD))
		return -1;

	//with normals!
    ccPointCloud* pc = static_cast<ccPointCloud*>(ent);
	if (!pc->hasNormals())
		return -2;

	bool ok;
	#if (QT_VERSION >= QT_VERSION_CHECK(4, 5, 0))
	int depth = QInputDialog::getInt(0, "Poisson reconstruction","Octree depth:", 8, 1, 24, 1, &ok);
	#else
	int depth = QInputDialog::getInteger(0, "Poisson reconstruction","Octree depth:", 8, 1, 24, 1, &ok);
	#endif

	if (!ok)
		return 1;

	 //TODO: faster, lighter
	unsigned i,count = pc->size();
	float* points = new float[count*3];
	if (!points)
		return -3;
	float* normals = new float[count*3];
	if (!normals)
	{
		delete[] points;
		return -3;
	}

	float* _points = points;
	float* _normals = normals;
	for (i=0;i<count;++i)
	{
		const CCVector3* P = pc->getPoint(i);
		*_points++ = (float)P->x;
		*_points++ = (float)P->y;
		*_points++ = (float)P->z;

		const PointCoordinateType* N = pc->getPointNormal(i);
		*_normals++ = (float)N[0];
		*_normals++ = (float)N[1];
		*_normals++ = (float)N[2];
	}

	/*** RECONSTRUCTION PROCESS ***/

	CoredVectorMeshData mesh;
	PoissonReconLib::PoissonReconResultInfo info;
	bool result = false;

	if (progressCb)
	{
		progressCb->setCancelButton(0);
		progressCb->setRange(0,0);
		progressCb->setInfo("Operation in progress");
		progressCb->setMethodTitle("Poisson Reconstruction");
		progressCb->start();
		//QApplication::processEvents();

		//run in a separate thread
		s_points = points;
		s_normals = normals;
		s_count = count;
		s_depth = depth;
		s_mesh = &mesh;
		s_info = &info;
		QFuture<void> future = QtConcurrent::run(doReconstruct);

		unsigned progress = 0;
		while (!future.isFinished())
		{
		    #if defined(_WIN32) || defined(WIN32)
			::Sleep(500);
			#else
			sleep(500);
			#endif

			progressCb->update(++progress);
			//Qtconcurrent::run can't be canceled!
			/*if (progressCb->isCancelRequested())
			{
				future.cancel();
				future.waitForFinished();
				s_result = false;
				break;
			}
			//*/
		}

		result = s_result;

		progressCb->stop();
		QApplication::processEvents();
	}
	else
	{
		result = PoissonReconLib::reconstruct(count, points, normals, mesh, depth, &info);
	}

	delete[] points;
	points=0;
	delete[] normals;
	normals=0;

	if (!result || mesh.polygonCount() < 1)
		return -4;

	unsigned nic         = (unsigned)mesh.inCorePoints.size();
	unsigned noc         = (unsigned)mesh.outOfCorePointCount();
	unsigned nr_vertices = nic+noc;
	unsigned nr_faces    = (unsigned)mesh.polygonCount();

	ccPointCloud* newPC = new ccPointCloud("vertices");
	newPC->reserve(nr_vertices);

	//we enlarge bounding box a little bit (2%)
	PointCoordinateType bbMin[3],bbMax[3];
	pc->getBoundingBox(bbMin,bbMax);
	CCVector3 boxHalfDiag = (CCVector3(bbMax)-CCVector3(bbMin))*0.51f;
	CCVector3 boxCenter = (CCVector3(bbMax)+CCVector3(bbMin))*0.5f;
	CCVector3 filterMin = boxCenter-boxHalfDiag;
	CCVector3 filterMax = boxCenter+boxHalfDiag;

	Point3D<float> p;
	CCVector3 p2;
	for (i=0; i<nic; i++)
	{
		p = mesh.inCorePoints[i];
		p2.x = p.coords[0]*info.scale+info.center[0];
		p2.y = p.coords[1]*info.scale+info.center[1];
		p2.z = p.coords[2]*info.scale+info.center[2];
		newPC->addPoint(p2);
	}
	for (i=0; i<noc; i++)
	{
		mesh.nextOutOfCorePoint(p);
		p2.x = p.coords[0]*info.scale+info.center[0];
		p2.y = p.coords[1]*info.scale+info.center[1];
		p2.z = p.coords[2]*info.scale+info.center[2];
		newPC->addPoint(p2);
	}

	ccMesh* newMesh = new ccMesh(newPC);
	newMesh->setName(QString("Mesh[%1] (level %2)").arg(pc->getName()).arg(depth));
	newMesh->reserve(nr_faces);
	newMesh->addChild(newPC);

	std::vector<CoredVertexIndex> vertices;
	for (i=0; i < nr_faces; i++)
	{
		mesh.nextPolygon(vertices);

		if (vertices.size()!=3)
		{
			//Can't handle anything else than triangles yet!
			assert(false);
		}
		else
		{
			for (std::vector<CoredVertexIndex>::iterator it = vertices.begin(); it != vertices.end(); ++it)
				if (!it->inCore)
					it->idx += nic;

			newMesh->addTriangle(vertices[0].idx,
								vertices[1].idx,
								vertices[2].idx);
		}
	}

	newPC->setVisible(false);
	newMesh->setVisible(true);
	newMesh->computeNormals();

	//output mesh
	selectedEntities.push_back(newMesh);

	//currently selected entities parameters may have changed!
    uiModificationFlags |= CC_PLUGIN_REFRESH_ENTITY_BROWSER;
    //currently selected entities appearance may have changed!
    uiModificationFlags |= CC_PLUGIN_REFRESH_GL_WINDOWS;

    return 1;
}