Ejemplo n.º 1
0
ccQuadric* ccQuadric::Fit(CCLib::GenericIndexedCloudPersist *cloud, double* rms/*=0*/)
{
	//number of points
	unsigned count = cloud->size();
	if (count < CC_LOCAL_MODEL_MIN_SIZE[HF])
	{
		ccLog::Warning(QString("[ccQuadric::fitTo] Not enough points in input cloud to fit a quadric! (%1 at the very least are required)").arg(CC_LOCAL_MODEL_MIN_SIZE[HF]));
		return 0;
	}

	//project the points on a 2D plane
	CCVector3 G, X, Y, N;
	{
		CCLib::Neighbourhood Yk(cloud);
		
		//plane equation
		const PointCoordinateType* theLSQPlane = Yk.getLSQPlane();
		if (!theLSQPlane)
		{
			ccLog::Warning("[ccQuadric::Fit] Not enough points to fit a quadric!");
			return 0;
		}

		assert(Yk.getGravityCenter());
		G = *Yk.getGravityCenter();

		//local base
		N = CCVector3(theLSQPlane);
		assert(Yk.getLSQPlaneX() && Yk.getLSQPlaneY());
		X = *Yk.getLSQPlaneX(); //main direction
		Y = *Yk.getLSQPlaneY(); //secondary direction
	}

	//project the points in a temporary cloud
	ccPointCloud tempCloud("temporary");
	if (!tempCloud.reserve(count))
	{
		ccLog::Warning("[ccQuadric::Fit] Not enough memory!");
		return 0;
	}

	cloud->placeIteratorAtBegining();
	for (unsigned k=0; k<count; ++k)
	{
		//projection into local 2D plane ref.
		CCVector3 P = *(cloud->getNextPoint()) - G;

		tempCloud.addPoint(CCVector3(P.dot(X),P.dot(Y),P.dot(N)));
	}

	CCLib::Neighbourhood Zk(&tempCloud);
	{
		//set exact values for gravity center and plane equation
		//(just to be sure and to avoid re-computing them)
		Zk.setGravityCenter(CCVector3(0,0,0));
		PointCoordinateType perfectEq[4] = { 0, 0, 1, 0 };
		Zk.setLSQPlane(	perfectEq,
						CCVector3(1,0,0),
						CCVector3(0,1,0),
						CCVector3(0,0,1));
	}

	uchar hfdims[3];
	const PointCoordinateType* eq = Zk.getHeightFunction(hfdims);
	if (!eq)
	{
		ccLog::Warning("[ccQuadric::Fit] Failed to fit a quadric!");
		return 0;
	}

	//we recenter the quadric object
	ccGLMatrix glMat(X,Y,N,G);

	ccBBox bb = tempCloud.getBB();
	CCVector2 minXY(bb.minCorner().x,bb.minCorner().y);
	CCVector2 maxXY(bb.maxCorner().x,bb.maxCorner().y);

	ccQuadric* quadric = new ccQuadric(minXY, maxXY, eq, hfdims, &glMat);

	quadric->setMetaData(QString("Equation"),QVariant(quadric->getEquationString()));

	//compute rms if necessary
	if (rms)
	{
		const uchar& dX = hfdims[0];
		const uchar& dY = hfdims[1];
//		const uchar& dZ = hfdims[2];

		*rms = 0;

		for (unsigned k=0; k<count; ++k)
		{
			//projection into local 2D plane ref.
			const CCVector3* P = tempCloud.getPoint(k);

			PointCoordinateType z = eq[0] + eq[1]*P->u[dX] + eq[2]*P->u[dY] + eq[3]*P->u[dX]*P->u[dX] + eq[4]*P->u[dX]*P->u[dY] + eq[5]*P->u[dY]*P->u[dY];
			*rms += (z-P->z)*(z-P->z);
		}

		if (count)
		{
			*rms = sqrt(*rms / count);
			quadric->setMetaData(QString("RMS"),QVariant(*rms));
		}
	}
	
	return quadric;
}
Ejemplo n.º 2
0
ccBBox ccQuadric::getFitBB(ccGLMatrix& trans)
{
	trans = m_transformation;
	return ccBBox( CCVector3(m_minCorner.x,m_minCorner.y,m_minZ), CCVector3(m_maxCorner.x,m_maxCorner.y,m_maxZ) );
}
Ejemplo n.º 3
0
CCVector3 ccUnrollDlg::getAxisPosition()
{
    return CCVector3(static_cast<PointCoordinateType>(doubleSpinBoxAxisX->value()),
                     static_cast<PointCoordinateType>(doubleSpinBoxAxisY->value()),
                     static_cast<PointCoordinateType>(doubleSpinBoxAxisZ->value()));
}
Ejemplo n.º 4
0
void qPCV::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 or one mesh!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
        return;
    }

    ccHObject* ent = selectedEntities[0];

    ccGenericPointCloud* cloud = NULL;
    ccGenericMesh* mesh = NULL;
    if (ent->isKindOf(CC_TYPES::POINT_CLOUD))
    {
        cloud = ccHObjectCaster::ToGenericPointCloud(ent);
    }
    else if (ent->isKindOf(CC_TYPES::MESH))
    {
        mesh = static_cast<ccGenericMesh*>(ent);
        cloud = mesh->getAssociatedCloud();
    }
    else
    {
        m_app->dispToConsole("Select a point cloud or a mesh!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
        return;
    }

    if (!cloud->isA(CC_TYPES::POINT_CLOUD)) //TODO
    {
        m_app->dispToConsole("Select a real point cloud (or a mesh associated to a real point cloud)!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
        return;
    }
    ccPointCloud* pc = static_cast<ccPointCloud*>(cloud);

    ccPcvDlg dlg(m_app->getMainWindow());

    //restore previous dialog state
    if (!s_firstLaunch)
    {
        dlg.raysSpinBox->setValue(s_raysSpinBoxValue);
        dlg.mode180CheckBox->setChecked(s_mode180CheckBoxState);
        dlg.resSpinBox->setValue(s_resSpinBoxValue);
        dlg.closedMeshCheckBox->setChecked(s_closedMeshCheckBoxState);
    }

    //for meshes only
    if (!mesh)
        dlg.closedMeshCheckBox->setEnabled(false);

    //for using clouds normals as rays
    std::vector<ccGenericPointCloud*> cloudsWithNormals;
    ccHObject* root = m_app->dbRootObject();
    if (root)
    {
        ccHObject::Container clouds;
        root->filterChildren(clouds,true,CC_TYPES::POINT_CLOUD);
        for (size_t i=0; i<clouds.size(); ++i)
        {
            //we keep only clouds with normals
            ccGenericPointCloud* cloud = ccHObjectCaster::ToGenericPointCloud(clouds[i]);
            if (cloud && cloud->hasNormals())
            {
                cloudsWithNormals.push_back(cloud);
                QString cloudTitle = QString("%1 - %2 points").arg(cloud->getName()).arg(cloud->size());
                if (cloud->getParent() && cloud->getParent()->isKindOf(CC_TYPES::MESH))
                    cloudTitle.append(QString(" (%1)").arg(cloud->getParent()->getName()));

                dlg.cloudsComboBox->addItem(cloudTitle);
            }
        }
    }
    if (cloudsWithNormals.empty())
        dlg.useCloudRadioButton->setEnabled(false);

    if (!dlg.exec())
        return;

    //save dialog state
    {
        s_firstLaunch				= false;
        s_raysSpinBoxValue			= dlg.raysSpinBox->value();
        s_mode180CheckBoxState		= dlg.mode180CheckBox->isChecked();
        s_resSpinBoxValue			= dlg.resSpinBox->value();
        s_closedMeshCheckBoxState	= dlg.closedMeshCheckBox->isChecked();
    }

    //we get the PCV field if it already exists
    int sfIdx = pc->getScalarFieldIndexByName(CC_PCV_FIELD_LABEL_NAME);
    //otherwise we create it
    if (sfIdx < 0)
        sfIdx = pc->addScalarField(CC_PCV_FIELD_LABEL_NAME);
    if (sfIdx < 0)
    {
        m_app->dispToConsole("Couldn't allocate a new scalar field for computing PCV field ! Try to free some memory ...",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
        return;
    }

    pc->setCurrentScalarField(sfIdx);

    unsigned raysNumber = dlg.raysSpinBox->value();
    unsigned res = dlg.resSpinBox->value();
    bool meshIsClosed = (mesh ? dlg.closedMeshCheckBox->checkState()==Qt::Checked : false);
    bool mode360 = !dlg.mode180CheckBox->isChecked();

    //progress dialog
    ccProgressDialog progressCb(true,m_app->getMainWindow());

    //PCV type ShadeVis
    bool success = false;
    if (!cloudsWithNormals.empty() && dlg.useCloudRadioButton->isChecked())
    {
        //Version with cloud normals as light rays
        assert(dlg.cloudsComboBox->currentIndex() < (int)cloudsWithNormals.size());
        ccGenericPointCloud* pc = cloudsWithNormals[dlg.cloudsComboBox->currentIndex()];
        std::vector<CCVector3> rays;
        unsigned count = pc->size();
        rays.resize(count);
        for (unsigned i=0; i<count; ++i)
            rays[i] = CCVector3(pc->getPointNormal(i));

        success = PCV::Launch(rays,cloud,mesh,meshIsClosed,res,res,&progressCb);
    }
    else
    {
        //Version with rays sampled on a sphere
        success = (PCV::Launch(raysNumber,cloud,mesh,meshIsClosed,mode360,res,res,&progressCb) > 0);
    }

    if (!success)
    {
        pc->deleteScalarField(sfIdx);
        m_app->dispToConsole("En error occurred during the PCV field computation!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
        return;
    }
    else
    {
        pc->getCurrentInScalarField()->computeMinAndMax();
        pc->setCurrentDisplayedScalarField(sfIdx);
        ccScalarField* sf = static_cast<ccScalarField*>(pc->getScalarField(sfIdx));
        if (sf)
            sf->setColorScale(ccColorScalesManager::GetDefaultScale(ccColorScalesManager::GREY));
        ent->showSF(true);
        ent->showNormals(false);
        ent->prepareDisplayForRefresh_recursive();
    }

    //currently selected entities parameters may have changed!
    m_app->updateUI();
    //currently selected entities appearance may have changed!
    m_app->refreshAll();
}
Ejemplo n.º 5
0
CCLib::SimpleCloud* ccGBLSensor::project(CCLib::GenericCloud* theCloud, int& errorCode, bool autoParameters/*false*/)
{
	assert(theCloud);

	CCLib::SimpleCloud* newCloud = new CCLib::SimpleCloud();

	unsigned pointCount = theCloud->size();
	if (!newCloud->reserve(pointCount) || !newCloud->enableScalarField()) //not enough memory
	{
		errorCode = -4;
		delete newCloud;
		return 0;
	}

	ScalarType maxDepth = 0;

	theCloud->placeIteratorAtBegining();
	{
		for (unsigned i=0; i<pointCount; ++i)
		{
			const CCVector3 *P = theCloud->getNextPoint();
			CCVector2 Q;
			ScalarType depth;
			projectPoint(*P,Q,depth);

			newCloud->addPoint(CCVector3(Q.x,Q.y,0));
			newCloud->setPointScalarValue(i,depth);

			if (i != 0)
				maxDepth = std::max(maxDepth,depth);
			else
				maxDepth = depth;
		}
	}

	if (autoParameters)
	{
		//dimensions = theta, phi, 0
		PointCoordinateType bbMin[3],bbMax[3];
		newCloud->getBoundingBox(bbMin,bbMax);

		setTheta(bbMin[0],bbMax[0]);
		setPhi(bbMin[1],bbMax[1]);
		setSensorRange(maxDepth);
	}

	//clear previous Z-buffer
	{
		if (m_depthBuffer.zBuff)
			delete[] m_depthBuffer.zBuff;
		m_depthBuffer.zBuff=0;
		m_depthBuffer.width=0;
		m_depthBuffer.height=0;
	}
	
	//init new Z-buffer
	{
		int width = static_cast<int>(ceil((thetaMax-thetaMin)/deltaTheta));
		int height = static_cast<int>(ceil((phiMax-phiMin)/deltaPhi));

		if (width*height == 0 || std::max(width,height) > 2048) //too small or... too big!
		{
			errorCode = -2;
			delete newCloud;
			return 0;
		}

		unsigned zBuffSize = width*height;
		m_depthBuffer.zBuff = new ScalarType[zBuffSize];
		if (!m_depthBuffer.zBuff) //not enough memory
		{
			errorCode = -4;
			delete newCloud;
			return 0;
		}
		m_depthBuffer.width = width;
		m_depthBuffer.height = height;
		memset(m_depthBuffer.zBuff,0,zBuffSize*sizeof(ScalarType));
	}

	//project points and accumulate them in Z-buffer
	newCloud->placeIteratorAtBegining();
	for (unsigned i=0; i<newCloud->size(); ++i)
	{
		const CCVector3 *P = newCloud->getNextPoint();
		ScalarType depth = newCloud->getPointScalarValue(i);

		int x = static_cast<int>(floor((P->x-thetaMin)/deltaTheta));
		int y = static_cast<int>(floor((P->y-phiMin)/deltaPhi));

		ScalarType& zBuf = m_depthBuffer.zBuff[y*m_depthBuffer.width+x];
		zBuf = std::max(zBuf,depth);
	}

	errorCode = 0;
	return newCloud;
}
Ejemplo n.º 6
0
void ccClipBox::drawMeOnly(CC_DRAW_CONTEXT& context)
{
    if (!MACRO_Draw3D(context))
        return;

    if (!m_box.isValid())
        return;

    //m_box.draw(m_selected ? context.bbDefaultCol : ccColor::magenta);
    m_box.draw(ccColor::yellow);

    //standard case: list names pushing
    bool pushName = MACRO_DrawEntityNames(context);
    if (pushName)
        glPushName(getUniqueIDForDisplay());

    if (m_selected)
    {
        //draw the interactors
        const CCVector3& minC = m_box.minCorner();
        const CCVector3& maxC = m_box.maxCorner();
        CCVector3 center = m_box.getCenter();

        PointCoordinateType scale = computeArrowsScale();

        //custom arrow 'context'
        CC_DRAW_CONTEXT componentContext = context;
        componentContext.flags &= (~CC_DRAW_ENTITY_NAMES); //we must remove the 'push name flag' so that the arows don't push their own!
        componentContext._win = 0;

        //1 if names shall be pushed, 0 otherwise
        if (pushName)
            glPushName(0); //fake ID, will be replaced by the arrows one if any

        DrawUnitArrow(X_MINUS_ARROW*pushName,CCVector3(minC.x,center.y,center.z),CCVector3(-1.0, 0.0, 0.0),scale,ccColor::red,componentContext);
        DrawUnitArrow(X_PLUS_ARROW*pushName,CCVector3(maxC.x,center.y,center.z),CCVector3( 1.0, 0.0, 0.0),scale,ccColor::red,componentContext);
        DrawUnitArrow(Y_MINUS_ARROW*pushName,CCVector3(center.x,minC.y,center.z),CCVector3( 0.0,-1.0, 0.0),scale,ccColor::green,componentContext);
        DrawUnitArrow(Y_PLUS_ARROW*pushName,CCVector3(center.x,maxC.y,center.z),CCVector3( 0.0, 1.0, 0.0),scale,ccColor::green,componentContext);
        DrawUnitArrow(Z_MINUS_ARROW*pushName,CCVector3(center.x,center.y,minC.z),CCVector3( 0.0, 0.0,-1.0),scale,ccColor::blue,componentContext);
        DrawUnitArrow(Z_PLUS_ARROW*pushName,CCVector3(center.x,center.y,maxC.z),CCVector3( 0.0, 0.0, 1.0),scale,ccColor::blue,componentContext);
        DrawUnitCross(CROSS*pushName,minC-CCVector3(scale,scale,scale)/2.0,scale,ccColor::yellow,componentContext);
        //DrawUnitSphere(SPHERE*pushName,maxC+CCVector3(scale,scale,scale)/2.0,scale/2.0,ccColor::yellow,componentContext);
        DrawUnitTorus(X_MINUS_TORUS*pushName,CCVector3(minC.x,center.y,center.z),CCVector3(-1.0, 0.0, 0.0),scale,c_lightRed,componentContext);
        DrawUnitTorus(Y_MINUS_TORUS*pushName,CCVector3(center.x,minC.y,center.z),CCVector3( 0.0,-1.0, 0.0),scale,c_lightGreen,componentContext);
        DrawUnitTorus(Z_MINUS_TORUS*pushName,CCVector3(center.x,center.y,minC.z),CCVector3( 0.0, 0.0,-1.0),scale,c_lightBlue,componentContext);
        DrawUnitTorus(X_PLUS_TORUS*pushName,CCVector3(maxC.x,center.y,center.z),CCVector3( 1.0, 0.0, 0.0),scale,c_lightRed,componentContext);
        DrawUnitTorus(Y_PLUS_TORUS*pushName,CCVector3(center.x,maxC.y,center.z),CCVector3( 0.0, 1.0, 0.0),scale,c_lightGreen,componentContext);
        DrawUnitTorus(Z_PLUS_TORUS*pushName,CCVector3(center.x,center.y,maxC.z),CCVector3( 0.0, 0.0, 1.0),scale,c_lightBlue,componentContext);

        if (pushName)
            glPopName();
    }

    if (pushName)
        glPopName();
}
Ejemplo n.º 7
0
PointCoordinateType* ccGBLSensor::projectNormals(CCLib::GenericCloud* aCloud, GenericChunkedArray<3,PointCoordinateType>& theNorms) const
{
	if (!aCloud || !theNorms.isAllocated())
		return 0;

	unsigned size = 3*m_depthBuffer.height*m_depthBuffer.width;
	if (size == 0)
		return 0; //depth buffer empty/not initialized!

	PointCoordinateType* theNewNorms = new PointCoordinateType[size];
	if (!theNewNorms)
		return 0; //not enough memory
	memset(theNewNorms,0,size*sizeof(PointCoordinateType));

	//poject each point+normal
	{
		aCloud->placeIteratorAtBegining();
		theNorms.placeIteratorAtBegining();
		unsigned pointCount = aCloud->size();
		for (unsigned i=0;i<pointCount;++i)
		{
			const CCVector3* P = aCloud->getNextPoint();
			const PointCoordinateType* N = theNorms.getCurrentValue();

			CCVector3 U = *P - sensorCenter;
			U.x += base;

			CCVector3 S;
			CCVector2 Q;

			PointCoordinateType norm = U.norm();
			if (norm>ZERO_TOLERANCE)
			{
				//normal component along sensor viewing dir.
				S.z = -CCVector3::vdot(N,U.u)/norm;

				if (S.z > 1.0-ZERO_TOLERANCE)
				{
					S.x = 0;
					S.y = 0;
				}
				else
				{
					//project point
					ScalarType depth1;
					projectPoint(*P,Q,depth1);

					//and point+normal
					CCVector3 R = *P + CCVector3(N);
					CCVector2 S2;
					ScalarType depth2;
					projectPoint(R,S2,depth2);

					//deduce other normals components
					PointCoordinateType coef = sqrt((1 - S.z*S.z)/(S.x*S.x + S.y*S.y));
					S.x = coef * (S2.x - Q.x);
					S.y = coef * (S2.y - Q.y);
				}
			}
			else
			{
				S = CCVector3(N);
			}

			//project in Z-buffer
			int x = static_cast<int>(floor((Q.x-thetaMin)/deltaTheta));
			int y = static_cast<int>(floor((Q.y-phiMin)/deltaPhi));

			//on ajoute la normale transformee
			PointCoordinateType* newN = theNewNorms+3*(y*m_depthBuffer.width+x);
			CCVector3::vadd(newN,S.u,newN);

			theNorms.forwardIterator();
		}
	}

	//normalize
	{
		PointCoordinateType* newN = theNewNorms;
		for (int i=0; i<m_depthBuffer.height*m_depthBuffer.width; ++i,newN+=3)
		{
			CCVector3::vnormalize(newN);
		}
	}

	return theNewNorms;
}
Ejemplo n.º 8
0
	virtual void add3dFace(const DL_3dFaceData& face)
	{
		//TODO: understand what this really is?!
		CCVector3 P[4];
		for (unsigned i=0; i<4; ++i)
		{
			P[i] = CCVector3(	static_cast<PointCoordinateType>(face.x[i]),
								static_cast<PointCoordinateType>(face.y[i]),
								static_cast<PointCoordinateType>(face.z[i]) );
		}
		
		//create the 'faces' mesh if necessary
		if (!m_faces)
		{
			ccPointCloud* vertices = new ccPointCloud("vertices");
			m_faces = new ccMesh(vertices);
			m_faces->setName("Faces");
			m_faces->addChild(vertices);
			m_faces->setVisible(true);
			vertices->setEnabled(false);
			vertices->setLocked(true);
			
			m_root->addChild(m_faces);
		}
		
		ccPointCloud* vertices = dynamic_cast<ccPointCloud*>(m_faces->getAssociatedCloud());
		if (!vertices)
		{
			assert(false);
			return;
		}
		
		int vertIndexes[4] = {-1, -1, -1, -1};
		unsigned addedVertCount = 4;
		//check if the two last vertices are the same
		if (P[2].x == P[3].x && P[2].y == P[3].y && P[2].z == P[3].z)
			addedVertCount = 3;

		//current face color
		colorType col[3];
		colorType* faceCol = 0;
		if (getCurrentColour(col))
			faceCol = col;


		//look for already defined vertices
		unsigned vertCount = vertices->size();
		if (vertCount)
		{
			//DGM TODO: could we be smarter?
			for (unsigned i=0; i<addedVertCount; ++i)
			{
				for (unsigned j=0; j<vertCount; ++j)
				{
					const CCVector3* Pj = vertices->getPoint(j);
					if (P[i].x == Pj->x && P[i].y == Pj->y && P[i].z == Pj->z)
					{
						bool useCurrentVertex = true;

						//We must also check that the color is the same (if any)
						if (faceCol || vertices->hasColors())
						{
							const colorType* _faceCol = faceCol ? faceCol : ccColor::white;
							const colorType* _vertCol = vertices->hasColors() ? vertices->getPointColor(j) : ccColor::white;
							useCurrentVertex = (_faceCol[0] == _vertCol[0] && _faceCol[1] == _vertCol[1] && _faceCol[2] == _vertCol[2]);
						}

						if (useCurrentVertex)
						{
							vertIndexes[i] = static_cast<int>(j);
							break;
						}
					}
				}
			}
		}

		//now create new vertices
		unsigned createdVertCount = 0;
		{
			for (unsigned i=0; i<addedVertCount; ++i)
				if (vertIndexes[i] < 0)
					++createdVertCount;
		}

		if (createdVertCount != 0)
		{
			//reserve memory for the new vertices
			if (!vertices->reserve(vertCount+createdVertCount))
			{
				ccLog::Error("[DxfImporter] Not enough memory!");
				return;
			}

			for (unsigned i=0; i<addedVertCount; ++i)
			{
				if (vertIndexes[i] < 0)
				{
					vertIndexes[i] = static_cast<int>(vertCount++);
					vertices->addPoint(P[i]);
				}
			}
		}

		//number of triangles to add
		unsigned addTriCount = (addedVertCount == 3 ? 1 : 2);

		//now add the corresponding face(s)
		if (!m_faces->reserve(m_faces->size() + addTriCount))
		{
			ccLog::Error("[DxfImporter] Not enough memory!");
			return;
		}
		m_faces->addTriangle(vertIndexes[0], vertIndexes[1], vertIndexes[2]);
		if (addedVertCount == 4)
			m_faces->addTriangle(vertIndexes[0], vertIndexes[2], vertIndexes[3]);

		//add per-triangle normals
		{
			//normals table
			NormsIndexesTableType* triNormsTable = m_faces->getTriNormsTable();
			bool firstTime = false;
			if (!triNormsTable)
			{
				triNormsTable = new NormsIndexesTableType(); 
				m_faces->setTriNormsTable(triNormsTable);
				m_faces->addChild(triNormsTable);
				firstTime = true;
			}

			//add 1 or 2 new entries
			unsigned triNormCount = triNormsTable->currentSize();
			if (!triNormsTable->reserve(triNormsTable->currentSize() + addTriCount))
			{
				ccLog::Error("[DxfImporter] Not enough memory!");
				return;
			}
			
			CCVector3 N = (P[1]-P[0]).cross(P[2]-P[0]);
			N.normalize();
			triNormsTable->addElement(ccNormalVectors::GetNormIndex(N.u));
			if (addTriCount == 2)
			{
				N = (P[2]-P[0]).cross(P[3]-P[0]);
				N.normalize();
				triNormsTable->addElement(ccNormalVectors::GetNormIndex(N.u));
			}

			//per-triangle normals indexes
			if (firstTime)
			{
				if (!m_faces->reservePerTriangleNormalIndexes())
				{
					ccLog::Error("[DxfImporter] Not enough memory!");
					return;
				}
				m_faces->showNormals(true);
			}
			int n1 = static_cast<int>(triNormCount);
			m_faces->addTriangleNormalIndexes(n1, n1, n1);
			if (addTriCount == 2)
			{
				int n2 = static_cast<int>(triNormCount+1);
				m_faces->addTriangleNormalIndexes(n2, n2, n2);
			}
		}

		//and now for the color
		if (faceCol)
		{
			//RGB field already instantiated?
			if (vertices->hasColors())
			{
				for (unsigned i=0; i<createdVertCount; ++i)
					vertices->addRGBColor(faceCol);
			}
			//otherwise, reserve memory and set all previous points to white by default
			else if (vertices->setRGBColor(ccColor::white))
			{
				//then replace the last color(s) by the current one
				for (unsigned i=0; i<createdVertCount; ++i)
					vertices->setPointColor(vertCount-1-i,faceCol);
				m_faces->showColors(true);
			}
		}
		else if (vertices->hasColors())
		{
			//add default color if none is defined!
			for (unsigned i=0; i<createdVertCount; ++i)
				vertices->addRGBColor(ccColor::white);
		}
	}
Ejemplo n.º 9
0
CC_FILE_ERROR PVFilter::loadFile(const char* filename, ccHObject& container, bool alwaysDisplayLoadDialog/*=true*/, bool* coordinatesShiftEnabled/*=0*/, double* coordinatesShift/*=0*/)
{
	//ccConsole::Print("[PVFilter::loadFile] Opening binary file '%s'...\n",filename);

	//opening file
	FILE *fp = fopen(filename, "rb");
    if (!fp)
        return CC_FERR_NO_ERROR;

	CCLib::CCMiscTools::fseek64(fp,0,2);		                //we reach the end of the file
	__int64 fileSize = CCLib::CCMiscTools::ftell64(fp);		//file size query
	CCLib::CCMiscTools::fseek64(fp,0,0);						//back to the begining

    //we read the points number
	unsigned nbOfPoints = (unsigned) (fileSize  / (__int64)(4*sizeof(float)));

	//ccConsole::Print("[PVFilter::loadFile] Points: %i\n",nbOfPoints);

    //if the file is too big, it will be chuncked in multiple parts
	unsigned fileChunkPos = 0;
	unsigned fileChunkSize = ccMin(nbOfPoints,CC_MAX_NUMBER_OF_POINTS_PER_CLOUD);

	//new cloud
    char name[64],k=0;
	sprintf(name,"unnamed - Cloud #%i",k);
	ccPointCloud* loadedCloud = new ccPointCloud(name);
    loadedCloud->reserveThePointsTable(fileChunkSize);
	loadedCloud->enableScalarField();

    float rBuff[3];

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

    //number of points read from the begining of the current cloud part
    //WARNING: different from lineCounter
	unsigned pointsRead=0;

	for (unsigned i=0;i<nbOfPoints;i++)
	{
        //if we reach the max. cloud size limit, we cerate a new chunk
		if (pointsRead == fileChunkPos+fileChunkSize)
		{
			loadedCloud->getCurrentInScalarField()->computeMinAndMax();
			int sfIdx = loadedCloud->getCurrentInScalarFieldIndex();
			loadedCloud->setCurrentDisplayedScalarField(sfIdx);
			loadedCloud->showSF(sfIdx>=0);
            container.addChild(loadedCloud);
			fileChunkPos = pointsRead;
			fileChunkSize = ccMin(nbOfPoints-pointsRead,CC_MAX_NUMBER_OF_POINTS_PER_CLOUD);
            sprintf(name,"unnamed - Cloud #%i",++k);
			loadedCloud = new ccPointCloud(name);
            loadedCloud->reserveThePointsTable(fileChunkSize);
			loadedCloud->enableScalarField();
		}

        //we read the 3 coordinates of the point
		if (fread(rBuff,4,3,fp)>=0)
		{
		    //conversion to CCVector3
		    CCVector3 P = CCVector3(PointCoordinateType(rBuff[0]),
                                    PointCoordinateType(rBuff[1]),
                                    PointCoordinateType(rBuff[2]));
			loadedCloud->addPoint(P);
		}
		else
		{
            fclose(fp);
			return CC_FERR_NO_ERROR;
		}

        //then the scalar value
		if (fread(rBuff,4,1,fp)>=0)
		{
		    //conversion to DistanceType
		    DistanceType d = DistanceType(rBuff[0]);
		    loadedCloud->setPointScalarValue(pointsRead,d);
		}
		else
		{
            fclose(fp);
			return CC_FERR_NO_ERROR;
		}

		++pointsRead;

		if (!nprogress.oneStep())
		{
			loadedCloud->resize(i+1-fileChunkPos);
			break;
		}
    }

    loadedCloud->getCurrentInScalarField()->computeMinAndMax();
	int sfIdx = loadedCloud->getCurrentInScalarFieldIndex();
	loadedCloud->setCurrentDisplayedScalarField(sfIdx);
	loadedCloud->showSF(sfIdx>=0);

    container.addChild(loadedCloud);

    fclose(fp);

	return CC_FERR_NO_ERROR;
}
Ejemplo n.º 10
0
void cc2DLabel::drawMeOnly3D(CC_DRAW_CONTEXT& context)
{
	assert(!m_points.empty());

	//standard case: list names pushing
	bool pushName = MACRO_DrawEntityNames(context);
	if (pushName)
	{
		//not particularily fast
		if (MACRO_DrawFastNamesOnly(context))
			return;
		glPushName(getUniqueIDForDisplay());
	}

    const float c_sizeFactor = 4.0f;
    bool loop = false;

	size_t count = m_points.size();
    switch (count)
    {
    case 3:
		{
			glPushAttrib(GL_COLOR_BUFFER_BIT);
			glEnable(GL_BLEND);

			//we draw the triangle
			glColor4ub(255,255,0,128);
			glBegin(GL_TRIANGLES);
			for (unsigned i=0; i<count; ++i)
				ccGL::Vertex3v(m_points[i].cloud->getPoint(m_points[i].index)->u);
			glEnd();

			glPopAttrib();
			loop=true;
		}
    case 2:
		{
			//segment width
			glPushAttrib(GL_LINE_BIT);
			glLineWidth(c_sizeFactor);

			//we draw the segments
			if (isSelected())
				glColor3ubv(ccColor::red);
			else
				glColor3ubv(ccColor::green);
			glBegin(GL_LINES);
			for (unsigned i=0; i<count; i++)
			{
				if (i+1<count || loop)
				{
					ccGL::Vertex3v(m_points[i].cloud->getPoint(m_points[i].index)->u);
					ccGL::Vertex3v(m_points[(i+1)%count].cloud->getPoint(m_points[(i+1)%count].index)->u);
				}
			}
			glEnd();
			glPopAttrib();
		}

    case 1:
		{
			//display point marker as spheres
			{
				if (!c_unitPointMarker)
				{
					c_unitPointMarker = QSharedPointer<ccSphere>(new ccSphere(1.0f,0,"PointMarker",12));
					c_unitPointMarker->showColors(true);
					c_unitPointMarker->setVisible(true);
					c_unitPointMarker->setEnabled(true);
				}
			
				//build-up point maker own 'context'
				CC_DRAW_CONTEXT markerContext = context;
				markerContext.flags &= (~CC_DRAW_ENTITY_NAMES); //we must remove the 'push name flag' so that the sphere doesn't push its own!
				markerContext._win = 0;

				if (isSelected() && !pushName)
					c_unitPointMarker->setTempColor(ccColor::red);
				else
					c_unitPointMarker->setTempColor(ccColor::magenta);

				for (unsigned i=0; i<count; i++)
				{
					glMatrixMode(GL_MODELVIEW);
					glPushMatrix();
					const CCVector3* P = m_points[i].cloud->getPoint(m_points[i].index);
					ccGL::Translate(P->x,P->y,P->z);
					glScalef(context.pickedPointsRadius,context.pickedPointsRadius,context.pickedPointsRadius);
					c_unitPointMarker->draw(markerContext);
					glPopMatrix();
				}
			}

			if (m_dispIn3D && !pushName) //no need to display label in point picking mode
			{
				QFont font(context._win->getTextDisplayFont()); //takes rendering zoom into account!
				//font.setPointSize(font.pointSize()+2);
				font.setBold(true);

				//draw their name
				glPushAttrib(GL_DEPTH_BUFFER_BIT);
				glDisable(GL_DEPTH_TEST);
				for (unsigned j=0; j<count; j++)
				{
					const CCVector3* P = m_points[j].cloud->getPoint(m_points[j].index);
					QString title = (count == 1 ? getName() : QString("P#%0").arg(m_points[j].index));
					context._win->display3DLabel(	title,
													*P + CCVector3(	context.pickedPointsTextShift,
																	context.pickedPointsTextShift,
																	context.pickedPointsTextShift),
													ccColor::magenta,
													font );
				}
				glPopAttrib();
			}
		}
    }

	if (pushName)
		glPopName();
}
Ejemplo n.º 11
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;
}