diff --git a/.editorconfig b/.editorconfig
index 7c9792f..df5e28a 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -2,44 +2,6 @@ root=true
# Microsoft .NET properties
csharp_new_line_before_members_in_object_initializers=true
-# ReSharper properties
-resharper_align_multiline_argument=true
-resharper_align_multiline_expression=true
-resharper_align_multiple_declaration=true
-resharper_align_multline_type_parameter_constrains=true
-resharper_align_multline_type_parameter_list=true
-resharper_align_tuple_components=true
-resharper_blank_lines_after_control_transfer_statements=1
-resharper_blank_lines_before_block_statements=1
-resharper_braces_for_dowhile=required_for_multiline
-resharper_braces_for_fixed=required_for_multiline
-resharper_braces_for_for=required_for_multiline
-resharper_braces_for_foreach=required_for_multiline
-resharper_braces_for_ifelse=required_for_multiline
-resharper_braces_for_lock=required_for_multiline
-resharper_braces_for_using=required_for_multiline
-resharper_braces_for_while=required_for_multiline
-resharper_constructor_or_destructor_body=expression_body
-resharper_csharp_wrap_before_binary_opsign=true
-resharper_csharp_wrap_extends_list_style=chop_if_long
-resharper_csharp_wrap_parameters_style=chop_if_long
-resharper_empty_block_style=together_same_line
-resharper_indent_nested_foreach_stmt=true
-resharper_indent_nested_for_stmt=true
-resharper_keep_existing_invocation_parens_arrangement=false
-resharper_keep_existing_switch_expression_arrangement=false
-resharper_local_function_body=expression_body
-resharper_max_array_initializer_elements_on_line=8
-resharper_max_formal_parameters_on_line=3
-resharper_max_initializer_elements_on_line=3
-resharper_method_or_operator_body=expression_body
-resharper_outdent_commas=true
-resharper_place_simple_switch_expression_on_single_line=true
-resharper_wrap_array_initializer_style=chop_if_long
-resharper_wrap_chained_binary_expressions=chop_if_long
-resharper_wrap_enum_declaration=chop_if_long
-resharper_wrap_switch_expression=chop_if_long
-
##########################################
# File Extension Settings
##########################################
@@ -106,10 +68,10 @@ visual_basic_preferred_modifier_order=Partial,Default,Private,Protected,Public,F
dotnet_style_readonly_field=true:warning
# Parentheses preferences
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parentheses-preferences
-# dotnet_style_parentheses_in_arithmetic_binary_operators=always_for_clarity:suggestion
-# dotnet_style_parentheses_in_relational_binary_operators=always_for_clarity:suggestion
-# dotnet_style_parentheses_in_other_binary_operators=always_for_clarity:suggestion
-# dotnet_style_parentheses_in_other_operators=always_for_clarity:suggestion
+dotnet_style_parentheses_in_arithmetic_binary_operators=always_for_clarity:suggestion
+dotnet_style_parentheses_in_relational_binary_operators=always_for_clarity:suggestion
+dotnet_style_parentheses_in_other_binary_operators=always_for_clarity:suggestion
+dotnet_style_parentheses_in_other_operators=always_for_clarity:suggestion
# Expression-level preferences
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences
dotnet_style_object_initializer=true:warning
@@ -403,6 +365,27 @@ dotnet_naming_rule.parameters_rule.symbols=parameters_group
dotnet_naming_rule.parameters_rule.style=camel_case_style
dotnet_naming_rule.parameters_rule.severity=warning
+# Microsoft .NET properties
+csharp_prefer_braces=false:none
+csharp_space_after_keywords_in_control_flow_statements=true
+csharp_space_between_method_call_parameter_list_parentheses=false
+csharp_space_between_method_declaration_parameter_list_parentheses=false
+csharp_space_between_parentheses=false
+
+# ReSharper properties
+resharper_braces_redundant=true
+resharper_empty_block_style=together_same_line
+resharper_local_function_body=expression_body
+resharper_space_within_catch_parentheses=false
+resharper_space_within_checked_parentheses=false
+resharper_space_within_foreach_parentheses=false
+resharper_space_within_for_parentheses=false
+resharper_space_within_if_parentheses=false
+resharper_space_within_parentheses=false
+resharper_space_within_switch_parentheses=false
+resharper_space_within_using_parentheses=false
+resharper_space_within_while_parentheses=false
+
##########################################
# License
##########################################
diff --git a/.travis.yml b/.travis.yml
index f4b043c..d3b7017 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,6 +16,7 @@ branches:
only:
- master
- development
+ - feature/*
notifications:
slack: paramdigma:FtUcdwSDOynOHw2M479kXHxs#geometry-library
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index a67b316..a9c5f85 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -5,7 +5,7 @@
// List of extensions which should be recommended for users of this workspace.
"recommendations": [
"ban.spellright",
- "ms-vscode.csharp",
+ "ms-dotnettools.csharp",
"Gruntfuggly.todo-tree",
"brainfit.vscode-coverage-highlighter",
"josefpihrt-vscode.snippetica-csharp",
diff --git a/Paramdigma.Core.sln.DotSettings b/Paramdigma.Core.sln.DotSettings
new file mode 100644
index 0000000..0b65484
--- /dev/null
+++ b/Paramdigma.Core.sln.DotSettings
@@ -0,0 +1,4 @@
+
+ True
+ True
+ True
\ No newline at end of file
diff --git a/coverage/cobertura.xml b/coverage/cobertura.xml
index 34a95ee..b2695c4 100644
--- a/coverage/cobertura.xml
+++ b/coverage/cobertura.xml
@@ -1,10 +1,10 @@
-
+
-
+
@@ -590,7 +590,7 @@
-
+
@@ -640,7 +640,7 @@
-
+
@@ -7644,31 +7644,31 @@
-
+
-
+
-
+
-
+
-
+
-
+
@@ -7678,74 +7678,74 @@
-
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
-
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
+
-
-
+
-
+
+
-
+
-
-
+
+
-
+
-
+
@@ -7764,232 +7764,239 @@
-
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
-
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
+
+
+
+
-
+
-
+
-
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -8001,9 +8008,9 @@
-
-
-
+
+
+
@@ -8015,151 +8022,152 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
+
-
+
-
-
-
+
+
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
-
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
@@ -8170,58 +8178,70 @@
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -8662,22 +8682,22 @@
-
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
@@ -8693,27 +8713,27 @@
-
+
-
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
@@ -8725,17 +8745,17 @@
-
+
-
+
-
+
@@ -8755,12 +8775,12 @@
-
+
-
+
@@ -8780,7 +8800,7 @@
-
+
@@ -8802,9 +8822,9 @@
-
-
-
+
+
+
@@ -8816,21 +8836,21 @@
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -8838,44 +8858,44 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -8914,306 +8934,306 @@
-
+
-
-
-
+
+
+
-
+
-
-
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
+
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
-
+
-
-
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Collections/Interval.cs b/src/Collections/Interval.cs
index fa36d8d..67821e2 100644
--- a/src/Collections/Interval.cs
+++ b/src/Collections/Interval.cs
@@ -14,12 +14,10 @@ public struct Interval
/// Ending value of the interval.
public Interval(double start, double end)
{
- if (start == end)
- throw new Exception("Cannot create Interval out of two equal numbers");
if (double.IsNaN(start) || double.IsInfinity(start))
- throw new Exception("Start value is invalid");
+ throw new ArithmeticException("Start value is invalid");
if (double.IsNaN(end) || double.IsInfinity(end))
- throw new Exception("End value is invalid");
+ throw new ArithmeticException("End value is invalid");
this.Start = start;
this.End = end;
}
@@ -130,7 +128,7 @@ public bool Contains(double number)
{
double min = this.HasInvertedDirection ? this.End : this.Start;
double max = this.HasInvertedDirection ? this.Start : this.End;
- return min < number && number < max;
+ return min <= number && number <= max;
}
///
diff --git a/src/Curves/Geodesics.cs b/src/Curves/Geodesics.cs
index 4ccbfe2..93329da 100644
--- a/src/Curves/Geodesics.cs
+++ b/src/Curves/Geodesics.cs
@@ -1,6 +1,4 @@
-using System;
using System.Collections.Generic;
-using Paramdigma.Core;
using Paramdigma.Core.Geometry;
using Paramdigma.Core.HalfEdgeMesh;
diff --git a/src/Curves/LevelSets.cs b/src/Curves/LevelSets.cs
index cd7f154..95a5ae3 100644
--- a/src/Curves/LevelSets.cs
+++ b/src/Curves/LevelSets.cs
@@ -1,4 +1,3 @@
-using System;
using System.Collections.Generic;
using Paramdigma.Core.Geometry;
using Paramdigma.Core.HalfEdgeMesh;
diff --git a/src/Exceptions/UnsetGeometryException.cs b/src/Exceptions/UnsetGeometryException.cs
new file mode 100644
index 0000000..ce252d6
--- /dev/null
+++ b/src/Exceptions/UnsetGeometryException.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace Paramdigma.Core.Exceptions
+{
+ ///
+ /// Represents errors that ocur when using a geometry that has the 'isUnset' flag set to true.
+ ///
+ public class UnsetGeometryException : Exception
+ {
+ ///
+ public UnsetGeometryException() { }
+
+ ///
+ public UnsetGeometryException( string message ) : base( message ) { }
+
+ ///
+ public UnsetGeometryException( string message, Exception innerException ) { }
+ }
+}
\ No newline at end of file
diff --git a/src/Geometry/2D/Ray2d.cs b/src/Geometry/2D/Ray2d.cs
index ef6a342..0a5d0db 100644
--- a/src/Geometry/2D/Ray2d.cs
+++ b/src/Geometry/2D/Ray2d.cs
@@ -1,10 +1,23 @@
+using System;
+
namespace Paramdigma.Core.Geometry
{
///
- /// Represents a 2-dimensional ray.
+ /// Represents an infinite 2-dimensional ray.
///
public class Ray2d
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Origin point.
+ /// Direction vector.
+ public Ray2d(Point2d origin, Vector2d direction)
+ {
+ this.Origin = origin ?? throw new ArgumentNullException(nameof(origin));
+ this.Direction = direction ?? throw new ArgumentNullException(nameof(direction));
+ }
+
///
/// Gets or sets the origin of the ray.
///
diff --git a/src/Geometry/2D/Vector2d.cs b/src/Geometry/2D/Vector2d.cs
index ef054ae..e80f0e2 100644
--- a/src/Geometry/2D/Vector2d.cs
+++ b/src/Geometry/2D/Vector2d.cs
@@ -13,7 +13,8 @@ public class Vector2d
/// X coordinate.
public double X
{
- get; set;
+ get;
+ set;
}
///
@@ -22,7 +23,8 @@ public double X
/// Y coordinate.
public double Y
{
- get; set;
+ get;
+ set;
}
///
@@ -31,9 +33,7 @@ public double Y
/// Vector to duplicate.
/// New vector with same values.
public Vector2d(Vector2d vector)
- : this(vector.X, vector.Y)
- {
- }
+ : this(vector.X, vector.Y) { }
///
/// Initializes a new instance of the class from a point.
@@ -41,9 +41,7 @@ public Vector2d(Vector2d vector)
/// Point to convert.
/// New vector with same values.
public Vector2d(Point2d point)
- : this(point.X, point.Y)
- {
- }
+ : this(point.X, point.Y) { }
///
/// Initializes a new instance of the class.
@@ -66,6 +64,16 @@ public Vector2d(double x, double y)
///
public double Length => Math.Sqrt(this.LengthSquared);
+ ///
+ /// Creates a vector in the World X direction {1;0}
+ ///
+ public static Vector2d WorldX => new Vector2d(1, 0);
+
+ ///
+ /// Creates a vector in the World Y direction {0;1}
+ ///
+ public static Vector2d WorldY => new Vector2d(0, 1);
+
///
/// Returns a unit vector of this vector.
///
diff --git a/src/Geometry/3D/Line.cs b/src/Geometry/3D/Line.cs
index 78488b9..85966b8 100644
--- a/src/Geometry/3D/Line.cs
+++ b/src/Geometry/3D/Line.cs
@@ -1,3 +1,6 @@
+using System;
+using Paramdigma.Core.Collections;
+
namespace Paramdigma.Core.Geometry
{
///
@@ -10,15 +13,17 @@ public class Line : BaseCurve
///
public Point3d StartPoint
{
- get; set;
+ get;
+ set;
}
///
- /// /// Gets or sets the line's end point.
+ /// Gets or sets the line's end point.
///
public Point3d EndPoint
{
- get; set;
+ get;
+ set;
}
///
@@ -55,7 +60,7 @@ public Line(Point3d origin, Vector3d direction, double length)
///
/// Parameter of the point. Must be between 0 and 1.
/// Point at specified parameter.
- public override Point3d PointAt(double t) => this.StartPoint + (t * (this.EndPoint - this.StartPoint));
+ public override Point3d PointAt(double t) => this.StartPoint + (Domain.RemapToUnit(t) * (this.EndPoint - this.StartPoint));
///
/// Computes the tangent at the given parameter.
@@ -79,7 +84,7 @@ public override Vector3d NormalAt(double t)
Vector3d tangent = TangentAt(t);
var v = new Vector3d();
- if (tangent.Dot(Vector3d.UnitZ) == 1)
+ if (Math.Abs(tangent.Dot(Vector3d.UnitZ) - 1) < Settings.Tolerance)
v = Vector3d.UnitX;
else
v = Vector3d.UnitZ;
diff --git a/src/Geometry/3D/Mesh/Mesh.cs b/src/Geometry/3D/Mesh/Mesh.cs
index dae34e9..05e0853 100644
--- a/src/Geometry/3D/Mesh/Mesh.cs
+++ b/src/Geometry/3D/Mesh/Mesh.cs
@@ -1,6 +1,4 @@
-using System;
-using System.Collections.Generic;
-using Paramdigma.Core;
+using System.Collections.Generic;
using Paramdigma.Core.Geometry;
namespace Paramdigma.Core.HalfEdgeMesh
diff --git a/src/Geometry/3D/Mesh/MeshEdge.cs b/src/Geometry/3D/Mesh/MeshEdge.cs
index da4e892..686b9a1 100644
--- a/src/Geometry/3D/Mesh/MeshEdge.cs
+++ b/src/Geometry/3D/Mesh/MeshEdge.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
namespace Paramdigma.Core.HalfEdgeMesh
{
diff --git a/src/Geometry/3D/Mesh/MeshGeometry.cs b/src/Geometry/3D/Mesh/MeshGeometry.cs
index 89da595..6f2524e 100644
--- a/src/Geometry/3D/Mesh/MeshGeometry.cs
+++ b/src/Geometry/3D/Mesh/MeshGeometry.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Generic;
using Paramdigma.Core.HalfEdgeMesh;
namespace Paramdigma.Core.Geometry
diff --git a/src/Geometry/3D/Mesh/MeshHalfEdge.cs b/src/Geometry/3D/Mesh/MeshHalfEdge.cs
index 28f0094..876f696 100644
--- a/src/Geometry/3D/Mesh/MeshHalfEdge.cs
+++ b/src/Geometry/3D/Mesh/MeshHalfEdge.cs
@@ -1,6 +1,4 @@
-using System;
-
-namespace Paramdigma.Core.HalfEdgeMesh
+namespace Paramdigma.Core.HalfEdgeMesh
{
///
/// Represents a mesh half-edge.
diff --git a/src/Geometry/3D/Mesh/MeshPoint.cs b/src/Geometry/3D/Mesh/MeshPoint.cs
index c172f79..2da9ca1 100644
--- a/src/Geometry/3D/Mesh/MeshPoint.cs
+++ b/src/Geometry/3D/Mesh/MeshPoint.cs
@@ -1,4 +1,3 @@
-using System.Collections;
using System.Collections.Generic;
using Paramdigma.Core.Geometry;
diff --git a/src/Geometry/3D/Mesh/MeshTopology.cs b/src/Geometry/3D/Mesh/MeshTopology.cs
index e583787..39c590c 100644
--- a/src/Geometry/3D/Mesh/MeshTopology.cs
+++ b/src/Geometry/3D/Mesh/MeshTopology.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
namespace Paramdigma.Core.HalfEdgeMesh
{
diff --git a/src/Geometry/3D/Mesh/MeshVertex.cs b/src/Geometry/3D/Mesh/MeshVertex.cs
index 2d171db..0e37e68 100644
--- a/src/Geometry/3D/Mesh/MeshVertex.cs
+++ b/src/Geometry/3D/Mesh/MeshVertex.cs
@@ -1,5 +1,4 @@
-using System.Collections;
-using System.Collections.Generic;
+using System.Collections.Generic;
using Paramdigma.Core.Geometry;
namespace Paramdigma.Core.HalfEdgeMesh
diff --git a/src/Geometry/3D/Plane.cs b/src/Geometry/3D/Plane.cs
index f7f80b6..c864025 100644
--- a/src/Geometry/3D/Plane.cs
+++ b/src/Geometry/3D/Plane.cs
@@ -127,8 +127,10 @@ public Plane(Point3d ptA, Point3d ptB, Point3d ptC)
Vector3d normal = tempX.Cross(tempY);
double colinearCheck = Math.Abs(1 - tempY.Dot(tempX));
+ var compare = tempX.Dot(tempY);
+
// Ensure points are not co-linear
- if (tempY.Dot(tempX) == 1)
+ if (Math.Abs(compare - 1) <= Settings.Tolerance)
throw new System.Exception("Cannot create plane out of co-linear points.");
Origin = ptA;
@@ -220,7 +222,7 @@ public Point3d ClosestPoint(Point3d point)
///
/// Point to compute distance to.
/// Distance to point.
- public double DistanceTo(Point3d point) => ((Vector3d)(point - Origin)).Dot(ZAxis);
+ public double DistanceTo(Point3d point) => (point - Origin).Dot(ZAxis);
///
/// Returns the parametric equation for this plane.
diff --git a/src/Geometry/3D/Point3d.cs b/src/Geometry/3D/Point3d.cs
index a6a40eb..741f743 100644
--- a/src/Geometry/3D/Point3d.cs
+++ b/src/Geometry/3D/Point3d.cs
@@ -70,6 +70,12 @@ public Point3d(Point4d point)
///
public static Point3d WorldOrigin => new Point3d(0, 0, 0);
+ ///
+ /// Performs a deep clone of the point.
+ ///
+ /// Returns a copy of this point instance.
+ public Point3d Clone() => new Point3d(this.X, this.Y, this.Z);
+
///
/// Gets the euclidean distance between this point and the provided one.
///
@@ -141,7 +147,6 @@ public Point3d(Point4d point)
/// .
public static Point3d operator /(Point3d point, double scalar) => new Point3d(point.X / scalar, point.Y / scalar, point.Z / scalar);
-
///
/// Checks equality between two points.
///
diff --git a/src/Geometry/3D/Point4d.cs b/src/Geometry/3D/Point4d.cs
index 752f933..6de279c 100644
--- a/src/Geometry/3D/Point4d.cs
+++ b/src/Geometry/3D/Point4d.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections;
-using System.Collections.Generic;
-using Paramdigma.Core.Geometry;
-using Paramdigma.Core.LinearAlgebra;
namespace Paramdigma.Core.Geometry
{
@@ -49,12 +45,24 @@ public Point4d(Point3d pt, double w)
weight = w;
}
+ ///
+ /// Initializes a new instance of the class from a 3-dimensional point and a weight.
+ ///
+ /// Point.
+ /// New 4-dimensional point with the specified values.
+ public Point4d(Point3d pt)
+ : base(pt)
+ {
+ weight = 1;
+ }
+
///
/// Gets or sets the weight of this point.
///
public double Weight
{
- get => weight; set
+ get => weight;
+ set
{
weight = value;
if (IsUnset)
@@ -62,6 +70,11 @@ public double Weight
}
}
+ ///
+ /// Returns the raw position of the point4d (without taking into account weight).
+ ///
+ public Point3d Position => new Point3d(X, Y, Z);
+
///
public static Point4d operator +(Point4d point, Point4d point2) => new Point4d(point.X + point2.X, point.Y + point2.Y, point.Z + point2.Z, point.Weight + point2.Weight);
@@ -80,9 +93,6 @@ public double Weight
///
public static Point4d operator /(Point4d point, double scalar) => new Point4d(point.X / scalar, point.Y / scalar, point.Z / scalar, point.Weight / scalar);
- ///
- public static Point4d operator /(double scalar, Point4d point) => new Point4d(point.X / scalar, point.Y / scalar, point.Z / scalar, point.Weight / scalar);
-
///
public static bool operator ==(Point4d point, Point4d point2) => point.Equals(point2);
@@ -97,7 +107,8 @@ public override bool Equals(object obj)
{
if (obj is Point4d pt)
{
- return base.Equals(obj) && this.Weight == pt.Weight;
+ return base.Equals(obj)
+ && Math.Abs(this.Weight - pt.Weight) < Settings.Tolerance;
}
else
{
@@ -114,4 +125,4 @@ public override int GetHashCode()
// TODO: Add hasWeightedCoordinates boolean and implement a weightCoordinates() method
}
-}
+}
\ No newline at end of file
diff --git a/src/Geometry/3D/Polyline.cs b/src/Geometry/3D/Polyline.cs
index 078026a..ef1780f 100644
--- a/src/Geometry/3D/Polyline.cs
+++ b/src/Geometry/3D/Polyline.cs
@@ -1,6 +1,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Linq;
+using Paramdigma.Core.Exceptions;
namespace Paramdigma.Core.Geometry
{
@@ -9,10 +11,32 @@ namespace Paramdigma.Core.Geometry
///
public class Polyline : BaseCurve, IEnumerable
{
+ // TODO: Frame, Normal, Binormal and Tangent calculation is still slightly sketchy. It must be checked.
private readonly List knots;
private List segments;
private bool segmentsNeedUpdate;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Polyline()
+ {
+ knots = new List();
+ segments = new List();
+ segmentsNeedUpdate = false;
+ }
+
+ ///
+ /// Initializes a new instance of the class from a list of points.
+ ///
+ /// List of points.
+ public Polyline(List knots)
+ {
+ this.knots = knots;
+ segments = new List();
+ this.RebuildSegments();
+ }
+
///
/// Gets the segment lines of the polyline.
///
@@ -22,41 +46,37 @@ public List Segments
get
{
if (segmentsNeedUpdate)
- RebuildSegments();
+ this.RebuildSegments();
return segments;
}
}
///
- /// Gets a value indicating whether the polyline is closed (first point == last point).
+ /// Gets the knot at the specified index.
///
- public bool IsClosed => knots[0] == knots[^1];
+ /// The index.
+ public Point3d this[int index] => this.knots[index];
///
- /// Gets a value indicating whether the polyline is unset.
+ /// Gets the list of knots for this polyline.
///
- public bool IsUnset => knots.Count == 0;
+ public List Knots => this.knots;
///
- /// Initializes a new instance of the class.
+ /// Gets a value indicating whether the polyline is closed (first point == last point).
///
- public Polyline()
- {
- knots = new List();
- segments = new List();
- segmentsNeedUpdate = false;
- }
+ public bool IsClosed => knots[0] == knots[^1];
///
- /// Initializes a new instance of the class from a list of points.
+ /// Gets a value indicating whether the polyline is unset.
///
- /// List of points.
- public Polyline(List knots)
- {
- this.knots = knots;
- segments = new List();
- segmentsNeedUpdate = true;
- }
+ public bool IsUnset => knots.Count == 0;
+
+ ///
+ public IEnumerator GetEnumerator() => ((IEnumerable)knots).GetEnumerator();
+
+ ///
+ IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)knots).GetEnumerator();
///
/// Add a new knot vertex at the end of the polyline.
@@ -73,7 +93,7 @@ public void AddKnot(Point3d knot)
///
/// Point to add.
/// Location to add at.
- public void AddKnot(Point3d knot, int index)
+ public void InsertKnot(Point3d knot, int index)
{
knots.Insert(index, knot); // Add knot to list
segmentsNeedUpdate = true;
@@ -81,27 +101,29 @@ public void AddKnot(Point3d knot, int index)
///
/// Delete a specific knot if it exists in the polyline.
+ /// If the point exists multiple times, it will remove the first occurrence.
///
/// Point to delete.
public void RemoveKnot(Point3d knot)
{
- if (knots.Contains(knot))
- {
- knots.Remove(knot);
- segmentsNeedUpdate = true;
- }
+ if (!this.knots.Contains(knot))
+ throw new Exception("Point is not a knot in the polyline");
+ this.knots.Remove(knot);
+ this.segmentsNeedUpdate = true;
}
///
/// Delete a knot at a specific index.
///
/// Index to delete knot at.
- public void RemoveKnot(int index)
+ public void RemoveKnotAt(int index)
{
if (IsUnset)
- throw new Exception("Cannot erase knot from an Unset polyline");
- if (index < 0 || index > segments.Count - 1)
+ throw new UnsetGeometryException("Cannot erase knot from an Unset polyline");
+ if (index < 0 || index > knots.Count - 1)
throw new IndexOutOfRangeException("Knot index must be within the Knot list count");
+ knots.RemoveAt(index);
+ this.segmentsNeedUpdate = true;
}
private void RebuildSegments()
@@ -115,26 +137,35 @@ private void RebuildSegments()
t += l.Length;
var t1 = t;
l.Domain = new Collections.Interval(t0, t1);
-
- // Add segment to list.
segments.Add(l);
}
}
///
- public override Vector3d BinormalAt(double t) => throw new NotImplementedException();
+ public override Vector3d BinormalAt(double t) => (from segment in this.segments
+ where segment.Domain.Contains(t)
+ select segment.BinormalAt(t)).FirstOrDefault();
///
- public override Vector3d NormalAt(double t) => throw new NotImplementedException();
+ public override Vector3d NormalAt(double t) => (from segment in this.segments
+ where segment.Domain.Contains(t)
+ select segment.NormalAt(t)).FirstOrDefault();
///
- public override Point3d PointAt(double t) => throw new NotImplementedException();
+ public override Point3d PointAt(double t) => (from segment in this.segments
+ where segment.Domain.Contains(t)
+ select segment.PointAt(t)).FirstOrDefault();
+
///
- public override Vector3d TangentAt(double t) => throw new NotImplementedException();
+ public override Vector3d TangentAt(double t) => (from segment in this.segments
+ where segment.Domain.Contains(t)
+ select segment.TangentAt(t)).FirstOrDefault();
///
- public override Plane FrameAt(double t) => throw new NotImplementedException();
+ public override Plane FrameAt(double t) => (from segment in this.segments
+ where segment.Domain.Contains(t)
+ select segment.FrameAt(t)).FirstOrDefault();
///
protected override double ComputeLength()
@@ -144,13 +175,24 @@ protected override double ComputeLength()
return length;
}
- ///
- public override bool CheckValidity() => throw new NotImplementedException();
-
- ///
- public IEnumerator GetEnumerator() => ((IEnumerable)knots).GetEnumerator();
+ ///
+ /// Checks the validity of the polyline. Currently only checks if some segments are collapsed (length == 0);
+ ///
+ /// True if polyline has no collapsed segments.
+ public override bool CheckValidity()
+ {
+ if (IsUnset)
+ return false;
+ bool valid = true;
+ foreach (var segment in this.segments)
+ {
+ if (segment.Length > Settings.Tolerance)
+ continue;
+ valid = false;
+ break;
+ }
- ///
- IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)knots).GetEnumerator();
+ return valid;
+ }
}
}
\ No newline at end of file
diff --git a/src/Geometry/3D/Primitives/Cylinder.cs b/src/Geometry/3D/Primitives/Cylinder.cs
index ba14b53..cdf3f89 100644
--- a/src/Geometry/3D/Primitives/Cylinder.cs
+++ b/src/Geometry/3D/Primitives/Cylinder.cs
@@ -56,6 +56,10 @@ public Plane FrameAt(double u, double v)
throw new System.NotImplementedException();
}
+ public double DistanceTo(Point3d point) => throw new System.NotImplementedException();
+
+ public Point3d ClosestPointTo(Point3d point) => throw new System.NotImplementedException();
+
///
public Vector3d NormalAt(double u, double v)
{
diff --git a/src/Geometry/3D/Primitives/Sphere.cs b/src/Geometry/3D/Primitives/Sphere.cs
index 553b847..17d9704 100644
--- a/src/Geometry/3D/Primitives/Sphere.cs
+++ b/src/Geometry/3D/Primitives/Sphere.cs
@@ -29,6 +29,8 @@ public class Sphere : ISurface
///
public double DistanceTo(Point3d point) => Plane.DistanceTo(point) - Radius;
+ public Point3d ClosestPointTo(Point3d point) => Plane.Origin + ((point - Plane.Origin).Unit() * Radius);
+
///
public Plane FrameAt(double u, double v) => throw new System.NotImplementedException();
diff --git a/src/Geometry/3D/Primitives/Torus.cs b/src/Geometry/3D/Primitives/Torus.cs
index 6967485..75d9c7a 100644
--- a/src/Geometry/3D/Primitives/Torus.cs
+++ b/src/Geometry/3D/Primitives/Torus.cs
@@ -48,6 +48,12 @@ public Torus(Plane plane, double majorRadius, double minorRadius)
///
public Plane FrameAt(double u, double v) => throw new System.NotImplementedException();
+ ///
+ public double DistanceTo(Point3d point) => throw new System.NotImplementedException();
+
+ ///
+ public Point3d ClosestPointTo(Point3d point) => throw new System.NotImplementedException();
+
///
public Vector3d NormalAt(double u, double v) => throw new System.NotImplementedException();
diff --git a/src/Geometry/3D/Ray.cs b/src/Geometry/3D/Ray.cs
index baba886..e36c870 100644
--- a/src/Geometry/3D/Ray.cs
+++ b/src/Geometry/3D/Ray.cs
@@ -1,3 +1,5 @@
+using System;
+
namespace Paramdigma.Core.Geometry
{
///
@@ -22,8 +24,8 @@ public class Ray
/// Vector representing the direction of the ray.
public Ray(Point3d origin, Vector3d direction)
{
- Origin = origin;
- Direction = direction;
+ Origin = origin ?? throw new ArgumentNullException(nameof(origin));
+ Direction = direction ?? throw new ArgumentNullException(nameof(direction));
}
///
diff --git a/src/Geometry/3D/Vector3d.cs b/src/Geometry/3D/Vector3d.cs
index 7894f76..adf6410 100644
--- a/src/Geometry/3D/Vector3d.cs
+++ b/src/Geometry/3D/Vector3d.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Generic;
namespace Paramdigma.Core.Geometry
{
@@ -48,7 +47,7 @@ public Vector3d(double xCoord, double yCoord, double zCoord)
}
///
- /// Gets the Euclidiean length squared of this vector.
+ /// Gets the Euclidean length squared of this vector.
///
/// Squared Length of the vector.
public double LengthSquared => DotProduct(this, this);
diff --git a/src/Geometry/Base/BaseCurve.cs b/src/Geometry/Base/BaseCurve.cs
index f9be678..2ab278a 100644
--- a/src/Geometry/Base/BaseCurve.cs
+++ b/src/Geometry/Base/BaseCurve.cs
@@ -1,5 +1,4 @@
-using System.Collections.Generic;
-using Paramdigma.Core.Collections;
+using Paramdigma.Core.Collections;
#pragma warning disable 1591
diff --git a/src/Geometry/Base/BasePoint.cs b/src/Geometry/Base/BasePoint.cs
index 58579d5..c916147 100644
--- a/src/Geometry/Base/BasePoint.cs
+++ b/src/Geometry/Base/BasePoint.cs
@@ -67,7 +67,10 @@ public double Z
/// Gets or sets a value indicating whether the current point is unset.
///
/// True if Unset.
- public bool IsUnset { get; set; }
+ public bool IsUnset
+ {
+ get; set;
+ }
private double x;
private double y;
@@ -173,7 +176,12 @@ public void Negate()
/// Converts a point to an array of numbers.
///
/// Array with cartesian coordinates of point.
- public double[] ToArray() => new double[] { x, y, z };
+ public double[] ToArray() => new double[] { this.x, this.y, this.z };
+
+ ///
+ /// Performs a deep clone of the point.
+ ///
+ /// Returns a copy of this BasePoint instance.
///
public override bool Equals(object obj)
diff --git a/src/Geometry/Interfaces/ISurface.cs b/src/Geometry/Interfaces/ISurface.cs
index f77d097..48f836b 100644
--- a/src/Geometry/Interfaces/ISurface.cs
+++ b/src/Geometry/Interfaces/ISurface.cs
@@ -11,13 +11,19 @@ public interface ISurface
/// Gets the domain in the U direction.
///
/// .
- Interval DomainU { get; }
+ Interval DomainU
+ {
+ get;
+ }
///
/// Gets the domain in the V direction.
///
/// .
- Interval DomainV { get; }
+ Interval DomainV
+ {
+ get;
+ }
///
/// Compute a point at the specified surface coordinates.
@@ -30,7 +36,7 @@ public interface ISurface
///
/// Compute the normal at the specified surface coordinates.
///
- /// U coordiante.
+ /// U coordinate.
/// V coordinate.
/// Normal vector.
Vector3d NormalAt(double u, double v);
@@ -38,9 +44,23 @@ public interface ISurface
///
/// Compute the tangent plane at the specified surface coordinates.
///
- /// U coordiante.
+ /// U coordinate.
/// V coordinate.
/// Tangent plane.
Plane FrameAt(double u, double v);
+
+ ///
+ /// Compute the distance between this surface and a point
+ ///
+ /// Point to compute distance to.
+ /// Number representing the distance.
+ double DistanceTo(Point3d point);
+
+ ///
+ /// Compute the projection of a point on this surface.
+ ///
+ /// Point to compute distance to.
+ /// Projected 3d point on the surface.
+ Point3d ClosestPointTo(Point3d point);
}
}
\ No newline at end of file
diff --git a/src/Geometry/Intersect/Intersect.cs b/src/Geometry/Intersect/Intersect.cs
index de0e72a..d225d27 100644
--- a/src/Geometry/Intersect/Intersect.cs
+++ b/src/Geometry/Intersect/Intersect.cs
@@ -1,10 +1,7 @@
using System;
-using System.Collections;
using System.Collections.Generic;
-using Paramdigma.Core.Curves;
using Paramdigma.Core.Geometry;
using Paramdigma.Core.HalfEdgeMesh;
-using Paramdigma.Core.LinearAlgebra;
namespace Paramdigma.Core
{
@@ -26,14 +23,14 @@ public static ISLinePlane LinePlane(Line line, Plane plane, out Point3d intersec
{
Vector3d u = line.EndPoint - line.StartPoint;
Vector3d w = line.StartPoint - plane.Origin;
-
+
double d = Vector3d.DotProduct(plane.ZAxis, u);
double n = -Vector3d.DotProduct(plane.ZAxis, w);
- if (d <= 0.000001)
+ if (Math.Abs(d) <= Settings.Tolerance)
{
// Segment is parallel to plane
- if (n == 0)
+ if (Math.Abs(n) < Settings.Tolerance)
{
// Segment lies in plane
intersectionPoint = null;
diff --git a/src/Geometry/SpatialStructures/PointCloud.cs b/src/Geometry/SpatialStructures/PointCloud.cs
index 8f13e93..e737eda 100644
--- a/src/Geometry/SpatialStructures/PointCloud.cs
+++ b/src/Geometry/SpatialStructures/PointCloud.cs
@@ -1,7 +1,4 @@
-using System.Collections;
using System.Collections.Generic;
-using System.Drawing;
-using Paramdigma.Core.Geometry;
namespace Paramdigma.Core.SpatialSearch
{
diff --git a/src/Geometry/SpatialStructures/PointCloudMember.cs b/src/Geometry/SpatialStructures/PointCloudMember.cs
index e4c7848..d446423 100644
--- a/src/Geometry/SpatialStructures/PointCloudMember.cs
+++ b/src/Geometry/SpatialStructures/PointCloudMember.cs
@@ -1,5 +1,3 @@
-using System.Collections;
-using System.Collections.Generic;
using System.Drawing;
using Paramdigma.Core.Geometry;
diff --git a/src/IO/OBJWritter.cs b/src/IO/OBJWritter.cs
index 80c471e..99c4ce1 100644
--- a/src/IO/OBJWritter.cs
+++ b/src/IO/OBJWritter.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections;
-
-#pragma warning disable 1591
+#pragma warning disable 1591
namespace Paramdigma.Core.IO
{
diff --git a/src/LinearAlgebra/Triplet.cs b/src/LinearAlgebra/Triplet.cs
index 5230853..d6dfe01 100644
--- a/src/LinearAlgebra/Triplet.cs
+++ b/src/LinearAlgebra/Triplet.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
#pragma warning disable 1591
diff --git a/src/Utility/Convert.cs b/src/Utility/Convert.cs
index d9bd878..06f06b3 100644
--- a/src/Utility/Convert.cs
+++ b/src/Utility/Convert.cs
@@ -1,10 +1,4 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using Paramdigma.Core.Curves;
using Paramdigma.Core.Geometry;
-using Paramdigma.Core.HalfEdgeMesh;
-using Paramdigma.Core.LinearAlgebra;
namespace Paramdigma.Core
{
diff --git a/src/Utility/Settings.cs b/src/Utility/Settings.cs
index f83b01c..7a26d24 100644
--- a/src/Utility/Settings.cs
+++ b/src/Utility/Settings.cs
@@ -1,6 +1,4 @@
-using System;
using System.IO;
-using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
@@ -31,13 +29,13 @@ public static int MaxDecimals
private static int tesselationLevel = 10;
///
- /// Gets the default tesselation level when converting nurbs to meshes.
+ /// Gets the default tessellation level when converting nurbs to meshes.
///
- /// Integer representing the default tesselation level.
+ /// Integer representing the default tessellation level.
public static int GetDefaultTesselationLevel() => tesselationLevel;
///
- /// Sets the default tesselation level when converting nurbs to meshes.
+ /// Sets the default tessellation level when converting nurbs to meshes.
///
private static void SetDefaultTesselationLevel(int value) => tesselationLevel = value;
@@ -75,5 +73,4 @@ private struct EmbeddedSettings
public int DefaultTesselation;
}
}
-
}
\ No newline at end of file
diff --git a/tests/Collections/IntervalTests.cs b/tests/Collections/IntervalTests.cs
index 6df637c..8be7799 100644
--- a/tests/Collections/IntervalTests.cs
+++ b/tests/Collections/IntervalTests.cs
@@ -7,12 +7,18 @@ namespace Paramdigma.Core.Tests
public class IntervalTests
{
[Fact]
- public async void CanCreate_Interval()
+ public void CanCreate_Interval()
{
var i0 = new Interval(0, 1);
var i1 = Interval.Unit;
var i2 = new Interval(i0);
+
+ Assert.Equal(1, i0.Length);
+ Assert.Throws(() => new Interval(double.NaN,1));
+ Assert.Throws(() => new Interval(0, double.NaN));
}
+
+
[Fact]
public void Can_CheckAndModifyDirection()
diff --git a/tests/Extensions/ListExtensionsTests.cs b/tests/Extensions/ListExtensionsTests.cs
new file mode 100644
index 0000000..c5ca0f1
--- /dev/null
+++ b/tests/Extensions/ListExtensionsTests.cs
@@ -0,0 +1,29 @@
+using Xunit;
+using Paramdigma.Core.Extensions;
+using Paramdigma.Core.Geometry;
+
+namespace Paramdigma.Core.Tests.Extensions
+{
+ public class ListExtensionsTests
+ {
+ [Fact]
+ public void CanCreate_RepeatedDefault()
+ {
+ for (int i = 1; i < 10; i++)
+ {
+ var list2 = Lists.RepeatedDefault(i);
+ Assert.True(list2.Count == i);
+ }
+ }
+
+ [Fact]
+ public void CanCreate_Repeated()
+ {
+ for (int i = 1; i < 10; i++)
+ {
+ var list2 = Lists.Repeated(new Point3d(1,1,1),4 );
+ list2.ForEach(pt => Assert.Equal(new Point3d(1,1,1),pt));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/Geometry/2D/Polyline2dTests.cs b/tests/Geometry/2D/Polyline2dTests.cs
index e814e63..0b128c6 100644
--- a/tests/Geometry/2D/Polyline2dTests.cs
+++ b/tests/Geometry/2D/Polyline2dTests.cs
@@ -1,4 +1,3 @@
-using System;
using System.Collections;
using System.Collections.Generic;
using Paramdigma.Core.Geometry;
diff --git a/tests/Geometry/2D/Ray2dTests.cs b/tests/Geometry/2D/Ray2dTests.cs
new file mode 100644
index 0000000..f503807
--- /dev/null
+++ b/tests/Geometry/2D/Ray2dTests.cs
@@ -0,0 +1,20 @@
+using System;
+using Paramdigma.Core.Geometry;
+using Xunit;
+
+namespace Paramdigma.Core.Tests.Geometry
+{
+ public class Ray2dTests
+ {
+ [Fact]
+ public void CanCreate_AndThrowExceptions()
+ {
+ var ray = new Ray2d(Point2d.Origin, Vector2d.WorldX);
+ Assert.Equal(Point2d.Origin, ray.Origin);
+ Assert.Equal(Vector2d.WorldX, ray.Direction);
+
+ Assert.Throws(() => new Ray2d(Point2d.Origin, null));
+ Assert.Throws(() => new Ray2d(null, Vector2d.WorldY));
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/Geometry/3D/Intersect3dTests.cs b/tests/Geometry/3D/Intersect3dTests.cs
new file mode 100644
index 0000000..308fdf5
--- /dev/null
+++ b/tests/Geometry/3D/Intersect3dTests.cs
@@ -0,0 +1,76 @@
+using Paramdigma.Core.Geometry;
+using Xunit;
+
+namespace Paramdigma.Core.Tests.Geometry._3D
+{
+ public class Intersect3dTests
+ {
+ [Fact]
+ public void CanIntersect_Line_Line()
+ {
+ var lineA = new Line(Point3d.WorldOrigin, new Point3d(1, 1, 1));
+ var lineB = new Line(new Point3d(1, 0, 0), new Point3d(0, 1, 1));
+
+ var status = Intersect3D.LineLine(lineA, lineB, out Intersect3D.IRLineLine result);
+ Assert.Equal(Intersect3D.ISLineLine.Point, status);
+ Assert.Equal(new Point3d(0.5, 0.5, 0.5), result.PointA);
+ Assert.Equal(new Point3d(0.5, 0.5, 0.5), result.PointB);
+ Assert.Equal(0.5,result.TA);
+ Assert.Equal(0.5,result.TB);
+ }
+
+
+ [Fact]
+ public void CanIntersect_Line_Plane()
+ {
+ var expected = new Point3d(.4, .23, 0);
+ var a = new Point3d(.4, .23, 1);
+ var b = new Point3d(.4, .23, -1);
+ var lineA = new Line(a, b);
+ var plane = Plane.WorldXY;
+
+ var status = Intersect3D.LinePlane(lineA, plane, out Point3d actual);
+ Assert.Equal(Intersect3D.ISLinePlane.Point, status);
+ Assert.Equal(expected, actual);
+ }
+
+ [Fact]
+ public void CannotIntersect_Line_Plane_Parallel()
+ {
+ var a = new Point3d(.6, .6, 0);
+ var b = new Point3d(.4, .2, 0);
+ var lineA = new Line(a, b);
+ var plane = Plane.WorldXY;
+
+ var status = Intersect3D.LinePlane(lineA, plane, out Point3d actual);
+ Assert.Equal(Intersect3D.ISLinePlane.OnPlane, status);
+ Assert.Null(actual);
+ }
+
+ [Fact]
+ public void CannotIntersect_Line_Plane_DoNotTouch()
+ {
+ var a = new Point3d(.4, .23, 1);
+ var b = new Point3d(.4, .23, .2);
+ var lineA = new Line(a, b);
+ var plane = Plane.WorldXY;
+
+ var status = Intersect3D.LinePlane(lineA, plane, out Point3d actual);
+ Assert.Equal(Intersect3D.ISLinePlane.NoIntersection, status);
+ Assert.Null(actual);
+ }
+
+ [Fact]
+ public void CannotIntersect_Line_Plane_DoNotTouchAndAreParallel()
+ {
+ var a = new Point3d(.4, .23, 1);
+ var b = new Point3d(.9, .23, 1);
+ var lineA = new Line(a, b);
+ var plane = Plane.WorldXY;
+
+ var status = Intersect3D.LinePlane(lineA, plane, out Point3d actual);
+ Assert.Equal(Intersect3D.ISLinePlane.NoIntersection, status);
+ Assert.Null(actual);
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/Geometry/3D/LineTests.cs b/tests/Geometry/3D/LineTests.cs
index 323dd28..bd44045 100644
--- a/tests/Geometry/3D/LineTests.cs
+++ b/tests/Geometry/3D/LineTests.cs
@@ -1,6 +1,4 @@
using System;
-using System.Collections;
-using System.Collections.Generic;
using Paramdigma.Core.Geometry;
using Xunit;
diff --git a/tests/Geometry/3D/NurbsTests.cs b/tests/Geometry/3D/NurbsTests.cs
index 905cd10..f549dfb 100644
--- a/tests/Geometry/3D/NurbsTests.cs
+++ b/tests/Geometry/3D/NurbsTests.cs
@@ -61,10 +61,6 @@ public void NurbsCurvePoint_Works()
var pt = NurbsCalculator.CurvePoint(3, 1, u, new Point3d[] { p0, p1, p2, p3 }, (double)i / n);
var pt2 = NurbsCalculator.CurvePoint(3, 2, u2, new Point3d[] { p0, p1, p2, p3 }, (double)i / n);
var pt3 = NurbsCalculator.CurvePoint(3, 3, u3, new Point3d[] { p0, p1, p2, p3 }, (double)i / n);
- Console.WriteLine($"t: {(double)i / n} — {pt}");
- Console.WriteLine($"t: {(double)i / n} — {pt2}");
- Console.WriteLine($"t: {(double)i / n} — {pt3}");
- Console.WriteLine("---");
}
watch.Stop();
Console.WriteLine(watch.Elapsed);
diff --git a/tests/Geometry/3D/PlaneTests.cs b/tests/Geometry/3D/PlaneTests.cs
index b3c40b9..9ec1916 100644
--- a/tests/Geometry/3D/PlaneTests.cs
+++ b/tests/Geometry/3D/PlaneTests.cs
@@ -67,5 +67,46 @@ public void CanCompute_ClosestPoint()
Assert.True(result == expected);
Assert.True(dist == 1);
}
+
+ [Fact]
+ public void LinearPoints_ThrowError()
+ {
+ var ptA = new Point3d(0, 0, 0);
+ var ptB = new Point3d(0.5, 0.5, 0.5);
+ var ptC = new Point3d(1, 1, 1);
+
+ Assert.Throws(() => new Plane(ptA, ptB, ptC));
+ }
+
+ [Fact]
+ public void CanRemap_ToXYPlane()
+ {
+ var yz = Plane.WorldYZ;
+ var pt = new Point3d(1, 1, 0);
+ var expected = new Point3d(0, 1, 1);
+ var result = yz.RemapToWorldXYSpace(pt);
+ Assert.Equal(expected, result);
+ }
+
+ [Fact]
+ public void CanRemap_FromXYPlane()
+ {
+ var yz = Plane.WorldYZ;
+ var pt = new Point3d(0, 1, 1);
+ var expected = new Point3d(1, 1, 0);
+ var result = yz.RemapToPlaneSpace(pt);
+ Assert.Equal(expected, result);
+ }
+
+ [Fact]
+ public void CanBe_Flipped()
+ {
+ var xy = Plane.WorldXY;
+ var flipped = xy.Clone();
+ flipped.Flip();
+ Assert.Equal(xy.XAxis, flipped.YAxis);
+ Assert.Equal(xy.YAxis, flipped.XAxis);
+ Assert.Equal(xy.ZAxis, -flipped.ZAxis);
+ }
}
}
\ No newline at end of file
diff --git a/tests/Geometry/3D/Point3dTests.cs b/tests/Geometry/3D/Point3dTests.cs
index 4328600..95b31f3 100644
--- a/tests/Geometry/3D/Point3dTests.cs
+++ b/tests/Geometry/3D/Point3dTests.cs
@@ -1,3 +1,4 @@
+using System.Collections.Generic;
using Paramdigma.Core.Geometry;
using Xunit;
@@ -119,6 +120,40 @@ public void CanConvert_ToArray()
Assert.True(arr.Length == 3);
Assert.True(arr[0] == 1 && arr[1] == 0 && arr[2] == 0);
}
-
+
+ [Theory]
+ [MemberData(nameof(UnsetPointData))]
+ public void CanToggleUnset_WithX(BasePoint pt)
+ {
+ Assert.True(pt.IsUnset);
+ pt.X += 1;
+ Assert.False(pt.IsUnset);
+
+ }
+
+ [Theory]
+ [MemberData(nameof(UnsetPointData))]
+ public void CanToggleUnset_WithY(BasePoint pt)
+ {
+ Assert.True(pt.IsUnset);
+ pt.Y += 1;
+ Assert.False(pt.IsUnset);
+
+ }
+
+ [Theory]
+ [MemberData(nameof(UnsetPointData))]
+ public void CanToggleUnset_WithZ(BasePoint pt)
+ {
+ Assert.True(pt.IsUnset);
+ pt.Z += 1;
+ Assert.False(pt.IsUnset);
+ }
+
+ public static IEnumerable