/// <summary> /// The position of the third (and follwing) primary particle is determined by the PCA: /// The radius determined by the geometrical properties is computed and the /// primary particle is positioned in that distance to the existing ones. /// If that primary particle is in contact with another one but not /// overlapping with any other, it may reside there. /// </summary> /// <param name="primaryParticles"></param> /// <param name="count"></param> /// <returns></returns> public bool AddNextPrimaryParticle(List <PrimaryParticle> primaryParticles, int count, INeighborslist neighborslist) { var com = primaryParticles.GetCenterOfMass(); // compute the distance for the next primary particle to fulfill fractal dimension var ppDistance = GetNextPrimaryParticleDistance(primaryParticles); // get a new primary particle without any position yet. var particle = InitializeNewPrimaryParticle(_psd.GetRandomSize()); var found = false; var rndPosition = new Vector3(); while (!found) { // get a new random position on the sphere of allowed positions rndPosition = ParticleFormationUtil.GetRandomPosition(_rndGen, ppDistance) + com; // check if that position is valid found = IsPrimaryParticlePositionValid(particle, rndPosition, neighborslist, primaryParticles, _config); if (count > _config.MaxAttemptsPerCluster) { _logger.Debug("Resetting cluster generation. Time limit exceeded."); return(false); } count++; } particle.MoveTo(rndPosition); primaryParticles.Add(particle); neighborslist.AddParticlesToNeighborsList(particle); return(true); }
/// <summary> /// Since there is a nearby primary particle, check if the position is valid: /// (1) there is at least 1 contact with other primary particles /// (2) there are no overlaps. /// </summary> /// <param name="particle"></param> /// <param name="primaryParticles"></param> /// <param name="config"></param> /// <param name="neighbors"></param> /// <returns></returns> private static bool IsAnyNeighborPositionValid( PrimaryParticle particle, Vector3 setToPosition, IAggregateFormationConfig config, IEnumerable <Tuple <PrimaryParticle, double> > neighborsWithDistance) { var(isInContact, hasNoOverlap) = ParticleFormationUtil.IsAnyNeighborInContactOrOverlapping(particle, setToPosition, config, neighborsWithDistance); return(isInContact && hasNoOverlap); }
/// <summary> /// (1) Check for the specific primary particles if the position is valid: no overlap /// (2) Check if any other primary particle is in contact /// </summary> /// <param name="tree">neighborListTree</param> /// <param name="primaryParticle">primary particle of interest</param> /// <param name="otherPrimaryParticles">all other fixed primary particles</param> /// <param name="config"></param> /// <returns></returns> public (bool isInContact, bool hasNoOverlap) IsPrimaryParticlePositionValid( INeighborslist neighborslist, PrimaryParticle primaryParticle, IEnumerable <PrimaryParticle> otherPrimaryParticles) { //var neighbors = ParticleFormationUtil.GetPossibleNeighbors(primaryParticle, primaryParticle.Position, tree, otherPrimaryParticles, config); var searchRadius = (primaryParticle.Radius + otherPrimaryParticles.GetMaxRadius()) * _config.Delta; var neighborsWithDistance = neighborslist.GetPrimaryParticlesAndDistanceWithinRadius(primaryParticle.Position, searchRadius); if (!neighborsWithDistance.Any()) { return(isInContact : false, hasNoOverlap : true); } return(ParticleFormationUtil.IsAnyNeighborInContactOrOverlapping(primaryParticle, primaryParticle.Position, _config, neighborsWithDistance)); }
/// <summary> /// The second primary particle position is determined by its and the radius of the initial primary particle /// </summary> /// <param name="primaryParticles"></param> public void SetSecondPrimaryParticle(List <PrimaryParticle> primaryParticles) { var radius = _psd.GetRandomSize(); // Distance of the CenterOfMass (com) of the second pp from the com // of the first pp var particle = new PrimaryParticle(0, radius); // Position the second primary particle directly in contact with the first var ppDistance = _config.Epsilon * (primaryParticles[0].Radius + particle.Radius); // Get any random position withon that distance var rndPosition = ParticleFormationUtil.GetRandomPosition(_rndGen, ppDistance); particle.MoveTo(rndPosition); primaryParticles.Add(particle); }
private bool IsRandomPositionValid( Cluster nextCluster, List <Cluster> depositedCluster, Random rndGen, double distance, INeighborslist neighborslist) { bool found; // Get a new random position for the COM on the sphere around the deposited cluster var rndPosition = ParticleFormationUtil.GetRandomPosition(rndGen, distance); // Move the cluster to that position on the sphere nextCluster.MoveTo(rndPosition); // Check if that random position is valid (no overlap, but connection between nextCluster an the deposited cluster) found = IsClusterPositionValid(nextCluster, neighborslist, depositedCluster); return(found); }