Skip to content

Commit e7bdd56

Browse files
ivaylo-matovzeusongit
authored andcommitted
[DYN-8596] Do not allow list for x & y min/max input (DynamoDS#16078)
Co-authored-by: Ashish Aggarwal <[email protected]> (cherry picked from commit c2f4070)
1 parent d011b85 commit e7bdd56

File tree

14 files changed

+330
-141
lines changed

14 files changed

+330
-141
lines changed

doc/distrib/xml/en-US/DSCoreNodes.xml

Lines changed: 16 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Libraries/CoreNodeModels/CurveMapperNodeModel.cs

Lines changed: 66 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,28 @@ public class CurveMapperNodeModel : NodeModel
2222
private double maxLimitX = 1;
2323
private double minLimitY = 0;
2424
private double maxLimitY = 1;
25-
private int pointsCount = 10;
25+
private List<Double> pointsCount = new List<double>() { 10.0 };
2626

2727
private List<double> outputValuesY;
2828
private List<double> outputValuesX;
2929
private List<double> renderValuesY;
3030
private List<double> renderValuesX;
3131

32-
private const int minXDefaultValue = 0;
33-
private const int maxXDefaultValue = 1;
34-
private const int minYDefaultValue = 0;
35-
private const int maxYDefaultValue = 1;
36-
37-
private const int pointCountDefaultValue = 10;
32+
private static readonly int minXDefaultValue = 0;
33+
private static readonly int maxXDefaultValue = 1;
34+
private static readonly int minYDefaultValue = 0;
35+
private static readonly int maxYDefaultValue = 1;
36+
private static readonly double pointCountDefaultValue = 10.0;
3837

3938
private readonly IntNode minLimitXDefaultValue = new IntNode(minXDefaultValue);
4039
private readonly IntNode maxLimitXDefaultValue = new IntNode(maxXDefaultValue);
4140
private readonly IntNode minLimitYDefaultValue = new IntNode(minYDefaultValue);
4241
private readonly IntNode maxLimitYDefaultValue = new IntNode(maxYDefaultValue);
43-
private readonly IntNode pointsCountDefaultValue = new IntNode(pointCountDefaultValue);
42+
private readonly AssociativeNode pointsCountDefaultValue =
43+
AstFactory.BuildExprList(new List<AssociativeNode>
44+
{
45+
AstFactory.BuildDoubleNode(pointCountDefaultValue)
46+
});
4447

4548
private const string gaussianCurveControlPointData2Tag = "GaussianCurveControlPointData2";
4649
private const string gaussianCurveControlPointData3Tag = "GaussianCurveControlPointData3";
@@ -232,7 +235,7 @@ public double MaxLimitY
232235

233236
/// <summary> Gets or sets the number of points used to compute the curve. </summary>
234237
[JsonProperty]
235-
public int PointsCount
238+
public List<double> PointsCount
236239
{
237240
get => pointsCount;
238241
set
@@ -680,9 +683,16 @@ public void UpdateGaussianCurveControlPoints(double deltaX, string tag)
680683

681684
private bool IsValidInput()
682685
{
683-
return PointsCount >= 2
684-
&& MinLimitX != MaxLimitX
685-
&& MinLimitY != MaxLimitY;
686+
if (pointsCount == null || pointsCount.Count == 0)
687+
return false;
688+
689+
if (pointsCount.Count == 1 && pointsCount.FirstOrDefault() < 2)
690+
return false;
691+
692+
if (MinLimitX == MaxLimitX || MinLimitY == MaxLimitY)
693+
return false;
694+
695+
return true;
686696
}
687697

688698
private bool IsValidCurve()
@@ -787,14 +797,31 @@ private void DataBridgeCallback(object data)
787797
var maxValueX = double.TryParse(inputs[1]?.ToString(), out var maxX) ? maxX : MaxLimitX;
788798
var minValueY = double.TryParse(inputs[2]?.ToString(), out var minY) ? minY : MinLimitY;
789799
var maxValueY = double.TryParse(inputs[3]?.ToString(), out var maxY) ? maxY : MaxLimitY;
790-
var listValue = int.TryParse(inputs[4]?.ToString(), out var parsedCount) ? parsedCount : PointsCount;
800+
var parsedPointsCount = new List<double>();
801+
802+
if (inputs[4] is IList list)
803+
{
804+
foreach (var item in list)
805+
{
806+
if (double.TryParse(item?.ToString(), out var val))
807+
parsedPointsCount.Add(val);
808+
}
809+
}
810+
else if (double.TryParse(inputs[4]?.ToString(), out var singleVal))
811+
{
812+
parsedPointsCount.Add(singleVal);
813+
}
814+
else
815+
{
816+
parsedPointsCount = PointsCount;
817+
}
791818

792819
// Check port connectivity
793820
if (InPorts[0].IsConnected) MinLimitX = minValueX;
794821
if (InPorts[1].IsConnected) MaxLimitX = maxValueX;
795822
if (InPorts[2].IsConnected) MinLimitY = minValueY;
796823
if (InPorts[3].IsConnected) MaxLimitY = maxValueY;
797-
if (InPorts[4].IsConnected) PointsCount = listValue;
824+
if (InPorts[4].IsConnected) PointsCount = parsedPointsCount;
798825

799826
// Notify property changes to update UI
800827
foreach (var propertyName in new[] { nameof(MinLimitX), nameof(MaxLimitX), nameof(MinLimitY), nameof(MaxLimitY), nameof(PointsCount) })
@@ -810,8 +837,8 @@ private void DataBridgeCallback(object data)
810837

811838
public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
812839
{
813-
// Return null outputs if GraphType is Empty
814-
if (SelectedGraphType == GraphTypes.Empty || !IsValidCurve())
840+
// If input is missing or invalid, return nulls
841+
if (inputAstNodes == null || inputAstNodes.Count < 5 || SelectedGraphType == GraphTypes.Empty || !IsValidCurve())
815842
{
816843
return new[]
817844
{
@@ -868,15 +895,13 @@ public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode
868895

869896
// Build controlPointsList dynamically
870897
var controlPointsList = AstFactory.BuildExprList(
871-
controlPointMap[SelectedGraphType]
872-
.SelectMany(cp => new AssociativeNode[]
873-
{
898+
controlPointMap[SelectedGraphType]
899+
.SelectMany(cp => new AssociativeNode[]
900+
{
874901
AstFactory.BuildDoubleNode(cp.X),
875902
AstFactory.BuildDoubleNode(DynamicCanvasSize - cp.Y)
876-
})
877-
.Cast<AssociativeNode>()
878-
.ToList()
879-
);
903+
}).ToList()
904+
);
880905

881906
// Handle input values with fall-back defaults
882907
var inputValues = new List<AssociativeNode>
@@ -888,32 +913,39 @@ public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode
888913
InPorts[4].IsConnected ? inputAstNodes[4] : pointsCountDefaultValue
889914
};
890915

891-
var curveInputs = new List<AssociativeNode> {controlPointsList, AstFactory.BuildDoubleNode(DynamicCanvasSize)};
916+
var curveInputs = new List<AssociativeNode> { controlPointsList, AstFactory.BuildDoubleNode(DynamicCanvasSize) };
892917
curveInputs.AddRange(inputValues);
893918
curveInputs.Add(AstFactory.BuildStringNode(SelectedGraphType.ToString()));
894919

895-
AssociativeNode buildResultNode =
920+
AssociativeNode buildResultNodeX =
896921
AstFactory.BuildFunctionCall(
897-
new Func<List<double>, double, double, double, double, double, int, string, List<List<double>>>(
898-
CurveMapperGenerator.CalculateValues),
922+
new Func<List<double>, double, object, object, object, object, List<double>, string, List<double>>(
923+
CurveMapperGenerator.CalculateValuesX),
899924
curveInputs
900925
);
901926

902-
// DataBridge call
903-
var dataBridgeCall = AstFactory.BuildAssignment(
904-
AstFactory.BuildIdentifier(AstIdentifierBase + "_dataBridge"),
905-
VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputValues))
906-
);
927+
AssociativeNode buildResultNodeY =
928+
AstFactory.BuildFunctionCall(
929+
new Func<List<double>, double, object, object, object, object, List<double>, string, List<double>>(
930+
CurveMapperGenerator.CalculateValuesY),
931+
curveInputs
932+
);
907933

908934
// Assign outputs
909935
var xValuesAssignment = AstFactory.BuildAssignment(
910936
GetAstIdentifierForOutputIndex(0),
911-
AstFactory.BuildIndexExpression(buildResultNode, AstFactory.BuildIntNode(0))
937+
buildResultNodeX
912938
);
913939

914940
var yValuesAssignment = AstFactory.BuildAssignment(
915941
GetAstIdentifierForOutputIndex(1),
916-
AstFactory.BuildIndexExpression(buildResultNode, AstFactory.BuildIntNode(1))
942+
buildResultNodeY
943+
);
944+
945+
// DataBridge call
946+
var dataBridgeCall = AstFactory.BuildAssignment(
947+
AstFactory.BuildIdentifier(AstIdentifierBase + "_dataBridge"),
948+
VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputValues))
917949
);
918950

919951
return new[] { xValuesAssignment, yValuesAssignment, dataBridgeCall };

src/Libraries/CoreNodeModelsWpf/CurveMapper/CurveMapperControl.xaml.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ private void ResetButton_Click(object sender, RoutedEventArgs e)
169169

170170
// Dictionary to map UI control points to their corresponding data
171171
var controlPointsResetMap = BuildControlPointsDictionary();
172-
173172
RecreateControlPoints(controlPointsResetMap);
174173
RenderCurve();
175174
}

src/Libraries/CoreNodes/CurveMapper/BezierCurve.cs

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,15 @@ private void GetValueAtT(double t, out double x, out double y)
5353
/// <summary>
5454
/// Gets interpolated Y values based on the assigned parameters and limits.
5555
/// </summary>
56-
protected override (List<double> XValues, List<double> YValues) GenerateCurve(int pointsCount, bool isRender)
56+
protected override (List<double> XValues, List<double> YValues) GenerateCurve(List<double> pointsDomain, bool isRender)
5757
{
5858
var renderValuesX = new List<double>();
5959
var renderValuesY = new List<double>();
6060
var valuesX = new List<double>();
6161
var valuesY = new List<double>();
6262

63+
var pointsCount = pointsDomain.Count == 1 ? pointsDomain[0] : pointsDomain.Count;
64+
6365
// Generate fine-grained samples to ensure better interpolation
6466
int fineSteps = (int)(pointsCount * CanvasSize);
6567

@@ -78,15 +80,35 @@ protected override (List<double> XValues, List<double> YValues) GenerateCurve(in
7880
return (renderValuesX, renderValuesY);
7981
}
8082

81-
// Collect output values
82-
for (int i = 0; i < pointsCount; i++)
83+
if (pointsDomain.Count == 1)
84+
{
85+
for (int i = 0; i < pointsCount; i++)
86+
{
87+
double targetX = (i / (double)(pointsCount - 1) * CanvasSize);
88+
int closestIndex = renderValuesX.IndexOf(renderValuesX.OrderBy(x => Math.Abs(x - targetX)).First());
89+
double y = renderValuesY[closestIndex];
90+
91+
valuesX.Add(targetX);
92+
valuesY.Add(y);
93+
}
94+
}
95+
else
8396
{
84-
double targetX = (i / (double)(pointsCount - 1) * CanvasSize);
85-
int closestIndex = renderValuesX.IndexOf(renderValuesX.OrderBy(x => Math.Abs(x - targetX)).First());
86-
double y = renderValuesY[closestIndex];
97+
double minInput = pointsDomain.Min();
98+
double maxInput = pointsDomain.Max();
99+
100+
// Normalize domain value & map to canvas X coordinate
101+
foreach (double t in pointsDomain)
102+
{
103+
double normalizedT = (t - minInput) / (maxInput - minInput);
104+
double targetX = normalizedT * CanvasSize;
105+
106+
int closestIndex = renderValuesX.IndexOf(renderValuesX.OrderBy(x => Math.Abs(x - targetX)).First());
107+
double y = renderValuesY[closestIndex];
87108

88-
valuesX.Add(targetX);
89-
valuesY.Add(y);
109+
valuesX.Add(targetX);
110+
valuesY.Add(y);
111+
}
90112
}
91113

92114
return (valuesX, valuesY);

src/Libraries/CoreNodes/CurveMapper/ControlLine.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public ControlLine(double cp1X, double cp1Y, double cp2X, double cp2Y, double ca
2121
ControlPoint2X = cp2X;
2222
ControlPoint2Y = cp2Y;
2323
}
24-
protected override (List<double> XValues, List<double> YValues) GenerateCurve(int pointsCount, bool isRender = false)
24+
protected override (List<double> XValues, List<double> YValues) GenerateCurve(List<double> pointsCount, bool isRender = false)
2525
{
2626
return (new List<double> { ControlPoint1X, ControlPoint2X }, new List<double> { ControlPoint1Y, ControlPoint2Y });
2727
}

0 commit comments

Comments
 (0)