Skip to content

Commit

Permalink
Karamba toolkit - Converters for K3D 1D model created (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
Fraser Greenroyd committed Mar 7, 2023
2 parents d80554f + ce12398 commit a97d459
Show file tree
Hide file tree
Showing 82 changed files with 6,788 additions and 1,314 deletions.
38 changes: 38 additions & 0 deletions .ci/unit-tests/Karamba3D_Engine_Tests/BaseTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* This file is part of the Buildings and Habitats object Model (BHoM)
* Copyright (c) 2015 - 2023, the respective contributors. All rights reserved.
*
* Each contributor holds copyright over their respective contributions.
* The project versioning (Git) records all such contribution source information.
*
*
* The BHoM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* The BHoM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

using BH.Engine.Adapters.Karamba3D;
using NUnit.Framework;

namespace Karamba3D_Engine_Tests
{
[TestFixture]
public class BaseTest
{
[TearDown]
public void TestTearDown()
{
// The logger will be reset after each test to avoid dependency between tests.
K3dLogger.Clean();
}
}
}
55 changes: 55 additions & 0 deletions .ci/unit-tests/Karamba3D_Engine_Tests/CroSecTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* This file is part of the Buildings and Habitats object Model (BHoM)
* Copyright (c) 2015 - 2023, the respective contributors. All rights reserved.
*
* Each contributor holds copyright over their respective contributions.
* The project versioning (Git) records all such contribution source information.
*
*
* The BHoM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* The BHoM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

using BH.Engine.Adapters.Karamba3D;
using Karamba.CrossSections;
using NUnit.Framework;
using System.Linq;

namespace Karamba3D_Engine_Tests
{
[TestFixture]
public class CroSecTests : BaseTest
{
private CroSec CreateCrossSectionToTest()
{
var material = MaterialTests.CreateMaterialToTest();
return new CroSec_Box("RandomFamily", "RandomName", "RandomCountry", null, material);
}

[Test]
public void CrossSections_WithSameGuids_WillBeInstancedOnce_Test()
{
// Arrange
var crossSection = CreateCrossSectionToTest();
crossSection.AddElemId(string.Empty); // the empty string means it will apply to all beams.
var model = TestUtilities.Create3NotEqualLengthHingesBeam(crossSection);

// Act
var bhomModel = model.ToBHoM();
var bhomMaterial = bhomModel.CrossSections.Single();

// Assert
Assert.AreEqual(bhomMaterial.BHoM_Guid, crossSection.guid);
}
}
}
227 changes: 227 additions & 0 deletions .ci/unit-tests/Karamba3D_Engine_Tests/CustomAsserts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
/*
* This file is part of the Buildings and Habitats object Model (BHoM)
* Copyright (c) 2015 - 2023, the respective contributors. All rights reserved.
*
* Each contributor holds copyright over their respective contributions.
* The project versioning (Git) records all such contribution source information.
*
*
* The BHoM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* The BHoM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

using BH.oM.Base;
using NUnit.Framework;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Karamba3D_Engine_Tests
{
public class BhOMEqualityTestOptions
{
public double DoubleTolerance { get; set; } = 0;
public float SingleTolerance { get; set; } = 0;

public decimal DecimalTolerance { get; set; } = 0;
public string FailureMessage { get; set; } = string.Empty;

public bool AreTolerancesEnabled => DoubleTolerance != 0 || SingleTolerance != 0 || DecimalTolerance != 0;
}

public static class CustomAsserts
{
public static void BhOMObjectsAreEqual<T>(T actual, T expected, BhOMEqualityTestOptions options = default)
{
if (options is null)
{
options = new BhOMEqualityTestOptions();
}
bool areEqual = AreEqualOrPropertiesEqual(actual, expected, out var notEqualProperties, options);

if (areEqual)
return;

var sb = new StringBuilder();
if (!notEqualProperties.Any())
{
sb.AppendLine($"{typeof(T)} are not equal");
}

foreach (var property in notEqualProperties)
{
sb.AppendLine($"The property \"{property.Name}\" of \"{typeof(T)}\" are not equal");
}

string message = string.Empty;
if (options.FailureMessage != string.Empty)
{
message += options.FailureMessage + Environment.NewLine;
}
Assert.Fail(message + sb);
}

private static bool AreEqualOrPropertiesEqual<T>(T actual, T expected, out IEnumerable<PropertyInfo> notEqualProperties, BhOMEqualityTestOptions options)
{
// If the type is string, value type or override the equal method, the equal method will be used
// else all the public readable properties will be compared
bool areEqual;
notEqualProperties = Enumerable.Empty<PropertyInfo>();

if (actual == null || expected == null)
{
return actual == null && expected == null;
}

if (EqualityCanBeDirectlyCheck(actual) && !options.AreTolerancesEnabled)
{
areEqual = Equals(actual, expected);
}
else
{
areEqual = CheckPropertiesEquality(actual, expected, out notEqualProperties, options);
}

return areEqual;
}

public static bool OverridesEqualsMethod(object obj)
{
return obj.GetType().GetMethods().Any(m => m.Name == "Equals" && m.DeclaringType != typeof(object));
}

private static bool CheckPropertiesEquality<T>(T actual, T expected, out IEnumerable<PropertyInfo> notEqualProperties, BhOMEqualityTestOptions options)
{
// The comparison will consider all the properties of the type T.
// 1. If the property type is string, value type or override the equal method,
// the equal method will be used.
// 2. If the type is IEnumerable each element of the enumerable will be tested.
// 3. If the type comes from IObject will be tested for property equality.
var failProperties = new List<PropertyInfo>();
foreach (var property in GetAllPublicReadableProperties(actual))
{
var areValuesEqual = true;
var actualValue = property?.GetValue(actual);
var expectedValue = property?.GetValue(expected);

if (actualValue == null || expectedValue == null)
{
areValuesEqual = actualValue == null && expectedValue == null;
}
else if (EqualityCanBeDirectlyCheck(actualValue))
{
areValuesEqual = AreAlmostEqual(actualValue, expectedValue, options);
}
else if (actualValue is IEnumerable actualEnumerable)
{
var expectedEnumerable = expectedValue as IEnumerable;
var actualEnumerator = actualEnumerable.GetEnumerator();
var expectedEnumerator = expectedEnumerable?.GetEnumerator();
bool actualCanMove = actualEnumerator.MoveNext();
bool expectedCanMove = expectedEnumerator?.MoveNext() ?? false;

while (actualCanMove && expectedCanMove && areValuesEqual)
{
// When any entity is not equal, the enumerables are not equal too.
areValuesEqual = AreEqualOrPropertiesEqual(actualEnumerator.Current, expectedEnumerator.Current, out _, options);

actualCanMove = actualEnumerator.MoveNext();
expectedCanMove = expectedEnumerator.MoveNext();
}

// If one can move and the other no, the enumerables
// have different length and are not equal.
if (actualCanMove || expectedCanMove)
{
areValuesEqual = false;
}

if (actualEnumerator is IDisposable actualDisposable)
{
actualDisposable.Dispose();
}

if (expectedEnumerator is IDisposable expectedDisposable)
{
expectedDisposable.Dispose();
}
}
else if (actualValue is IObject pActualObject)
{
var pExpectedObject = expectedValue as IObject;
areValuesEqual = CheckPropertiesEquality(pActualObject, pExpectedObject, out _, options);
}
else
{
throw new ArgumentException($"\"{actualValue.GetType()}\" property cannot be compared.");
}

if (!areValuesEqual)
{
failProperties.Add(property);
}
}

notEqualProperties = failProperties;
return !notEqualProperties.Any();
}

private static IEnumerable<PropertyInfo> GetAllPublicReadableProperties(object obj)
{
return obj.GetType()
.GetProperties()
.Where(p => p.Name != "BHoM_Guid")
.Where(p => p.CanRead)
.Where(p => p.GetMethod?.IsPublic ?? false);
}

private static bool EqualityCanBeDirectlyCheck(object obj)
{
return obj.GetType().IsValueType || obj is string || OverridesEqualsMethod(obj);
}

private static bool AreAlmostEqual<T>(T actualValue, T expectedValue, BhOMEqualityTestOptions options)
{
if (!options.AreTolerancesEnabled)
return Equals(actualValue, expectedValue);

if (actualValue is double actualDouble &&
expectedValue is double expectedDouble)
{
return Math.Abs(actualDouble - expectedDouble) < options.DoubleTolerance;
}

if (actualValue is float actualFloat &&
expectedValue is float expectedFloat)
{
return Math.Abs(actualFloat - expectedFloat) < options.SingleTolerance;
}

if (actualValue is decimal actualDecimal &&
expectedValue is decimal expectedDecimal)
{
return Math.Abs(actualDecimal - expectedDecimal) < options.DecimalTolerance;
}

if (actualValue is IObject)
{
return CheckPropertiesEquality(actualValue, expectedValue, out _, options);
}

return Equals(actualValue, expectedValue);
}
}
}
Binary file not shown.
51 changes: 51 additions & 0 deletions .ci/unit-tests/Karamba3D_Engine_Tests/JointTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* This file is part of the Buildings and Habitats object Model (BHoM)
* Copyright (c) 2015 - 2023, the respective contributors. All rights reserved.
*
* Each contributor holds copyright over their respective contributions.
* The project versioning (Git) records all such contribution source information.
*
*
* The BHoM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* The BHoM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

using BH.Engine.Adapters.Karamba3D;
using BH.oM.Structure.Constraints;
using Karamba.Joints;
using NUnit.Framework;

namespace Karamba3D_Engine_Tests
{
[TestFixture]
public class JointTests : BaseTest
{
[Test]
public void ToBHoMConversionTest()
{
var joint = new Joint();
joint.c[0] = 0;
joint.c[1] = 1;
Joint nullJoint = null;

var barRelease = joint.ToBHoM();
var nullBarRelease = nullJoint.ToBHoM();

Assert.IsNull(nullBarRelease);
Assert.AreEqual(barRelease.StartRelease.TranslationX, DOFType.Spring);
Assert.AreEqual(barRelease.StartRelease.TranslationalStiffnessX, 0);
Assert.AreEqual(barRelease.StartRelease.TranslationY, DOFType.Spring);
Assert.AreEqual(barRelease.StartRelease.TranslationalStiffnessY, 1);
}
}
}
Loading

0 comments on commit a97d459

Please sign in to comment.