/** * @brief Compute the coefficients of the number of planes specified for a given cloud. * * @param cloud Point cloud in which the computation is based. */ void MultiplePlaneSegmentation::computeCoefficients(const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &cloud) { // Cloud containing the points without the planes. pcl::PointCloud<pcl::PointXYZRGBA>::Ptr remainingCloud = pcl::PointCloud<pcl::PointXYZRGBA>::Ptr(new pcl::PointCloud<pcl::PointXYZRGBA>(*cloud)); // Create the segmentation object. pcl::SACSegmentation<pcl::PointXYZRGBA> seg; // Set segmentation parameters. seg.setModelType(pcl::SACMODEL_PARALLEL_PLANE); seg.setOptimizeCoefficients(true); seg.setAxis(orientation); seg.setEpsAngle(angleThreshold); seg.setMethodType(pcl::SAC_RANSAC); seg.setMaxIterations(5000); seg.setDistanceThreshold(planeDistance); // Create the filtering object. pcl::ExtractIndices<pcl::PointXYZRGBA> extract; // At each step, one plane is removed from remainingCloud. for(int i = 0; i < nPlanes; i++){ pcl::ModelCoefficients coefficients; pcl::PointIndices::Ptr inliers(new pcl::PointIndices()); // Segment the largest planar component from the remaining cloud. seg.setInputCloud(remainingCloud); seg.segment(*inliers, coefficients); // Remove non valid points. removeNans(cloud, inliers); // Make sure the normal is looking to the camera. float origin[] = {0,0,0}; correctNormal(origin, cloud->points[inliers->indices[0]], coefficients); // With 0 inliers, nothing needs to be done. if (inliers->indices.size() == 0) break; // Extract the plane inliers from the remainingCloud. extract.setInputCloud(remainingCloud); extract.setIndices(inliers); extract.setNegative(true); extract.filter(*remainingCloud); // Update plane coefficients. planes[i].setCoefficients(coefficients); } }
bool Foam::parcel::move(spray& sDB) { const polyMesh& mesh = cloud().pMesh(); const polyBoundaryMesh& pbMesh = mesh.boundaryMesh(); const liquidMixture& fuels = sDB.fuels(); scalar deltaT = sDB.runTime().deltaT().value(); label Nf = fuels.components().size(); label Ns = sDB.composition().Y().size(); // Calculate the interpolated gas properties at the position of the parcel vector Up = sDB.UInterpolator().interpolate(position(), cell()) + Uturb(); scalar rhog = sDB.rhoInterpolator().interpolate(position(), cell()); scalar pg = sDB.pInterpolator().interpolate(position(), cell()); scalar Tg = sDB.TInterpolator().interpolate(position(), cell()); scalarField Yfg(Nf, 0.0); scalar cpMixture = 0.0; for(label i=0; i<Ns; i++) { const volScalarField& Yi = sDB.composition().Y()[i]; if (sDB.isLiquidFuel()[i]) { label j = sDB.gasToLiquidIndex()[i]; scalar Yicelli = Yi[cell()]; Yfg[j] = Yicelli; } cpMixture += Yi[cell()]*sDB.gasProperties()[i].Cp(Tg); } // Correct the gaseous temperature for evaporated fuel scalar cellV = sDB.mesh().V()[cell()]; scalar cellMass = rhog*cellV; Tg += sDB.shs()[cell()]/(cpMixture*cellMass); // Changed cut-off temperature for evaporation. HJ, 27/Apr/2011 Tg = max(273, Tg); scalar tauMomentum = GREAT; scalar tauHeatTransfer = GREAT; scalarField tauEvaporation(Nf, GREAT); scalarField tauBoiling(Nf, GREAT); bool keepParcel = true; setRelaxationTimes ( cell(), tauMomentum, tauEvaporation, tauHeatTransfer, tauBoiling, sDB, rhog, Up, Tg, pg, Yfg, m()*fuels.Y(X()), deltaT ); // set the end-time for the track scalar tEnd = (1.0 - stepFraction())*deltaT; // Set the maximum time step for this parcel // FPK changes: avoid temperature-out-of-range errors // in spray tracking. HJ, 13/Oct/2007 // tauEvaporation no longer multiplied by 1e20, // to account for the evaporation timescale // FPK, 13/Oct/2007 scalar dtMax = min ( tEnd, min ( tauMomentum, min ( mag(min(tauEvaporation)), min ( mag(tauHeatTransfer), mag(min(tauBoiling)) ) ) ) )/sDB.subCycles(); // prevent the number of subcycles from being too many // (10 000 seems high enough) dtMax = max(dtMax, 1.0e-4*tEnd); bool switchProcessor = false; vector planeNormal = vector::zero; if (sDB.twoD()) { planeNormal = n() ^ sDB.axisOfSymmetry(); planeNormal /= mag(planeNormal); } // move the parcel until there is no 'timeLeft' while (keepParcel && tEnd > SMALL && !switchProcessor) { // set the lagrangian time-step scalar dt = min(dtMax, tEnd); // remember which cell the parcel is in // since this will change if a face is hit label celli = cell(); scalar p = sDB.p()[celli]; // track parcel to face, or end of trajectory if (keepParcel) { // Track and adjust the time step if the trajectory // is not completed dt *= trackToFace(position() + dt*U_, sDB); // Decrement the end-time acording to how much time the track took tEnd -= dt; // Set the current time-step fraction. stepFraction() = 1.0 - tEnd/deltaT; if (onBoundary()) // hit face { # include "boundaryTreatment.H" } } if (keepParcel && sDB.twoD()) { scalar z = position() & sDB.axisOfSymmetry(); vector r = position() - z*sDB.axisOfSymmetry(); if (mag(r) > SMALL) { correctNormal(sDB.axisOfSymmetry()); } } // **** calculate the lagrangian source terms **** // First we get the 'old' properties. // and then 'update' them to get the 'new' // properties. // The difference is then added to the source terms. scalar oRho = fuels.rho(p, T(), X()); scalarField oMass(Nf, 0.0); scalar oHg = 0.0; scalar oTotMass = m(); scalarField oYf(fuels.Y(X())); forAll(oMass, i) { oMass[i] = m()*oYf[i]; label j = sDB.liquidToGasIndex()[i]; oHg += oYf[i]*sDB.gasProperties()[j].Hs(T()); } vector oMom = m()*U(); scalar oHv = fuels.hl(p, T(), X()); scalar oH = oHg - oHv; scalar oPE = (p - fuels.pv(p, T(), X()))/oRho; // update the parcel properties (U, T, D) updateParcelProperties ( dt, sDB, celli, face() ); scalar nRho = fuels.rho(p, T(), X()); scalar nHg = 0.0; scalarField nMass(Nf, 0.0); scalarField nYf(fuels.Y(X())); forAll(nMass, i) { nMass[i] = m()*nYf[i]; label j = sDB.liquidToGasIndex()[i]; nHg += nYf[i]*sDB.gasProperties()[j].Hs(T()); }