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); } }
protected override void SolveInstance(IGH_DataAccess DA) { var points = new List <GH_Point>(); var vectors = new List <GH_Vector>(); var surface = new GH_Surface(); var dynamicsWrapped = new List <GH_ObjectWrapper>(); if (DA.GetDataList(0, points) && points == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid point list. Operation canceled."); return; } if (DA.GetDataList(1, vectors) && vectors == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid vector list. Operation canceled."); return; } // if vec field is empty, create parallel list of 0 vectors if (vectors.Count == 0) { for (int i = 0; i < points.Count; i++) { vectors.Add(new GH_Vector()); } } if (DA.GetDataList(2, dynamicsWrapped) && dynamicsWrapped == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid dynamics list. Operation canceled."); return; } if (DA.GetData(3, ref surface) && surface == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid surface. Operation canceled."); return; } var dynamics = new List <IDynamic>(); foreach (var d in dynamicsWrapped) { dynamics.Add(d.Value as IDynamic); } Algos.SortDynamicsByPriority(dynamics); Algos.ClearDynamics(dynamics); foreach (var d in dynamics) { Algos.ProcessDynamics(d, points, vectors, surface); } Algos.RealignAccelerationVectors(dynamics, vectors); DA.SetDataList(0, points); DA.SetDataList(1, vectors); }
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]; } }
public void Process(List <GH_Point> points, List <GH_Vector> vectors, GH_Surface surface) { var surfaces = Param["Surfs"] as List <GH_Surface>; var alignList = new List <int>(); for (int i = 0; i < points.Count; i++) { var point = points[i].Value; var vector = vectors[i].Value; foreach (var surf in surfaces) { var curve = Curve.CreateControlPointCurve(new Point3d[] { point, point + vector }); Curve[] overlaps; Point3d[] intersections; Intersection.CurveBrep(curve, surf.Value, 0.001d, out overlaps, out intersections); if (intersections.Length > 0) { var intersect = intersections[0]; // get uv coordiantes of intersection double u, v; surf.Face.ClosestPoint(intersect, out u, out v); var surfNormal = surf.Face.NormalAt(u, v); // unitize manually, apply dot product surfNormal *= 1 / surfNormal.Length; surfNormal *= Algos.DotProduct(vector, surfNormal); // black magic vector -= 2 * surfNormal; vectors[i].Value = vector; alignList.Add(i); } } } if (alignList.Count > 0) { Param["alignAccVectors"] = alignList; } else { Param.Remove("alignAccVectors"); } }
public static GH_Point GetPointModifiedByDynamics(GH_Point traveller, Basis outBasis, List <IDynamic> dynamics, StaticSettings spm_settings) { var output = new GH_Point(); foreach (var d in dynamics) { var p = new List <GH_Point>(); p.Add(traveller); var v = new List <GH_Vector>(); if (d.PostProcess) { v.Add(outBasis.Vector); } else { v.Add(new GH_Vector()); } ProcessDynamics(d, p, v, spm_settings.surface); if (d.PostProcess) { outBasis.Vector.Value = v[0].Value; } else { outBasis.Vector.Value += v[0].Value; } } // realign acceleration if necessary var outVec = new List <GH_Vector>() { outBasis.Vector }; Algos.RealignAccelerationVectors(dynamics, outVec); outBasis.Vector = outVec[0]; // compute our resultant point via the traveller + resultant vectors var res = traveller.Value + (outBasis.Vector.Value); return(new GH_Point(res)); }
public void Process(List <GH_Point> points, List <GH_Vector> vectors, GH_Surface surface) { var dynamicsWrapped = Param["D"] as List <GH_ObjectWrapper>; var dynamics = new List <IDynamic>(); foreach (var d in dynamicsWrapped) { dynamics.Add(d.Value as IDynamic); } Algos.SortDynamicsByPriority(dynamics); foreach (var d in dynamics) { Algos.ProcessDynamics(d, points, vectors, surface); } }
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; } } }
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) { // inputs var points = new List <GH_Point>(); var vectors = new List <GH_Vector>(); var startPoints = new List <GH_Point>(); var reset = new GH_Boolean(); var settings = new GH_ObjectWrapper(); 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) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Vector list size mismatch with points list, they must be equal in length. Operation canceled."); return; } if (DA.GetDataList(2, startPoints) && startPoints == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid travelling points. Operation canceled."); return; } // spm parameters component is optional, we use its defaults if it is not available SPM_Parameters spm_settings = new SPM_Parameters(); if (DA.GetData(3, 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 = (SPM_Parameters)settings.Value; } if (DA.GetData(4, ref reset) && reset == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid reset input. Operation canceled."); return; } if (startBasis == null || reset.Value) { var count = startPoints.Count; startBasis = new Basis[count]; lastVecs = new GH_Vector[count]; xy = new double[count]; yz = new double[count]; xz = new double[count]; for (int i = 0; i < count; i++) { startBasis[i] = new Basis(startPoints[i]); lastVecs[i] = new GH_Vector(); xy[i] = 0; yz[i] = 0; xz[i] = 0; } } if (moving == null || reset.Value) { moving = startPoints; return; } int steps = spm_settings.steps; if (steps == 0) { steps = 1; } var bases = new List <Basis>(); for (int i = 0; i < points.Count; i++) { bases.Add(new Basis(points[i], vectors[i])); } // find each next point based on an averaging formula and iterate for (int i = 0; i < startPoints.Count; i++) { for (int j = 0; j < steps; j++) { bool add = false; var outBasis = new Basis(); bool working = Algos.SampleForNextPoint(bases, moving[i].Value, startBasis[i], lastVecs[i], spm_settings, out outBasis, out add); if (spm_settings.stop && spm_settings.windAngle != 0.0d) { if (!lastVecs[i].Value.IsZero) { double cxy = xy[i]; double cyz = yz[i]; double cxz = xz[i]; if (Algos.IsWoundPast(outBasis.Vector.Value, lastVecs[i].Value, spm_settings.windAngle, ref cxy, ref cyz, ref cxz)) { break; } xy[i] = cxy; yz[i] = cyz; xz[i] = cxz; } } lastVecs[i] = outBasis.Vector; if (working && startBasis[i].Vector.Value.IsZero) { startBasis[i].Vector.Value = moving[i].Value - startBasis[i].Point.Value; } if (add) { moving[i] = outBasis.Point; } if (!working) { moving[i] = startPoints[i]; } } } DA.SetDataList(0, moving); }
public void Process(List <GH_Point> points, List <GH_Vector> vectors, GH_Surface surface) { var planes = Param["Pl"] as List <GH_Plane>; var h = (double)Param["h"]; var k = (double)Param["k"]; var a = (double)Param["a"]; var e = (bool)Param["e"]; var funnel = (bool)Param["F"]; var reverse = (bool)Param["r"]; var nv = new GH_Vector(); double u1, v1, u2, v2; u1 = u2 = v1 = v2 = 0.0d; for (int i = 0; i < points.Count; i++) { foreach (var pl in planes) { var o = pl.Value.Origin; var currP = points[i].Value; if (surface.IsValid) { if (!e) { surface.Face.ClosestPoint(currP, out u1, out v1); var surfPl = new Plane(currP, surface.Face.NormalAt(u1, v1)); Point3d remap; surfPl.RemapToPlaneSpace(pl.Value.Origin, out remap); var dir = surfPl.PointAt(remap.X, remap.Y) - surfPl.Origin; dir.Unitize(); surface.Face.ClosestPoint(pl.Value.Origin, out u2, out v2); Point2d uv1 = new Point2d(u1, v1); Point2d uv2 = new Point2d(u2, v2); var dis = uv1.DistanceTo(uv2); dir *= (k / Math.Pow(dis, h)); var tan = Vector3d.CrossProduct(dir, surface.Face.NormalAt(u1, v1)); tan.Unitize(); tan *= a / dis; Vector3d rotation = dir + tan; rotation.Unitize(); Basis offCheck = new Basis(new GH_Point(currP + rotation)); if (!Algos.CheckIfOffSurface(offCheck, surface)) { nv.Value += rotation; } } else { surface.Face.ClosestPoint(currP, out u1, out v1); surface.Face.ClosestPoint(o, out u2, out v2); var p1 = new Point2d(u1, v1); var p2 = new Point2d(u2, v2); var c = surface.Face.ShortPath(p1, p2, 0.001d); var v = c.TangentAtStart; nv = new GH_Vector(v); nv.Value.Unitize(); nv.Value *= (k / Math.Pow(c.GetLength(), 1d + h)); var sn = surface.Face.NormalAt(u1, v1); var sncv = Vector3d.CrossProduct(sn, v); sncv.Unitize(); sncv *= a / c.GetLength(); nv.Value += sncv; } if (reverse) { surface.Face.ClosestPoint(currP, out u1, out v1); var surfN = surface.Face.NormalAt(u1, v1); var v = Vector3d.CrossProduct(surfN, nv.Value); v.Unitize(); v *= nv.Value.Length; nv.Value = v; } } else { nv = new GH_Vector(o - currP); nv.Value.Unitize(); nv.Value *= (k / Math.Pow(currP.DistanceTo(o), 1d + h)); if (funnel) { Point3d outP; pl.Value.RemapToPlaneSpace(currP, out outP); nv.Value *= Math.Sign(outP.Z); } Point3d sign; pl.Value.RemapToPlaneSpace(currP, out sign); if (sign.X != 0 && sign.Y != 0) { Vector3d tan; tan = new Vector3d(-sign.Y, sign.X, 0); var tanAtPl = pl.Value.PointAt(tan.X, tan.Y, 0); var tanAtO = tanAtPl - o; tanAtO *= a / Math.Pow(tan.Length, 2d + h); nv.Value += tanAtO; } } vectors[i].Value += nv.Value; } } }
protected override void SolveInstance(IGH_DataAccess DA) { // inputs var points = new List <GH_Point>(); var planes = new List <GH_Plane>(); var vectors = new List <GH_Vector>(); var traveller = new GH_Point(); var settings = new GH_ObjectWrapper(); var dynamicsWrapped = new List <GH_ObjectWrapper>(); var dynamics = new List <IDynamic>(); // outputs var linePoints = new List <GH_Point>(); var lineVecs = new List <GH_Vector>(); // gather and validate inputs if (DA.GetDataList(0, points) && points == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid points list. Operation canceled."); return; } if (DA.GetData(2, ref traveller) && traveller == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid travelling point. Operation canceled."); return; } if (DA.GetDataList(3, 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); // spm parameters component is optional, we use its defaults if it is not available StaticSettings spm_settings = new StaticSettings(); if (DA.GetData(4, 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 = (StaticSettings)settings.Value; } var bases = new List <Basis>(); var basesWrapper = new List <GH_ObjectWrapper>(); // we need to get the vector field information after settings, for tensor settings if (spm_settings.tensor && (spm_settings.tensorDir >= 0 && spm_settings.tensorDir <= 2)) { if (DA.GetDataList(1, basesWrapper) && basesWrapper == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid tensor field. Operation canceled."); return; } for (int i = 0; i < basesWrapper.Count; i++) { Basis b = basesWrapper[i].Value as Basis; bases.Add(new Basis(points[i], b.Vectors)); bases[i].Axes = spm_settings.tensorAxes; } } else { 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 if you wish to integrate using just dynamics). Operation canceled."); return; } // if vectors list is empty we'll populate it with empty vectors to match each point if (vectors.Count == 0) { foreach (var i in Enumerable.Range(0, points.Count)) { vectors.Add(new GH_Vector()); } } for (int i = 0; i < points.Count; i++) { bases.Add(new Basis(points[i], vectors[i])); } } int steps = spm_settings.steps; if (steps == 0) { steps = MAX_ITERATIONS; } var startBasis = new Basis(traveller); var vecLast = new GH_Vector(); double xy = 0; double yz = 0; double xz = 0; // add start point to output linePoints.Add(startBasis.Point); Algos.ClearDynamics(dynamics); // find each next point based on an averaging formula and iterate for (int i = 0; i < steps; i++) { bool add = false; var outBasis = new Basis(); if (points.Count != 0 && !Algos.SampleForNextPoint(bases, traveller.Value, startBasis, vecLast, spm_settings, out outBasis)) { break; } if (dynamics.Count > 0) { traveller = Algos.GetPointModifiedByDynamics(traveller, outBasis, dynamics, spm_settings); outBasis.Point = traveller; } else { traveller = outBasis.Point; } // this step must be done oustide of the regular halting checks as we must store the axes rotations if (spm_settings.windAngle != 0.0d && !vecLast.Value.IsZero && Algos.IsWoundPast(outBasis.Vector.Value, vecLast.Value, spm_settings.windAngle, ref xy, ref yz, ref xz)) { break; } var working = Algos.CheckHaltingConditions(traveller, startBasis, outBasis, vecLast.Value, out add, spm_settings); traveller = outBasis.Point; vecLast = outBasis.Vector; // cache the vector between start and start+1 if (i == 0 && working) { startBasis.Vector.Value = traveller.Value - startBasis.Point.Value; } if (add) { linePoints.Add(traveller); lineVecs.Add(vecLast); } if (!working) { break; } } DA.SetDataList(0, linePoints); DA.SetDataList(1, lineVecs); }