bool GeometricalAnalysisTools::computeSphereFrom4(	const CCVector3& A,
													const CCVector3& B,
													const CCVector3& C,
													const CCVector3& D,
													CCVector3& center,
													PointCoordinateType& radius )
{
	//inspired from 'tetrahedron_circumsphere_3d' by Adrian Bowyer and John Woodwark

	//Set up the linear system.
	double a[12];
	{
		CCVector3 AB = B-A;
		a[0] = AB.x;
		a[3] = AB.y;
		a[6] = AB.z;
		a[9] = AB.norm2d();
	}
	{
		CCVector3 AC = C-A;
		a[1]  = AC.x;
		a[4]  = AC.y;
		a[7]  = AC.z;
		a[10] = AC.norm2d();
	}
	{
		CCVector3 AD = D-A;
		a[2]  = AD.x;
		a[5]  = AD.y;
		a[8]  = AD.z;
		a[11] = AD.norm2d();
	}

	//  Solve the linear system (with Gauss-Jordan elimination)
	if ( dmat_solve ( 3, 1, a ) != 0 )
	{
		//system is singular?
		return false;
	}

	//  Compute the radius and center.
	CCVector3 u = CCVector3(static_cast<PointCoordinateType>(a[0+3*3]),
							static_cast<PointCoordinateType>(a[1+3*3]),
							static_cast<PointCoordinateType>(a[2+3*3])) / 2;
	radius = u.norm();
	center = A + u;

	return true;
}
示例#2
0
bool ScalarFieldTools::computeMeanGradientOnPatch(	const DgmOctree::octreeCell& cell,
													void** additionalParameters,
													NormalizedProgress* nProgress/*=0*/)
{
	//additional parameters
	bool euclideanDistances			= *reinterpret_cast<bool*>(additionalParameters[0]);
	PointCoordinateType radius		= *reinterpret_cast<PointCoordinateType*>(additionalParameters[1]);
	ScalarField* theGradientNorms	= reinterpret_cast<ScalarField*>(additionalParameters[2]);

	//number of points inside the current cell
	unsigned n = cell.points->size();

	//spherical neighborhood extraction structure
	DgmOctree::NearestNeighboursSphericalSearchStruct nNSS;
	nNSS.level = cell.level;
	nNSS.prepare(radius,cell.parentOctree->getCellSize(nNSS.level));
	cell.parentOctree->getCellPos(cell.truncatedCode,cell.level,nNSS.cellPos,true);
	cell.parentOctree->computeCellCenter(nNSS.cellPos,cell.level,nNSS.cellCenter);

	//we already know the points inside the current cell
	{
		try
		{
			nNSS.pointsInNeighbourhood.resize(n);
		}
		catch (.../*const std::bad_alloc&*/) //out of memory
		{
			return false;
		}
		DgmOctree::NeighboursSet::iterator it = nNSS.pointsInNeighbourhood.begin();
		for (unsigned j=0; j<n; ++j,++it)
		{
			it->point = cell.points->getPointPersistentPtr(j);
			it->pointIndex = cell.points->getPointGlobalIndex(j);
		}
		nNSS.alreadyVisitedNeighbourhoodSize = 1;
	}

	const GenericIndexedCloudPersist* cloud = cell.points->getAssociatedCloud();

	for (unsigned i=0; i<n; ++i)
	{
		ScalarType gN = NAN_VALUE;
		ScalarType d1 = cell.points->getPointScalarValue(i);

        if (ScalarField::ValidValue(d1))
		{
			 cell.points->getPoint(i,nNSS.queryPoint);

			//we extract the point's neighbors
			//warning: there may be more points at the end of nNSS.pointsInNeighbourhood than the actual nearest neighbors (k)!
			unsigned k = cell.parentOctree->findNeighborsInASphereStartingFromCell(nNSS,radius,true);

            //if more than one neighbour (the query point itself)
			if (k > 1)
			{
				CCVector3d sum(0,0,0);
				unsigned counter = 0;

				//j = 1 because the first point is the query point itself --> contribution = 0
				for (unsigned j=1; j<k; ++j)
				{
					ScalarType d2 = cloud->getPointScalarValue(nNSS.pointsInNeighbourhood[j].pointIndex);
					if (ScalarField::ValidValue(d2))
					{
						CCVector3 u = *nNSS.pointsInNeighbourhood[j].point - nNSS.queryPoint;
						double norm2 = u.norm2d();

						if (norm2 > ZERO_TOLERANCE)
						{
                            double dd = d2 - d1;
							if (!euclideanDistances || dd*dd < 1.01 * norm2)
							{
								dd /= norm2;
								sum.x += u.x * dd; //warning: and here 'dd'=dd/norm2 ;)
								sum.y += u.y * dd;
								sum.z += u.z * dd;
								++counter;
							}
						}
					}
				}

				if (counter != 0)
					gN = static_cast<ScalarType>(sum.norm()/counter);
			}
		}

		if (theGradientNorms)
			//if "IN" and "OUT" SFs are the same
			theGradientNorms->setValue(cell.points->getPointGlobalIndex(i),gN);
		else
			//if "IN" and "OUT" SFs are different
			cell.points->setPointScalarValue(i,gN);

		if (nProgress && !nProgress->oneStep())
			return false;
	}

	return true;
}