Skip to content

Add tolerance based equals node #10004

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Sep 30, 2019
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/Engine/ProtoCore/Utils/MathUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,20 @@ public static bool IsLessThanOrEquals(double lhs, double rhs)
return (lhs < rhs) || Equals(lhs, rhs);
}

public static bool Equals(double lhs, double rhs)
public static bool Equals(double lhs, double rhs, double tolerance)
{
if (double.IsPositiveInfinity(lhs) && double.IsPositiveInfinity(rhs))
return true;

if (double.IsNegativeInfinity(lhs) && double.IsNegativeInfinity(rhs))
return true;

return Math.Abs(lhs - rhs) < Tolerance;
return Math.Abs(lhs - rhs) < tolerance;
}

public static bool Equals(double lhs, double rhs)
{
return Equals(lhs, rhs, Tolerance);
}
}
}
1 change: 1 addition & 0 deletions src/Libraries/CoreNodeModels/CoreNodeModels.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Equals.cs" />
<Compile Include="Input\ColorPalette.cs" />
<Compile Include="Input\DateTime.cs" />
<Compile Include="DynamoConvert.cs" />
Expand Down
93 changes: 93 additions & 0 deletions src/Libraries/CoreNodeModels/Equals.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using System.Linq;
using CoreNodeModels.Properties;
using Dynamo.Graph.Nodes;
using Newtonsoft.Json;
using ProtoCore.AST.AssociativeAST;
using ProtoCore.DSASM;
using ProtoCore.Utils;

namespace CoreNodeModels
{
[NodeName("==")]
[NodeDescription("EqualsWithToleranceDescription", typeof(Resources))]
[NodeCategory("Core.Math")]
[NodeSearchTags("EqualsWithToleranceSearchTags", typeof(Resources))]
[InPortTypes("double", "double", "double")]
[OutPortTypes("bool")]
[IsDesignScriptCompatible]
public class Equals : NodeModel
{
private static readonly DoubleNode tolerancePortDefaultValue = new DoubleNode(MathUtils.Tolerance);

[JsonConstructor]
private Equals(IEnumerable<PortModel> inPorts, IEnumerable<PortModel> outPorts) : base(inPorts, outPorts)
{
ArgumentLacing = LacingStrategy.Auto;
inPorts.ElementAt(2).DefaultValue = tolerancePortDefaultValue;
}

public Equals()
{
ArgumentLacing = LacingStrategy.Auto;

InPorts.Add(new PortModel(PortType.Input, this, new PortData("x", Resources.EqualsWithToleranceLhsRhsTooltip)));
InPorts.Add(new PortModel(PortType.Input, this, new PortData("y", Resources.EqualsWithToleranceLhsRhsTooltip)));
InPorts.Add(new PortModel(PortType.Input, this,
new PortData("tolerance", string.Format(Resources.EqualsWithToleranceTooltip, MathUtils.Tolerance), tolerancePortDefaultValue)));
OutPorts.Add(new PortModel(PortType.Output, this, new PortData("bool", Resources.EqualsWithToleranceOutportTooltip)));
RegisterAllPorts();
}

public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
{
if (!InPorts[0].IsConnected && !InPorts[1].IsConnected && !InPorts[2].IsConnected)
{
return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()) };
}

AssociativeNode rhs;
if (IsPartiallyApplied)
{
var connectedInputs = Enumerable.Range(0, InPorts.Count)
.Where(index => InPorts[index].IsConnected)
.Select(x => new IntNode(x) as AssociativeNode)
.ToList();
var arguments = AstFactory.BuildExprList(inputAstNodes);


var functionNode = new IdentifierListNode
{
LeftNode = new IdentifierNode("DSCore.Math"),
RightNode = new IdentifierNode("Equals")
};
IntNode paramNumNode = new IntNode(3);
var positionNode = AstFactory.BuildExprList(connectedInputs);

var inputParams = new List<AssociativeNode>
{
functionNode,
paramNumNode,
positionNode,
arguments,
AstFactory.BuildBooleanNode(true)
};

rhs = AstFactory.BuildFunctionCall("__CreateFunctionObject", inputParams);
}
else
{
UseLevelAndReplicationGuide(inputAstNodes);

rhs = AstFactory.BuildFunctionCall(new Func<double, double, double, bool>(DSCore.Math.Equals),
inputAstNodes);
}

return new[]
{
AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), rhs)
};
}
}
}
54 changes: 50 additions & 4 deletions src/Libraries/CoreNodeModels/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions src/Libraries/CoreNodeModels/Properties/Resources.en-US.resx
Original file line number Diff line number Diff line change
Expand Up @@ -590,4 +590,22 @@
<data name="ColorPaletteSearchTags" xml:space="preserve">
<value>color</value>
</data>
<data name="EqualsWithToleranceDescription" xml:space="preserve">
<value>Equals with tolerance input.</value>
<comment>Description for Equals with tolerance node</comment>
</data>
<data name="EqualsWithToleranceLhsRhsTooltip" xml:space="preserve">
<value>Integer or double value</value>
<comment>Equals with tolerance node input port tooltip</comment>
</data>
<data name="EqualsWithToleranceOutportTooltip" xml:space="preserve">
<value>Result of equality check</value>
</data>
<data name="EqualsWithToleranceSearchTags" xml:space="preserve">
<value>equals;tolerance</value>
</data>
<data name="EqualsWithToleranceTooltip" xml:space="preserve">
<value>Tolerance
Default value: {0}</value>
</data>
</root>
18 changes: 18 additions & 0 deletions src/Libraries/CoreNodeModels/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -590,4 +590,22 @@
<data name="ColorPaletteSearchTags" xml:space="preserve">
<value>color</value>
</data>
<data name="EqualsWithToleranceDescription" xml:space="preserve">
<value>Equals with tolerance input.</value>
<comment>Description for Equals with tolerance node</comment>
</data>
<data name="EqualsWithToleranceLhsRhsTooltip" xml:space="preserve">
<value>Integer or double value</value>
<comment>Equals with tolerance node input port tooltip</comment>
</data>
<data name="EqualsWithToleranceOutportTooltip" xml:space="preserve">
<value>Result of equality check</value>
</data>
<data name="EqualsWithToleranceSearchTags" xml:space="preserve">
<value>equals;tolerance</value>
</data>
<data name="EqualsWithToleranceTooltip" xml:space="preserve">
<value>Tolerance
Default value: {0}</value>
</data>
</root>
4 changes: 4 additions & 0 deletions src/Libraries/CoreNodes/CoreNodes.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@
<Name>DynamoCore</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\Engine\ProtoCore\ProtoCore.csproj">
<Project>{7a9e0314-966f-4584-baa3-7339cbb849d1}</Project>
<Name>ProtoCore</Name>
</ProjectReference>
<ProjectReference Include="..\..\NodeServices\DynamoServices.csproj">
<Project>{ef879a10-041d-4c68-83e7-3192685f1bae}</Project>
<Name>DynamoServices</Name>
Expand Down
14 changes: 14 additions & 0 deletions src/Libraries/CoreNodes/Math.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Autodesk.DesignScript.Runtime;
using DSCore.Properties;
using NCalc;
using ProtoCore.Utils;
using CSMath = System.Math;

namespace DSCore
Expand Down Expand Up @@ -200,6 +201,19 @@ public static double Abs(double number)
return CSMath.Abs(number);
}

/// <summary>
/// This method is ONLY used by the Equals (with tolerance) NodeModel node
/// </summary>
/// <param name="lhs"></param>
/// <param name="rhs"></param>
/// <param name="tol"></param>
/// <returns></returns>
[IsVisibleInDynamoLibrary(false)]
public static bool Equals(double lhs, double rhs, double tol)
{
return MathUtils.Equals(lhs, rhs, tol);
}

/// <summary>
/// Finds the absolute value of a number.
/// </summary>
Expand Down
3 changes: 3 additions & 0 deletions src/LibraryViewExtension/web/library/layoutSpecs.json
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,9 @@
{
"path": "Operators.=="
},
{
"path": "Core.Math.=="
},
{
"path": "Operators.>="
},
Expand Down
26 changes: 26 additions & 0 deletions test/DynamoCoreTests/DefaultArgumentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.IO;
using Dynamo.Graph.Nodes;
using Dynamo.Graph.Nodes.ZeroTouch;
using FFITarget.DesignScript;
using NUnit.Framework;

namespace Dynamo.Tests
Expand Down Expand Up @@ -86,5 +87,30 @@ public void TestDefaultArgumentExpressionResolutionWithConflict()

Assert.IsTrue(result.State == ElementState.Warning);
}

[Test]
public void TestDefaultArgumentExpressionWithReplicationGuides()
{
// Simulate loading of external libraries in Dynamo by importing
// FFITarget after preloading the standard set of libraries above
string libraryPath = "FFITarget.dll";

CurrentDynamoModel.LibraryServices.ImportLibrary(libraryPath);

string openPath = Path.Combine(TestDirectory,
@"core\dsevaluation\TestDefaultArgumentExpressionWithReplicationGuides.dyn");
OpenModel(openPath);

BeginRun();

// Assert that node using default argument expression with fully qualified Point class evaluates
var pt00 = Point.XYZ(1, 2, 0);
var pt01 = Point.XYZ(1, 3, 0);
var pt10 = Point.XYZ(2, 2, 0);
var pt11 = Point.XYZ(2, 3, 0);

AssertPreviewValue("cc365216-df02-41ce-9ea4-e477c06b7d55",
new object[] {new[] {pt00, pt01}, new[] {pt10, pt11}});
}
}
}
44 changes: 44 additions & 0 deletions test/DynamoCoreTests/Nodes/LogicTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using NUnit.Framework;

namespace Dynamo.Tests
Expand All @@ -12,6 +13,7 @@ protected override void GetLibrariesToPreload(List<string> libraries)
libraries.Add("VMDataBridge.dll");
libraries.Add("DesignScriptBuiltin.dll");
libraries.Add("DSCoreNodes.dll");
libraries.Add("FunctionObject.ds");
base.GetLibrariesToPreload(libraries);
}

Expand Down Expand Up @@ -254,6 +256,48 @@ public void testCompare_StringDouble()
AssertPreviewValue("a4c69409-8430-42a4-9769-2817a507b1b7", null);
AssertPreviewValue("5801abfd-e00f-408a-8bb1-8289b795686f", null);
}

[Test]
public void testToleranceEquals_defaultTolerance()
{
string testFilePath = Path.Combine(logicTestFolder, "testToleranceEquals_defaultTolerance.dyn");

RunModel(testFilePath);
AssertPreviewValue("d3ca0126-f365-4d79-8168-476022009dc2", false);
AssertPreviewValue("c2f69bf4-34be-47fa-8f0a-4a0ceca5910b", false);
}

[Test]
public void testToleranceEquals_lacing()
{
string testFilePath = Path.Combine(logicTestFolder, "testToleranceEquals_lacing.dyn");

RunModel(testFilePath);
AssertPreviewValue("89af328d-f688-489f-a0b8-e01566ee74d5", new[] {true, true, false, false});
AssertPreviewValue("9db0f6f3-0680-4c0f-bd60-82fd38ac536b",
new object[] {new[] {true, false, false, false}, new[] {false, true, false, false}});
AssertPreviewValue("399a6b0a-699f-4494-8160-d6e4301b7921", new[] {true, true});
}

[Test]
public void testToleranceEquals_map()
{
string testFilePath = Path.Combine(logicTestFolder, "testToleranceEquals_map.dyn");

RunModel(testFilePath);
AssertPreviewValue("94354c1d-853d-4932-9228-38b241bac6f3", new[] {true, true});
AssertPreviewValue("462b6cae-ceea-475a-ac4a-76dd79d17d68", new[] {true, true});
}

[Test]
public void testToleranceEquals_map2()
{
string testFilePath = Path.Combine(logicTestFolder, "testToleranceEquals_map2.dyn");

RunModel(testFilePath);
AssertPreviewValue("8f17012e-9331-455d-9760-3537233e7262",
new object[] {new[] {true, false}, new[] {false, true}, new[] {false, false}, new[] {false, false}});
}
}

[TestFixture]
Expand Down
Loading