diff --git a/doc/distrib/xml/en-US/DSCoreNodes.xml b/doc/distrib/xml/en-US/DSCoreNodes.xml index 8f9074672cc..964204be67a 100644 --- a/doc/distrib/xml/en-US/DSCoreNodes.xml +++ b/doc/distrib/xml/en-US/DSCoreNodes.xml @@ -208,7 +208,7 @@ A Bezier curve is defined by four control points and provides smooth interpolation. - + Gets interpolated Y values based on the assigned parameters and limits. @@ -225,21 +225,26 @@ Provides common functionality for generating and retrieving curve values. - + Abstract method to be implemented by derived classes for generating curve values. - + Common method for retrieving X values. - + Common method for retrieving Y values. + + + Generates X and Y values by mapping domain inputs to canvas space and evaluating a curve function. + + Represents a Gaussian curve in the CurveMapper. @@ -251,7 +256,7 @@ Indicates whether the node is currently being resized, preventing unintended control point updates. - + Returns X and Y values distributed across the curve. @@ -272,7 +277,7 @@ Calculates the X values (canvas coordinates) for min and max Y values - + Returns X and Y values distributed across the curve. @@ -283,7 +288,7 @@ The curve follows a quadratic equation based on two control points. - + Returns X and Y values distributed across the curve. @@ -294,7 +299,7 @@ The curve generates procedural noise based on control points and Perlin noise functions. - + Returns X and Y values distributed across the curve. @@ -305,7 +310,7 @@ The curve is defined by a power equation derived from a control point. - + Returns X and Y values distributed across the curve. @@ -316,7 +321,7 @@ The sine wave is defined by two control points and follows a trigonometric function. - + Returns X and Y values distributed across the curve. @@ -327,7 +332,7 @@ The curve follows a square root function and is influenced by two control points. - + Returns X and Y values distributed across the curve. diff --git a/src/Libraries/CoreNodeModels/CurveMapperNodeModel.cs b/src/Libraries/CoreNodeModels/CurveMapperNodeModel.cs index f5884956648..bcac218d948 100644 --- a/src/Libraries/CoreNodeModels/CurveMapperNodeModel.cs +++ b/src/Libraries/CoreNodeModels/CurveMapperNodeModel.cs @@ -22,25 +22,28 @@ public class CurveMapperNodeModel : NodeModel private double maxLimitX = 1; private double minLimitY = 0; private double maxLimitY = 1; - private int pointsCount = 10; + private List pointsCount = new List() { 10.0 }; private List outputValuesY; private List outputValuesX; private List renderValuesY; private List renderValuesX; - private const int minXDefaultValue = 0; - private const int maxXDefaultValue = 1; - private const int minYDefaultValue = 0; - private const int maxYDefaultValue = 1; - - private const int pointCountDefaultValue = 10; + private static readonly int minXDefaultValue = 0; + private static readonly int maxXDefaultValue = 1; + private static readonly int minYDefaultValue = 0; + private static readonly int maxYDefaultValue = 1; + private static readonly double pointCountDefaultValue = 10.0; private readonly IntNode minLimitXDefaultValue = new IntNode(minXDefaultValue); private readonly IntNode maxLimitXDefaultValue = new IntNode(maxXDefaultValue); private readonly IntNode minLimitYDefaultValue = new IntNode(minYDefaultValue); private readonly IntNode maxLimitYDefaultValue = new IntNode(maxYDefaultValue); - private readonly IntNode pointsCountDefaultValue = new IntNode(pointCountDefaultValue); + private readonly AssociativeNode pointsCountDefaultValue = + AstFactory.BuildExprList(new List + { + AstFactory.BuildDoubleNode(pointCountDefaultValue) + }); private const string gaussianCurveControlPointData2Tag = "GaussianCurveControlPointData2"; private const string gaussianCurveControlPointData3Tag = "GaussianCurveControlPointData3"; @@ -236,7 +239,7 @@ public double MaxLimitY /// Gets or sets the number of points used to compute the curve. [JsonProperty] - public int PointsCount + public List PointsCount { get => pointsCount; set @@ -702,9 +705,16 @@ public void UpdateGaussianCurveControlPoints(double deltaX, string tag) private bool IsValidInput() { - return PointsCount >= 2 - && MinLimitX != MaxLimitX - && MinLimitY != MaxLimitY; + if (pointsCount == null || pointsCount.Count == 0) + return false; + + if (pointsCount.Count == 1 && pointsCount.FirstOrDefault() < 2) + return false; + + if (MinLimitX == MaxLimitX || MinLimitY == MaxLimitY) + return false; + + return true; } private bool IsValidCurve() @@ -809,14 +819,44 @@ private void DataBridgeCallback(object data) var maxValueX = double.TryParse(inputs[1]?.ToString(), out var maxX) ? maxX : MaxLimitX; var minValueY = double.TryParse(inputs[2]?.ToString(), out var minY) ? minY : MinLimitY; var maxValueY = double.TryParse(inputs[3]?.ToString(), out var maxY) ? maxY : MaxLimitY; - var listValue = int.TryParse(inputs[4]?.ToString(), out var parsedCount) ? parsedCount : PointsCount; + List parsedPointsCount; + + if (inputs[4] is IList countList) + { + parsedPointsCount = new List(); + + foreach (var item in countList) + { + if (item is IList nestedList) + { + foreach (var nested in nestedList) + { + if (double.TryParse(nested?.ToString(), out var val)) + parsedPointsCount.Add(val); + } + } + else if (double.TryParse(item?.ToString(), out var val)) + { + parsedPointsCount.Add(val); + } + } + } + else if (double.TryParse(inputs[4]?.ToString(), out var singleVal)) + { + parsedPointsCount = new List { singleVal }; + } + else + { + parsedPointsCount = PointsCount; + } + // Check port connectivity if (InPorts[0].IsConnected) MinLimitX = minValueX; if (InPorts[1].IsConnected) MaxLimitX = maxValueX; if (InPorts[2].IsConnected) MinLimitY = minValueY; if (InPorts[3].IsConnected) MaxLimitY = maxValueY; - if (InPorts[4].IsConnected) PointsCount = listValue; + if (InPorts[4].IsConnected) PointsCount = parsedPointsCount; // Notify property changes to update UI foreach (var propertyName in new[] { nameof(MinLimitX), nameof(MaxLimitX), nameof(MinLimitY), nameof(MaxLimitY), nameof(PointsCount) }) @@ -832,8 +872,8 @@ private void DataBridgeCallback(object data) public override IEnumerable BuildOutputAst(List inputAstNodes) { - // Return null outputs if GraphType is Empty - if (SelectedGraphType == GraphTypes.Empty || !IsValidCurve()) + // If input is missing or invalid, return nulls + if (inputAstNodes == null || inputAstNodes.Count < 5 || SelectedGraphType == GraphTypes.Empty || !IsValidCurve()) { return new[] { @@ -888,16 +928,13 @@ public override IEnumerable BuildOutputAst(List new AssociativeNode[] { AstFactory.BuildDoubleNode(cp.X), AstFactory.BuildDoubleNode(DynamicCanvasSize - cp.Y) - }) - .Cast() - .ToList() + }).ToList() ); // Handle input values with fall-back defaults @@ -914,28 +951,32 @@ public override IEnumerable BuildOutputAst(List, double, double, double, double, double, int, string, List>>( - CurveMapperGenerator.CalculateValues), + new Func, double, double, double, double, double, List, string, List>( + CurveMapperGenerator.CalculateValuesX), curveInputs ); - // DataBridge call - var dataBridgeCall = AstFactory.BuildAssignment( - AstFactory.BuildIdentifier(AstIdentifierBase + "_dataBridge"), - VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputValues)) - ); + AssociativeNode buildResultNodeY = + AstFactory.BuildFunctionCall( + new Func, double, double, double, double, double, List, string, List>( + CurveMapperGenerator.CalculateValuesY), + curveInputs + ); - // Assign outputs var xValuesAssignment = AstFactory.BuildAssignment( GetAstIdentifierForOutputIndex(0), - AstFactory.BuildIndexExpression(buildResultNode, AstFactory.BuildIntNode(0)) - ); + buildResultNodeX); var yValuesAssignment = AstFactory.BuildAssignment( GetAstIdentifierForOutputIndex(1), - AstFactory.BuildIndexExpression(buildResultNode, AstFactory.BuildIntNode(1)) + buildResultNodeY); + + // DataBridge call + var dataBridgeCall = AstFactory.BuildAssignment( + AstFactory.BuildIdentifier(AstIdentifierBase + "_dataBridge"), + VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputValues)) ); return new[] { xValuesAssignment, yValuesAssignment, dataBridgeCall }; diff --git a/src/Libraries/CoreNodeModels/Properties/Resources.Designer.cs b/src/Libraries/CoreNodeModels/Properties/Resources.Designer.cs index 35dcde8f8e0..539ff788b92 100644 --- a/src/Libraries/CoreNodeModels/Properties/Resources.Designer.cs +++ b/src/Libraries/CoreNodeModels/Properties/Resources.Designer.cs @@ -268,7 +268,7 @@ public static string CreateListPortDataResultToolTip { } /// - /// Looks up a localized string similar to count. + /// Looks up a localized string similar to values. /// public static string CurveMapperCountInputPortName { get { @@ -277,9 +277,7 @@ public static string CurveMapperCountInputPortName { } /// - /// Looks up a localized string similar to Number of values to generate. - /// - ///Default value (int): {0}. + /// Looks up a localized string similar to Number of values to map or List of values to map.. /// public static string CurveMapperCountInputPortToolTip { get { diff --git a/src/Libraries/CoreNodeModels/Properties/Resources.en-US.resx b/src/Libraries/CoreNodeModels/Properties/Resources.en-US.resx index d75abf971fe..aec9a9d1e1e 100644 --- a/src/Libraries/CoreNodeModels/Properties/Resources.en-US.resx +++ b/src/Libraries/CoreNodeModels/Properties/Resources.en-US.resx @@ -681,12 +681,10 @@ In Generative Design workflows, this node should be used to control and block th default value: G - count + values - Number of values to generate. - -Default value (int): {0} + Number of values to map or List of values to map. Redistributes x-coordinates along y-coordinates based on a selected mathematical curve, providing precise control over point distribution. diff --git a/src/Libraries/CoreNodeModels/Properties/Resources.resx b/src/Libraries/CoreNodeModels/Properties/Resources.resx index 035630e6111..09cd704020a 100644 --- a/src/Libraries/CoreNodeModels/Properties/Resources.resx +++ b/src/Libraries/CoreNodeModels/Properties/Resources.resx @@ -681,12 +681,10 @@ In Generative Design workflows, this node should be used to control and block th default value: G - count + values - Number of values to generate. - -Default value (int): {0} + Number of values to map or List of values to map. Redistributes x-coordinates along y-coordinates based on a selected mathematical curve, providing precise control over point distribution. diff --git a/src/Libraries/CoreNodes/CurveMapper/BezierCurve.cs b/src/Libraries/CoreNodes/CurveMapper/BezierCurve.cs index 67a46e1b399..dc9f84252d5 100644 --- a/src/Libraries/CoreNodes/CurveMapper/BezierCurve.cs +++ b/src/Libraries/CoreNodes/CurveMapper/BezierCurve.cs @@ -53,13 +53,15 @@ private void GetValueAtT(double t, out double x, out double y) /// /// Gets interpolated Y values based on the assigned parameters and limits. /// - protected override (List XValues, List YValues) GenerateCurve(int pointsCount, bool isRender) + protected override (List XValues, List YValues) GenerateCurve(List pointsDomain, bool isRender) { var renderValuesX = new List(); var renderValuesY = new List(); var valuesX = new List(); var valuesY = new List(); + var pointsCount = pointsDomain.Count == 1 ? pointsDomain[0] : pointsDomain.Count; + // Generate fine-grained samples to ensure better interpolation int fineSteps = (int)(pointsCount * CanvasSize); @@ -78,15 +80,35 @@ protected override (List XValues, List YValues) GenerateCurve(in return (renderValuesX, renderValuesY); } - // Collect output values - for (int i = 0; i < pointsCount; i++) + if (pointsDomain.Count == 1) + { + for (int i = 0; i < pointsCount; i++) + { + double targetX = (i / (double)(pointsCount - 1) * CanvasSize); + int closestIndex = renderValuesX.IndexOf(renderValuesX.OrderBy(x => Math.Abs(x - targetX)).First()); + double y = renderValuesY[closestIndex]; + + valuesX.Add(targetX); + valuesY.Add(y); + } + } + else { - double targetX = (i / (double)(pointsCount - 1) * CanvasSize); - int closestIndex = renderValuesX.IndexOf(renderValuesX.OrderBy(x => Math.Abs(x - targetX)).First()); - double y = renderValuesY[closestIndex]; + double minInput = pointsDomain.Min(); + double maxInput = pointsDomain.Max(); + + // Normalize domain value & map to canvas X coordinate + foreach (double t in pointsDomain) + { + double normalizedT = (t - minInput) / (maxInput - minInput); + double targetX = normalizedT * CanvasSize; + + int closestIndex = renderValuesX.IndexOf(renderValuesX.OrderBy(x => Math.Abs(x - targetX)).First()); + double y = renderValuesY[closestIndex]; - valuesX.Add(targetX); - valuesY.Add(y); + valuesX.Add(targetX); + valuesY.Add(y); + } } return (valuesX, valuesY); diff --git a/src/Libraries/CoreNodes/CurveMapper/ControlLine.cs b/src/Libraries/CoreNodes/CurveMapper/ControlLine.cs index cb60497892d..ab1da877550 100644 --- a/src/Libraries/CoreNodes/CurveMapper/ControlLine.cs +++ b/src/Libraries/CoreNodes/CurveMapper/ControlLine.cs @@ -21,7 +21,7 @@ public ControlLine(double cp1X, double cp1Y, double cp2X, double cp2Y, double ca ControlPoint2X = cp2X; ControlPoint2Y = cp2Y; } - protected override (List XValues, List YValues) GenerateCurve(int pointsCount, bool isRender = false) + protected override (List XValues, List YValues) GenerateCurve(List pointsCount, bool isRender = false) { return (new List { ControlPoint1X, ControlPoint2X }, new List { ControlPoint1Y, ControlPoint2Y }); } diff --git a/src/Libraries/CoreNodes/CurveMapper/CurveBase.cs b/src/Libraries/CoreNodes/CurveMapper/CurveBase.cs index a3ce5c18d52..6a36f0228f0 100644 --- a/src/Libraries/CoreNodes/CurveMapper/CurveBase.cs +++ b/src/Libraries/CoreNodes/CurveMapper/CurveBase.cs @@ -1,4 +1,6 @@ +using System; using System.Collections.Generic; +using System.Linq; namespace DSCore.CurveMapper { @@ -19,12 +21,12 @@ protected CurveBase(double canvasSize) /// /// Abstract method to be implemented by derived classes for generating curve values. /// - protected abstract (List XValues, List YValues) GenerateCurve(int pointsCount, bool isRender); + protected abstract (List XValues, List YValues) GenerateCurve(List pointsCount, bool isRender); /// /// Common method for retrieving X values. /// - public virtual List GetCurveXValues(int pointsCount, bool isRender = false) + public virtual List GetCurveXValues(List pointsCount, bool isRender = false) { return GenerateCurve(pointsCount, isRender).XValues; } @@ -32,9 +34,33 @@ public virtual List GetCurveXValues(int pointsCount, bool isRender = fal /// /// Common method for retrieving Y values. /// - public virtual List GetCurveYValues(int pointsCount, bool isRender = false) + public virtual List GetCurveYValues(List pointsCount, bool isRender = false) { return GenerateCurve(pointsCount, isRender).YValues; } + + /// + /// Generates X and Y values by mapping domain inputs to canvas space and evaluating a curve function. + /// + protected (List xValues, List yValues) GenerateFromDomain(List domain, Func computeY) + { + var valuesX = new List(); + var valuesY = new List(); + + double minInput = domain.Min(); + double maxInput = domain.Max(); + + foreach (var t in domain) + { + // Normalize domain value & map to canvas X coordinate + double normalizedT = (t - minInput) / (maxInput - minInput); + double x = normalizedT * CanvasSize; + + valuesX.Add(x); + valuesY.Add(computeY(x)); + } + + return (valuesX, valuesY); + } } } diff --git a/src/Libraries/CoreNodes/CurveMapper/CurveMapperGenerator.cs b/src/Libraries/CoreNodes/CurveMapper/CurveMapperGenerator.cs index aad65891ff9..44e275167f6 100644 --- a/src/Libraries/CoreNodes/CurveMapper/CurveMapperGenerator.cs +++ b/src/Libraries/CoreNodes/CurveMapper/CurveMapperGenerator.cs @@ -6,17 +6,23 @@ namespace DSCore.CurveMapper public class CurveMapperGenerator { private static int rounding = 10; + private static List> cachedValues = null; public static List> CalculateValues( List controlPoints, double canvasSize, double minX, double maxX, double minY, double maxY, - int pointsCount, string graphType + List pointsCount, string graphType ) { var xValues = new List() { double.NaN }; var yValues = new List() { double.NaN }; - if (minX != maxX && minY != maxY && pointsCount >= 2) + if (pointsCount.Count == 1 && pointsCount[0] < 2) + { + return new List> { yValues, xValues }; + } + + if (minX != maxX && minY != maxY) { // Unpack the control points double cp1x = GetCP(controlPoints, 0), cp1y = GetCP(controlPoints, 1); @@ -69,6 +75,31 @@ public static List> CalculateValues( return new List> { yValues, xValues }; } + public static List CalculateValuesX( + List controlPoints, double canvasSize, + double minX, double maxX, double minY, double maxY, + List pointsCount, string graphType + ) + { + // X values must always be calculated first to initialize the cache. + // CalculateValuesY() depends on this to avoid redundant calculation. + cachedValues = CalculateValues(controlPoints, canvasSize, minX, maxX, minY, maxY, pointsCount, graphType); + return cachedValues[0]; + } + + public static List CalculateValuesY( + List controlPoints, double canvasSize, + double minX, double maxX, double minY, double maxY, + List pointsCount, string graphType + ) + { + if ( cachedValues == null ) + { + cachedValues = CalculateValues(controlPoints, canvasSize, minX, maxX, minY, maxY, pointsCount, graphType); + } + return cachedValues[1]; + } + private static double GetCP(List controlPoints, int index) { return index < controlPoints.Count ? controlPoints[index] : 0; diff --git a/src/Libraries/CoreNodes/CurveMapper/GaussianCurve.cs b/src/Libraries/CoreNodes/CurveMapper/GaussianCurve.cs index ead49914ae9..b5f432855cf 100644 --- a/src/Libraries/CoreNodes/CurveMapper/GaussianCurve.cs +++ b/src/Libraries/CoreNodes/CurveMapper/GaussianCurve.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; namespace DSCore.CurveMapper { @@ -47,7 +48,7 @@ private double ComputeGaussianY(double x, double A, double mu, double sigma) /// /// Returns X and Y values distributed across the curve. /// - protected override (List XValues, List YValues) GenerateCurve(int pointsCount, bool isRender) + protected override (List XValues, List YValues) GenerateCurve(List pointsDomain, bool isRender) { var valuesX = new List(); var valuesY = new List(); @@ -106,18 +107,23 @@ protected override (List XValues, List YValues) GenerateCurve(in } } } - else + else if (pointsDomain.Count == 1) { + var pointsCount = pointsDomain[0]; var step = CanvasSize / (pointsCount - 1); for (int i = 0; i < pointsCount; i++) { double x = 0 + i * step; - double y = CanvasSize - ComputeGaussianY(x, A, mu, sigma); + valuesX.Add(x); - valuesY.Add(y); + valuesY.Add(CanvasSize - ComputeGaussianY(x, A, mu, sigma)); } } + else + { + return GenerateFromDomain(pointsDomain, x => CanvasSize - ComputeGaussianY(x, A, mu, sigma)); + } return (valuesX, valuesY); } diff --git a/src/Libraries/CoreNodes/CurveMapper/LinearCurve.cs b/src/Libraries/CoreNodes/CurveMapper/LinearCurve.cs index 52849c32630..b19de728adf 100644 --- a/src/Libraries/CoreNodes/CurveMapper/LinearCurve.cs +++ b/src/Libraries/CoreNodes/CurveMapper/LinearCurve.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; namespace DSCore.CurveMapper { @@ -54,7 +55,7 @@ private double SolveForXGivenY(double y) /// /// Returns X and Y values distributed across the curve. /// - protected override (List XValues, List YValues) GenerateCurve(int pointsCount, bool isRender = false) + protected override (List XValues, List YValues) GenerateCurve(List pointsDomain, bool isRender = false) { double leftX = SolveForXGivenY(0); double rightX = SolveForXGivenY(CanvasSize); @@ -76,8 +77,10 @@ protected override (List XValues, List YValues) GenerateCurve(in ? new List { System.Math.Clamp(highY, 0, CanvasSize), System.Math.Clamp(lowY, 0, CanvasSize) } : new List { System.Math.Clamp(lowY, 0, CanvasSize), System.Math.Clamp(highY, 0, CanvasSize) }; } - else + else if (pointsDomain.Count == 1) { + var pointsCount = (int)pointsDomain[0]; + // For full point distribution double stepX = CanvasSize / (pointsCount - 1); double stepY = (highY - lowY) / (pointsCount - 1); @@ -88,6 +91,10 @@ protected override (List XValues, List YValues) GenerateCurve(in valuesY.Add((lowY + i * stepY)); } } + else + { + return GenerateFromDomain(pointsDomain, x => LineEquation(x)); + } return (valuesX, valuesY); } diff --git a/src/Libraries/CoreNodes/CurveMapper/ParabolicCurve.cs b/src/Libraries/CoreNodes/CurveMapper/ParabolicCurve.cs index 2418af9358e..dc99a29418d 100644 --- a/src/Libraries/CoreNodes/CurveMapper/ParabolicCurve.cs +++ b/src/Libraries/CoreNodes/CurveMapper/ParabolicCurve.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; namespace DSCore.CurveMapper { @@ -41,14 +42,16 @@ private double SolveParabolaForY(double x) /// /// Returns X and Y values distributed across the curve. /// - protected override (List XValues, List YValues) GenerateCurve(int pointsCount, bool isRender) + protected override (List XValues, List YValues) GenerateCurve(List pointsDomain, bool isRender) { double leftBoundaryY = (ControlPoint2Y > ControlPoint1Y) ? CanvasSize : 0.0; double rightBoundaryY = (ControlPoint2Y < ControlPoint1Y) ? CanvasSize : 0.0; - double startX = SolveParabolaForX(leftBoundaryY, true); double endX = SolveParabolaForX(leftBoundaryY); + var valuesX = new List(); + var valuesY = new List(); + if (isRender) { double minX = Math.Max(0, Math.Min(startX, endX)); @@ -57,8 +60,8 @@ protected override (List XValues, List YValues) GenerateCurve(in // First point double firstY = SolveParabolaForY(minX); - var valuesX = new List { minX }; - var valuesY = new List { firstY }; + valuesX.Add(minX); + valuesY.Add(firstY); for (double d = minX; d < maxX; d += renderIncrementX) { @@ -73,19 +76,10 @@ protected override (List XValues, List YValues) GenerateCurve(in // Last point valuesX.Add(maxX); valuesY.Add(SolveParabolaForY(maxX)); - - return (valuesX, valuesY); } - else + else if (pointsDomain.Count == 1) { - bool flip = ControlPoint2Y > ControlPoint1Y; - - // First point - double firstY = SolveParabolaForY(leftBoundaryY); - double firstX = leftBoundaryY; - - var valuesX = new List(); - var valuesY = new List(); + var pointsCount = pointsDomain[0]; var step = (rightBoundaryY - leftBoundaryY) / (pointsCount - 1); @@ -99,14 +93,18 @@ protected override (List XValues, List YValues) GenerateCurve(in } // Reverse lists if needed to ensure X values increase from left to right - if (flip) + if (ControlPoint2Y > ControlPoint1Y) { valuesX.Reverse(); valuesY.Reverse(); } - - return (valuesX, valuesY); } + else + { + return GenerateFromDomain(pointsDomain, x => SolveParabolaForY(x)); + } + + return (valuesX, valuesY); } } } diff --git a/src/Libraries/CoreNodes/CurveMapper/PerlinNoiseCurve.cs b/src/Libraries/CoreNodes/CurveMapper/PerlinNoiseCurve.cs index 48d4773d0ca..bd8d548c3b0 100644 --- a/src/Libraries/CoreNodes/CurveMapper/PerlinNoiseCurve.cs +++ b/src/Libraries/CoreNodes/CurveMapper/PerlinNoiseCurve.cs @@ -160,7 +160,7 @@ private double ComputePerlinCurveY(double x) /// /// Returns X and Y values distributed across the curve. /// - protected override (List XValues, List YValues) GenerateCurve(int pointsCount, bool isRender = false) + protected override (List XValues, List YValues) GenerateCurve(List pointsDomain, bool isRender = false) { var valuesX = new List(); var valuesY = new List(); @@ -194,19 +194,23 @@ protected override (List XValues, List YValues) GenerateCurve(in valuesX = sortedPairs.Select(p => p.X).ToList(); valuesY = sortedPairs.Select(p => p.Y).ToList(); } - else + else if (pointsDomain.Count == 1) { + var pointsCount = pointsDomain[0]; var step = CanvasSize / (pointsCount - 1); for (int i = 0; i < pointsCount; i++) { double x = 0 + step * i; - double y = ComputePerlinCurveY(x); valuesX.Add(x); - valuesY.Add(y); + valuesY.Add(ComputePerlinCurveY(x)); } } + else + { + return GenerateFromDomain(pointsDomain, x => ComputePerlinCurveY(x)); + } return (valuesX, valuesY); } diff --git a/src/Libraries/CoreNodes/CurveMapper/PowerCurve.cs b/src/Libraries/CoreNodes/CurveMapper/PowerCurve.cs index b286ddc02ae..34e05dda683 100644 --- a/src/Libraries/CoreNodes/CurveMapper/PowerCurve.cs +++ b/src/Libraries/CoreNodes/CurveMapper/PowerCurve.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; namespace DSCore.CurveMapper { @@ -48,7 +49,7 @@ private double ComputePowerY(double x, double powerFactor) /// /// Returns X and Y values distributed across the curve. /// - protected override (List XValues, List YValues) GenerateCurve(int pointsCount, bool isRender) + protected override (List XValues, List YValues) GenerateCurve(List pointsDomain, bool isRender) { var valuesX = new List(); var valuesY = new List(); @@ -63,18 +64,22 @@ protected override (List XValues, List YValues) GenerateCurve(in valuesY.Add(y); } } - else + else if (pointsDomain.Count == 1) { + var pointsCount = (int)pointsDomain[0]; double step = CanvasSize / (pointsCount - 1); for (int i = 0; i < pointsCount; i++) { double x = i * step; valuesX.Add(x); - double y = ComputePowerY(x, powerFactor); - valuesY.Add(y); + valuesY.Add(ComputePowerY(x, powerFactor)); } } + else + { + return GenerateFromDomain(pointsDomain, x => ComputePowerY(x, powerFactor)); + } return (valuesX, valuesY); } diff --git a/src/Libraries/CoreNodes/CurveMapper/SineWave.cs b/src/Libraries/CoreNodes/CurveMapper/SineWave.cs index 83ec7bc0029..3aab4796cbd 100644 --- a/src/Libraries/CoreNodes/CurveMapper/SineWave.cs +++ b/src/Libraries/CoreNodes/CurveMapper/SineWave.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; namespace DSCore.CurveMapper { @@ -46,7 +47,7 @@ private void GetEquationCoefficients() /// /// Returns X and Y values distributed across the curve. /// - protected override (List XValues, List YValues) GenerateCurve(int pointsCount, bool isRender = false) + protected override (List XValues, List YValues) GenerateCurve(List pointsDomain, bool isRender = false) { var valuesX = new List(); var valuesY = new List(); @@ -60,15 +61,26 @@ protected override (List XValues, List YValues) GenerateCurve(in valuesY.Add(ConvertTrigoToY(y)); } } - else + else if (pointsDomain.Count == 1) { + var pointsCount = (int)pointsDomain[0]; + double step = CanvasSize / (pointsCount - 1); for (int i = 0; i < pointsCount; i++) { double x = i * step; valuesX.Add(x); - double y = CosineEquation(ConvertXToTrigo(x)); - valuesY.Add(ConvertTrigoToY(y)); + valuesY.Add(ConvertTrigoToY(CosineEquation(ConvertXToTrigo(x)))); + } + } + else + { + double minInput = pointsDomain.Min(); + double maxInput = pointsDomain.Max(); + + foreach (var t in pointsDomain) + { + return GenerateFromDomain(pointsDomain, x => ConvertTrigoToY(CosineEquation(ConvertXToTrigo(x)))); } } diff --git a/src/Libraries/CoreNodes/CurveMapper/SquareRootCurve.cs b/src/Libraries/CoreNodes/CurveMapper/SquareRootCurve.cs index ec54d7130ca..9866b20c753 100644 --- a/src/Libraries/CoreNodes/CurveMapper/SquareRootCurve.cs +++ b/src/Libraries/CoreNodes/CurveMapper/SquareRootCurve.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; namespace DSCore.CurveMapper { @@ -56,7 +57,7 @@ private double ComputeSquareRootY(double x, double sqrtFactor) /// /// Returns X and Y values distributed across the curve. /// - protected override (List XValues, List YValues) GenerateCurve(int pointsCount, bool isRender) + protected override (List XValues, List YValues) GenerateCurve(List pointsDomain, bool isRender) { var valuesX = new List(); var valuesY = new List(); @@ -90,8 +91,9 @@ protected override (List XValues, List YValues) GenerateCurve(in } } } - else + else if (pointsDomain.Count == 1) { + var pointsCount = (int)pointsDomain[0]; var step = CanvasSize / (pointsCount - 1); for (int i = 0; i < pointsCount; i++) @@ -102,6 +104,10 @@ protected override (List XValues, List YValues) GenerateCurve(in valuesY.Add(ComputeSquareRootY(x, sqrtFactor)); } } + else + { + return GenerateFromDomain(pointsDomain, x => ComputeSquareRootY(x, sqrtFactor)); + } return (valuesX, valuesY); }