private void CheckHaltingConditions(DynamicSettings settings) { var staticSettings = ConvertDynSettingsToStatic(settings); var toRemove = new List <Particle>(); for (int i = 0; i < particles.Count; i++) { var p = particles[i]; var add = false; var outBasis = new Basis(p.Current.Point, p.Current.Vector); if (!Algos.CheckHaltingConditions(p.Current.Point, p.Start, outBasis, p.Current.Vector.Value, out add, staticSettings) || add == false) { toRemove.Add(p); } else { p.Current.Point = outBasis.Point; } } foreach (var remove in toRemove) { particles.Remove(remove); } }
private void UpdateWithDynamics(List <IDynamic> dynamics, DynamicSettings settings) { var points = new List <GH_Point>(particles.Count); var vectors = new List <GH_Vector>(particles.Count); for (int i = 0; i < particles.Count; i++) { points.Add(particles[i].Current.Point); vectors.Add(new GH_Vector()); } foreach (var d in dynamics) { // we need a new list of vectors each way through, which we add seperately to an end result // otherwise acceleration can apply across dynamics in unintended ways var tempVectors = new List <GH_Vector>(particles.Count); for (int i = 0; i < particles.Count; i++) { tempVectors.Add(new GH_Vector()); } // post processes use the cumulative vector list // pre processes use the temporary empty vector list if (d.PostProcess) { // vectors is modified inline so we don't need to update as below Algos.ProcessDynamics(d, points, vectors, settings.surface); } else { Algos.ProcessDynamics(d, points, tempVectors, settings.surface); for (int i = 0; i < particles.Count; i++) { vectors[i].Value += tempVectors[i].Value; } } } Algos.RealignAccelerationVectors(dynamics, vectors); for (int i = 0; i < points.Count; i++) { points[i].Value += vectors[i].Value; // update particles from resultant p/v's above particles[i].Current.Point = points[i]; particles[i].Current.Vector = vectors[i]; } }
protected Emitter(int startLife, DynamicSettings settings) { this.startLife = startLife; respawn = settings.respawn; emitTime = settings.newSpawn; emitDeviance = settings.rndSpawn; emitCountDown = new List <int>(); // parallel to startParticles particles = new List <Particle>(); startParticles = new List <Particle>(); rnd = new Random(); }
private StaticSettings ConvertDynSettingsToStatic(DynamicSettings dyn) { var sta = new StaticSettings(); // 1:1 functionality sta.avgRadius = dyn.avgRadius; sta.bounds = dyn.bounds; sta.lineCont = dyn.lineCont; sta.snapAngle = dyn.snapAngle; sta.snapTol = dyn.snapTol; sta.surface = dyn.surface; // not used or used differently from regular static usage sta.stop = false; // never use the regular stop checks in dynamic sta.tolerance = double.MaxValue; return(sta); }
protected override void SolveInstance(IGH_DataAccess DA) { // inputs var points = new List <GH_Point>(); var vectors = new List <GH_Vector>(); var startPoints = new List <GH_Point>(); var lifeTime = new GH_Integer(); var settings = new GH_ObjectWrapper(); var reset = new GH_Boolean(); var dynamicsWrapped = new List <GH_ObjectWrapper>(); var dynamics = new List <IDynamic>(); if (DA.GetDataList(0, points) && points == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid points list. Operation canceled."); return; } if (DA.GetDataList(1, vectors) && vectors == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid vector list. Operation canceled."); return; } if (vectors.Count != points.Count && vectors.Count != 0) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Vector list size mismatch with points list, they must be equal in length (or empty). Operation canceled."); return; } if (DA.GetDataList(2, startPoints) && startPoints == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid travelling points. Operation canceled."); return; } if (DA.GetData(3, ref lifeTime) && lifeTime == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid lifetime input. Operation canceled."); return; } if (DA.GetDataList(4, dynamicsWrapped) && dynamicsWrapped == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid dynamics list. Operation canceled."); return; } dynamics = (from d in dynamicsWrapped select d.Value as IDynamic).ToList(); Algos.SortDynamicsByPriority(dynamics); // if vectors list is empty we'll populate it with empty vectors to match each point if (vectors.Count == 0) { for (int i = 0; i < points.Count; i++) { vectors.Add(new GH_Vector()); } } // spm parameters component is optional, we use its defaults if it is not available var spm_settings = new DynamicSettings(); if (DA.GetData(5, ref settings)) { // if getdata succeeded but the settings var is null we had bad input if (settings == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid settings input. Operation canceled."); return; } // otherwise cast from gh_objectwrapper and continue spm_settings = (DynamicSettings)settings.Value; } if (DA.GetData(6, ref reset) && reset == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid reset input. Operation canceled."); return; } if (emitter == null || reset.Value) { emitter = new Emitter(startPoints, lifeTime.Value, spm_settings); DA.SetDataList(0, startPoints); var zv = new List <GH_Vector>(startPoints.Count); for (int i = 0; i < startPoints.Count; i++) { zv.Add(new GH_Vector()); } Algos.ClearDynamics(dynamics); DA.SetDataList(1, zv); return; } // emitter updates dynamics emitter.Update(dynamics, points, vectors, spm_settings); DA.SetDataList(0, emitter.Points); DA.SetDataList(1, emitter.Vectors); }
protected override void SolveInstance(IGH_DataAccess DA) { var respawn = new GH_Boolean(); var newSpawn = new GH_Integer(); var rndSpawn = new GH_Integer(); var avgRadius = new GH_Number(); var bounds = new GH_Brep(); var snapTol = new GH_Number(); var snapAngle = new GH_Number(); var surface = new GH_Surface(); var lineCont = new GH_Boolean(); if (DA.GetData(0, ref respawn) && respawn == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid respawn value. Operation canceled."); return; } if (DA.GetData(1, ref newSpawn) && newSpawn == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid new spawn value. Operation canceled."); return; } if (DA.GetData(2, ref rndSpawn) && rndSpawn == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid new spawn randomizing value. Operation canceled."); return; } if (DA.GetData(3, ref avgRadius) && avgRadius == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid interpolation radius value. Operation canceled."); return; } if (DA.GetData(4, ref bounds) && bounds == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid bounding box. Operation canceled."); return; } if (DA.GetData(5, ref snapTol) && snapTol == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid snap tolerance. Operation canceled."); return; } if (DA.GetData(6, ref snapAngle) && snapAngle == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid snapping angle. Operation canceled."); return; } if (DA.GetData(7, ref surface) && surface == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid surface constraint. Operation canceled."); return; } if (DA.GetData(8, ref lineCont) && lineCont == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid line continuity value. Operation canceled."); return; } DynamicSettings settings = new DynamicSettings(); settings.respawn = respawn.Value; settings.newSpawn = newSpawn.Value; settings.rndSpawn = rndSpawn.Value; settings.avgRadius = avgRadius.Value; settings.bounds = bounds; settings.snapTol = snapTol.Value; settings.snapAngle = snapAngle.Value; settings.surface = surface; settings.lineCont = lineCont.Value; var output = new GH_ObjectWrapper(settings); DA.SetData(0, output); }
private void UpdateIntegration(List <GH_Point> points, List <GH_Vector> vectors, DynamicSettings settings) { // only integrate if we have a vector field to work with if (points.Count > 0) { // integration var bases = new List <Basis>(); for (int i = 0; i < points.Count; i++) { bases.Add(new Basis(points[i], vectors[i])); } var ptSampling = (points.Count != 0); var staticSettings = ConvertDynSettingsToStatic(settings); for (int i = 0; i < particles.Count; i++) { var p = particles[i]; var traveller = p.Current.Point; var startBasis = p.Start; var vecLast = p.Current.Vector; var outBasis = new Basis(); if (points.Count != 0 && !Algos.SampleForNextPoint(bases, traveller.Value, startBasis, vecLast, staticSettings, out outBasis)) { break; } p.Current.Point = outBasis.Point; p.Current.Vector = outBasis.Vector; } } }
public void Update(List <IDynamic> dynamics, List <GH_Point> points, List <GH_Vector> vectors, DynamicSettings settings) { UpdateWithDynamics(dynamics, settings); UpdateLifeTimes(dynamics); UpdateEmitCounter(); UpdateIntegration(points, vectors, settings); CheckHaltingConditions(settings); }
public Emitter(List <GH_Point> points, int startLife, DynamicSettings settings) : this(startLife, settings) { points.ForEach(p => startParticles.Add(new Particle(p, startLife))); Begin(); }
public Emitter(List <GH_Point> points, List <GH_Vector> vectors, int startLife, DynamicSettings settings) : this(startLife, settings) { if (points.Count != vectors.Count) { throw new ArgumentException("Points and Vectors list must be parallel (same length)!"); } for (int i = 0; i < points.Count; i++) { startParticles.Add(new Particle(points[i], vectors[i], startLife)); } Begin(); }
public Emitter(List <Basis> bases, int startLife, DynamicSettings settings) : this(startLife, settings) { bases.ForEach(b => startParticles.Add(new Particle(b, startLife))); Begin(); }