public static bool SampleForNextPoint(List <Basis> bases, Point3d point, Basis start, GH_Vector lastVec, StaticSettings settings, out Basis outBasis) { var tolerance = settings.tolerance; var radius = settings.avgRadius; var lineCont = settings.lineCont; var tensorDir = settings.tensorDir; outBasis = new Basis(); GH_Vector ghkv = GetInterpolatedVector(bases, lastVec, lineCont, tensorDir, ref point, tolerance, radius); if (ghkv == null) { return(false); } var kv = ghkv.Value; // po = pt + kv outBasis.Vector = new GH_Vector(kv); outBasis.Point = new GH_Point(point + kv); return(true); }
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); }
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 static bool CheckHaltingConditions(GH_Point traveller, Basis start, Basis outBasis, Vector3d previous, out bool add, StaticSettings settings) { var stop = settings.stop; var surface = settings.surface; var bounds = settings.bounds; var snapTol = settings.snapTol; var snapAngle = settings.snapAngle; add = false; if (stop && !previous.IsZero && CheckStopped(previous)) { return(false); } if (CheckIfOffSurface(outBasis, surface)) { return(false); } if (CheckInsideBounds(outBasis, traveller, bounds, ref add)) { return(false); } if (CheckIfOrbitting(outBasis, start, previous, snapTol, snapAngle, ref add)) { return(false); } add = true; return(true); }
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); }
protected override void SolveInstance(IGH_DataAccess DA) { var steps = new GH_Integer(); var tolerance = new GH_Number(); var stop = new GH_Boolean(); var windAngle = new GH_Number(); 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 tensor = new GH_Boolean(); var tensorDir = new GH_Integer(); var tensorAxes = new List <GH_Integer>(); var lineCont = new GH_Boolean(); if (DA.GetData(0, ref steps) && steps == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid step count. Operation canceled."); return; } if (DA.GetData(1, ref tolerance) && tolerance == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid tolerance. Operation canceled."); return; } if (DA.GetData(2, ref stop) && stop == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid stop value. Operation canceled."); return; } if (DA.GetData(3, ref windAngle) && windAngle == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid tolerance. Operation canceled."); return; } if (DA.GetData(4, ref avgRadius) && avgRadius == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid interpolation radius value. Operation canceled."); return; } if (DA.GetData(5, ref bounds) && bounds == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid bounding box. Operation canceled."); return; } if (DA.GetData(6, ref snapTol) && snapTol == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid snap tolerance. Operation canceled."); return; } if (DA.GetData(7, ref snapAngle) && snapAngle == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid snapping angle. Operation canceled."); return; } if (DA.GetData(8, ref surface) && surface == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid surface constraint. Operation canceled."); return; } if (DA.GetData(9, ref tensor) && tensor == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid tensor input. Operation canceled."); return; } if (DA.GetData(10, ref tensorDir) && tensorDir == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid tensor direction. Operation canceled."); return; } if (tensorDir.Value < 0 || tensorDir.Value > 2) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid tensor direction. Valid input is 0-2. Operation canceled."); return; } if (DA.GetDataList(11, tensorAxes) && tensorAxes == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid tensor direction. Operation canceled."); return; } if (DA.GetData(12, ref lineCont) && lineCont == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid line continuity value. Operation canceled."); return; } StaticSettings settings = new StaticSettings(); settings.steps = steps.Value; settings.stop = stop.Value; settings.windAngle = windAngle.Value; settings.tolerance = tolerance.Value; settings.avgRadius = avgRadius.Value; settings.bounds = bounds; settings.snapTol = snapTol.Value; settings.snapAngle = snapAngle.Value; settings.surface = surface; settings.tensor = tensor.Value; settings.tensorDir = tensorDir.Value; settings.lineCont = lineCont.Value; if (tensorAxes.Count == 0) { settings.tensorAxes.Add(0); settings.tensorAxes.Add(1); } else { foreach (var axis in tensorAxes) { settings.tensorAxes.Add(axis.Value); } } if (settings.tensor == false) { settings.tensorDir = -1; } var output = new GH_ObjectWrapper(settings); DA.SetData(0, output); }