From 9f429415fb211151d25f61823b5e2fc90a8c2f4b Mon Sep 17 00:00:00 2001 From: Alan Rynne Date: Sun, 1 Nov 2020 16:00:47 +0100 Subject: [PATCH] fix(style): Completely changed .editorconfig and executed code cleanup --- .editorconfig | 516 ++++-------------- src/Collections/Interval.cs | 27 +- src/Collections/Matrix{T}.cs | 36 +- src/Curves/Geodesics.cs | 15 +- src/Curves/LevelSets.cs | 39 +- src/Exceptions/UnsetGeometryException.cs | 6 +- src/Extensions/Lists.cs | 1 + src/Geometry/2D/BoundingBox2d.cs | 80 ++- src/Geometry/2D/Delaunay.cs | 39 +- src/Geometry/2D/DelaunayEdge.cs | 29 +- src/Geometry/2D/DelaunayPoint.cs | 19 +- src/Geometry/2D/DelaunayTriangle.cs | 74 +-- src/Geometry/2D/Line2d.cs | 26 +- src/Geometry/2D/Point2d.cs | 56 +- src/Geometry/2D/Polyline2d.cs | 36 +- src/Geometry/2D/Ray2d.cs | 13 +- src/Geometry/2D/Vector2d.cs | 58 +- src/Geometry/3D/Circle.cs | 30 +- src/Geometry/3D/Line.cs | 43 +- src/Geometry/3D/Mesh/Mesh.cs | 94 ++-- src/Geometry/3D/Mesh/MeshCorner.cs | 13 +- src/Geometry/3D/Mesh/MeshEdge.cs | 21 +- src/Geometry/3D/Mesh/MeshFace.cs | 20 +- src/Geometry/3D/Mesh/MeshGeometry.cs | 43 +- src/Geometry/3D/Mesh/MeshHalfEdge.cs | 56 +- src/Geometry/3D/Mesh/MeshPoint.cs | 30 +- src/Geometry/3D/Mesh/MeshTopology.cs | 69 ++- src/Geometry/3D/Mesh/MeshVertex.cs | 28 +- src/Geometry/3D/Nurbs/NurbsCalculator.cs | 285 +++++++--- src/Geometry/3D/Nurbs/NurbsCurve.cs | 33 +- src/Geometry/3D/Plane.cs | 78 ++- src/Geometry/3D/Point3d.cs | 75 ++- src/Geometry/3D/Point4d.cs | 139 ++++- src/Geometry/3D/Polyline.cs | 70 ++- src/Geometry/3D/Primitives/Box.cs | 39 +- src/Geometry/3D/Primitives/Cylinder.cs | 40 +- src/Geometry/3D/Primitives/Sphere.cs | 52 +- src/Geometry/3D/Primitives/Torus.cs | 36 +- src/Geometry/3D/Ray.cs | 16 +- src/Geometry/3D/Vector3d.cs | 52 +- src/Geometry/3D/VectorNd.cs | 64 ++- src/Geometry/Base/BaseCurve.cs | 17 +- src/Geometry/Base/BasePoint.cs | 29 +- src/Geometry/Base/InvalidCurveException.cs | 2 + src/Geometry/Interfaces/ICurve.cs | 4 + src/Geometry/Interfaces/ISurface.cs | 15 +- src/Geometry/Intersect/Intersect.cs | 22 +- src/Geometry/Intersect/IntersectErrors.cs | 50 +- src/Geometry/SpatialStructures/PointCloud.cs | 25 +- .../SpatialStructures/PointCloudMember.cs | 6 +- src/Geometry/SpatialStructures/Quadtree.cs | 22 +- src/IO/OBJMeshData.cs | 30 +- src/IO/OFFMeshData.cs | 12 +- src/IO/OFFReader.cs | 2 + src/IO/OFFResult.cs | 8 +- src/IO/OFFWritter.cs | 2 + src/LinearAlgebra/Complex.cs | 49 +- src/LinearAlgebra/LeastSquaresLinearFit.cs | 12 +- src/LinearAlgebra/Triplet.cs | 35 +- src/Optimization/GradientDescent.cs | 18 +- src/Optimization/GradientDescentOptions.cs | 23 +- src/Optimization/KMeansCluster.cs | 12 + src/Optimization/KMeansClustering.cs | 91 +-- src/Paramdigma.Core.csproj | 4 - src/Utility/Convert.cs | 6 +- src/Utility/Settings.cs | 26 +- tests/Collections/IntervalTests.cs | 14 +- tests/Curves/LevelSetsTests.cs | 10 +- tests/Extensions/ListExtensionsTests.cs | 1 + tests/Geometry/2D/DelaunayTests.cs | 78 +-- tests/Geometry/2D/Line2dTests.cs | 5 + tests/Geometry/2D/Point2dTests.cs | 11 +- tests/Geometry/2D/Polyline2dTests.cs | 39 +- tests/Geometry/2D/Vector2dTests.cs | 18 +- tests/Geometry/3D/BoxTests.cs | 1 + tests/Geometry/3D/CircleTests.cs | 9 +- tests/Geometry/3D/CylinderTests.cs | 2 + tests/Geometry/3D/Intersect3dTests.cs | 3 + tests/Geometry/3D/LineTests.cs | 7 + tests/Geometry/3D/MeshFaceTests.cs | 42 +- tests/Geometry/3D/MeshGeometryTests.cs | 47 +- tests/Geometry/3D/MeshPointTests.cs | 1 + tests/Geometry/3D/MeshTests.cs | 7 + tests/Geometry/3D/MeshVertexTests.cs | 29 +- tests/Geometry/3D/NurbsCurveData.cs | 1 + tests/Geometry/3D/NurbsCurveTests.cs | 50 +- tests/Geometry/3D/NurbsTests.cs | 40 +- tests/Geometry/3D/PlaneTests.cs | 10 + tests/Geometry/3D/Point3dData.cs | 1 + tests/Geometry/3D/Point3dTests.cs | 23 +- tests/Geometry/3D/Point4dTests.cs | 13 +- tests/Geometry/3D/Polyline3dTests.cs | 17 +- tests/Geometry/3D/Ray3dTests.cs | 1 + tests/Geometry/3D/SphereTests.cs | 10 +- tests/Geometry/3D/Vector3dTests.cs | 8 + tests/Geometry/3D/VectorNd_Tests.cs | 87 ++- .../GradientDescentOptionsTests.cs | 2 + tests/Optimization/GradientDescentTests.cs | 5 +- tests/Optimization/KMeansClusteringTests.cs | 33 +- tests/RhinoConversions.cs | 19 +- tests/Utilities/JsonFileDataAttribute.cs | 15 +- tests/Utilities/ResourcesTests.cs | 18 +- 102 files changed, 2153 insertions(+), 1542 deletions(-) diff --git a/.editorconfig b/.editorconfig index 315152e..b981a9d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,387 +1,80 @@ root=true -# Microsoft .NET properties -csharp_new_line_before_members_in_object_initializers=true - -########################################## -# File Extension Settings -########################################## - -# Visual Studio Solution Files -[*.sln] -indent_style=tab - -# Visual Studio XML Project Files -[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] -indent_size=2 - -# Various XML Configuration Files -[*.{xml,config,props,targets,nuspec,resx,ruleset,vsixmanifest,vsct}] -indent_size=2 - -# JSON Files -[*.{json,json5}] -indent_size=2 - -# YAML Files -[*.{yml,yaml}] -indent_size=2 - -# Markdown Files -[*.md] -trim_trailing_whitespace=false - -# Web Files -[*.{htm,html,js,ts,tsx,css,sass,scss,less,svg,vue}] -indent_size=2 - -# Batch Files -[*.{cmd,bat}] -end_of_line=crlf - -# Bash Files -[*.sh] -end_of_line=lf - -########################################## -# .NET Language Conventions -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions -########################################## - -# .NET Code Style Settings -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#net-code-style-settings -[*.{cs,csx,cake,vb}] -# "this." and "Me." qualifiers -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#this-and-me -dotnet_style_qualification_for_field=true:silent -dotnet_style_qualification_for_property=true:silent -dotnet_style_qualification_for_method=true:silent -dotnet_style_qualification_for_event=true:silent -# Language keywords instead of framework type names for type references -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#language-keywords -dotnet_style_predefined_type_for_locals_parameters_members=true:warning -dotnet_style_predefined_type_for_member_access=true:warning -# Modifier preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#normalize-modifiers -dotnet_style_require_accessibility_modifiers=always:warning -csharp_preferred_modifier_order=public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async -visual_basic_preferred_modifier_order=Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async -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 -# Expression-level preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences -dotnet_style_object_initializer=true:warning -dotnet_style_collection_initializer=true:warning -dotnet_style_explicit_tuple_names=true:warning -dotnet_style_prefer_inferred_tuple_names=true:warning -dotnet_style_prefer_inferred_anonymous_type_member_names=true:warning -dotnet_style_prefer_auto_properties=true:warning -dotnet_style_prefer_is_null_check_over_reference_equality_method=true:refactoring -dotnet_style_prefer_conditional_expression_over_assignment=false:refactoring -dotnet_style_prefer_conditional_expression_over_return=false:refactoring -dotnet_style_prefer_compound_assignment=true:warning -# Null-checking preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#null-checking-preferences -dotnet_style_coalesce_expression=true:warning -dotnet_style_null_propagation=true:warning -# Parameter preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parameter-preferences -dotnet_code_quality_unused_parameters=all:suggestion -# More style options (Undocumented) -# https://github.com/MicrosoftDocs/visualstudio-docs/issues/3641 -dotnet_style_operator_placement_when_wrapping=end_of_line - -# C# Code Style Settings -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-code-style-settings -[*.{cs,csx,cake}] -# Implicit and explicit types -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#implicit-and-explicit-types -csharp_style_var_for_built_in_types=true:refactoring -csharp_style_var_when_type_is_apparent=true:refactoring -csharp_style_var_elsewhere=true:refactoring -# Expression-bodied members -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-bodied-members -csharp_style_expression_bodied_methods=true:refactoring -csharp_style_expression_bodied_constructors=true:refactoring -csharp_style_expression_bodied_operators=true:refactoring -csharp_style_expression_bodied_properties=true:refactoring -csharp_style_expression_bodied_indexers=true:refactoring -csharp_style_expression_bodied_accessors=true:refactoring -csharp_style_expression_bodied_lambdas=true:refactoring -csharp_style_expression_bodied_local_functions=true:refactoring -# Pattern matching -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#pattern-matching -csharp_style_pattern_matching_over_is_with_cast_check=true:suggestion -csharp_style_pattern_matching_over_as_with_null_check=true:suggestion -# Inlined variable declarations -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#inlined-variable-declarations -csharp_style_inlined_variable_declaration=true:warning -# Expression-level preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences -csharp_prefer_simple_default_expression=true:warning -# "Null" checking preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-null-checking-preferences -csharp_style_throw_expression=true:warning -csharp_style_conditional_delegate_call=true:warning -# Code block preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#code-block-preferences -csharp_prefer_braces=false -# Unused value preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#unused-value-preferences -csharp_style_unused_value_expression_statement_preference=discard_variable:refactoring -csharp_style_unused_value_assignment_preference=discard_variable:refactoring -# Index and range preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#index-and-range-preferences -csharp_style_prefer_index_operator=true:warning -csharp_style_prefer_range_operator=true:warning -# Miscellaneous preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#miscellaneous-preferences -csharp_style_deconstructed_variable_declaration=true:warning -csharp_style_pattern_local_over_anonymous_function=true:warning -csharp_using_directive_placement=outside_namespace:silent -csharp_prefer_static_local_function=true:warning -csharp_prefer_simple_using_statement=false:warning - -########################################## -# .NET Formatting Conventions -# https://docs.microsoft.com/visualstudio/ide/editorconfig-code-style-settings-reference#formatting-conventions -########################################## - -# Organize usings -# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#organize-using-directives -dotnet_sort_system_directives_first=true -# Newline options -# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#new-line-options -csharp_new_line_before_open_brace=all -csharp_new_line_before_else=true -csharp_new_line_before_catch=true -csharp_new_line_before_finally=true -csharp_new_line_before_members_in_object_initializers=true -csharp_new_line_before_members_in_anonymous_types=true -csharp_new_line_between_query_expression_clauses=true - -# Indentation options -# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#indentation-options -csharp_indent_case_contents=true -csharp_indent_switch_labels=true -csharp_indent_labels=no_change -csharp_indent_block_contents=true -csharp_indent_braces=false -csharp_indent_case_contents_when_block=false -# Spacing options -# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#spacing-options -csharp_space_after_cast=false -csharp_space_after_keywords_in_control_flow_statements=true -csharp_space_between_parentheses=false -csharp_space_before_colon_in_inheritance_clause=true -csharp_space_after_colon_in_inheritance_clause=true -csharp_space_around_binary_operators=before_and_after -csharp_space_between_method_declaration_parameter_list_parentheses=false -csharp_space_between_method_declaration_empty_parameter_list_parentheses=false -csharp_space_between_method_declaration_name_and_open_parenthesis=false -csharp_space_between_method_call_parameter_list_parentheses=false -csharp_space_between_method_call_empty_parameter_list_parentheses=false -csharp_space_between_method_call_name_and_opening_parenthesis=false -csharp_space_after_comma=true -csharp_space_before_comma=false -csharp_space_after_dot=false -csharp_space_before_dot=false -csharp_space_after_semicolon_in_for_statement=true -csharp_space_before_semicolon_in_for_statement=false -csharp_space_around_declaration_statements=false -csharp_space_before_open_square_brackets=false -csharp_space_between_empty_square_brackets=false -csharp_space_between_square_brackets=false -# Wrapping options -# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#wrap-options -csharp_preserve_single_line_statements=false -csharp_preserve_single_line_blocks=false - -########################################## -# .NET Naming Conventions -# https://docs.microsoft.com/visualstudio/ide/editorconfig-naming-conventions -########################################## +[*] +# Most of the standard properties are supported +indent_size=4 +max_line_length=100 -[*.{cs,csx,cake,vb}] +# Most frequently used .NET-coding-convention properties are supported +csharp_space_between_parentheses=control_flow_statements,expressions,type_casts +csharp_style_var_for_built_in_types=true:suggestion -########################################## -# Styles -########################################## +# dotnet_diagnostic rules are supported +dotnet_diagnostic.cs1058.severity=suggestion -# camel_case_style - Define the camelCase style -dotnet_naming_style.camel_case_style.capitalization=camel_case -# pascal_case_style - Define the PascalCase style -dotnet_naming_style.pascal_case_style.capitalization=pascal_case -# first_upper_style - The first character must start with an upper-case character -dotnet_naming_style.first_upper_style.capitalization=first_word_upper -# prefix_interface_with_i_style - Interfaces must be PascalCase and the first character of an interface must be an 'I' -dotnet_naming_style.prefix_interface_with_i_style.capitalization=pascal_case -dotnet_naming_style.prefix_interface_with_i_style.required_prefix=I -# prefix_type_parameters_with_t_style - Generic Type Parameters must be PascalCase and the first character must be a 'T' -dotnet_naming_style.prefix_type_parameters_with_t_style.capitalization=pascal_case -dotnet_naming_style.prefix_type_parameters_with_t_style.required_prefix=T -# disallowed_style - Anything that has this style applied is marked as disallowed -# dotnet_naming_style.disallowed_style.capitalization=pascal_case -# dotnet_naming_style.disallowed_style.required_prefix=____RULE_VIOLATION____ -# dotnet_naming_style.disallowed_style.required_suffix=____RULE_VIOLATION____ -# internal_error_style - This style should never occur... if it does, it's indicates a bug in file or in the parser using the file -# dotnet_naming_style.internal_error_style.capitalization=pascal_case -# dotnet_naming_style.internal_error_style.required_prefix=____INTERNAL_ERROR____ -# dotnet_naming_style.internal_error_style.required_suffix=____INTERNAL_ERROR____ +# JetBrains Rider custom properties for code formatting styles +resharper_csharp_blank_lines_around_invocable=2 -########################################## -# .NET Design Guideline Field Naming Rules -# Naming rules for fields follow the .NET Framework design guidelines -# https://docs.microsoft.com/dotnet/standard/design-guidelines/index -########################################## +# JetBrains Rider custom properties for code syntax styles +csharp_default_private_modifier=explicit +braces_for_ifelse=not_required -# All public/protected/protected_internal constant fields must be PascalCase -# https://docs.microsoft.com/dotnet/standard/design-guidelines/field -dotnet_naming_symbols.public_protected_constant_fields_group.applicable_accessibilities=public, protected, protected_internal -dotnet_naming_symbols.public_protected_constant_fields_group.required_modifiers=const -dotnet_naming_symbols.public_protected_constant_fields_group.applicable_kinds=field -dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.symbols=public_protected_constant_fields_group -dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.style=pascal_case_style -dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.severity=warning - -# All public/protected/protected_internal static readonly fields must be PascalCase -# https://docs.microsoft.com/dotnet/standard/design-guidelines/field -dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_accessibilities=public, protected, protected_internal -dotnet_naming_symbols.public_protected_static_readonly_fields_group.required_modifiers=static, readonly -dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_kinds=field -dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.symbols=public_protected_static_readonly_fields_group -dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.style=pascal_case_style -dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.severity=warning - -# No other public/protected/protected_internal fields are allowed -# https://docs.microsoft.com/dotnet/standard/design-guidelines/field -dotnet_naming_symbols.other_public_protected_fields_group.applicable_accessibilities=public, protected, protected_internal -dotnet_naming_symbols.other_public_protected_fields_group.applicable_kinds=field -dotnet_naming_rule.other_public_protected_fields_disallowed_rule.symbols=other_public_protected_fields_group -dotnet_naming_rule.other_public_protected_fields_disallowed_rule.style=disallowed_style -dotnet_naming_rule.other_public_protected_fields_disallowed_rule.severity=error - -########################################## -# StyleCop Field Naming Rules -# Naming rules for fields follow the StyleCop analyzers -# This does not override any rules using disallowed_style above -# https://github.com/DotNetAnalyzers/StyleCopAnalyzers -########################################## - -# All constant fields must be PascalCase -# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1303.md -dotnet_naming_symbols.stylecop_constant_fields_group.applicable_accessibilities=public, internal, protected_internal, protected, private_protected, private -dotnet_naming_symbols.stylecop_constant_fields_group.required_modifiers=const -dotnet_naming_symbols.stylecop_constant_fields_group.applicable_kinds=field -dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.symbols=stylecop_constant_fields_group -dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.style=pascal_case_style -dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.severity=warning - -# All static readonly fields must be PascalCase -# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md -dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_accessibilities=public, internal, protected_internal, protected, private_protected, private -dotnet_naming_symbols.stylecop_static_readonly_fields_group.required_modifiers=static, readonly -dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_kinds=field -dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.symbols=stylecop_static_readonly_fields_group -dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.style=pascal_case_style -dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.severity=warning - -# No non-private instance fields are allowed -# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1401.md -dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_accessibilities=public, internal, protected_internal, protected, private_protected -dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_kinds=field -dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.symbols=stylecop_fields_must_be_private_group -dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.style=disallowed_style -dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.severity=error - -# Private fields must be camelCase -# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1306.md -dotnet_naming_symbols.stylecop_private_fields_group.applicable_accessibilities=private -dotnet_naming_symbols.stylecop_private_fields_group.applicable_kinds=field -dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.symbols=stylecop_private_fields_group -dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.style=camel_case_style -dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.severity=warning - -# Local variables must be camelCase -# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md -dotnet_naming_symbols.stylecop_local_fields_group.applicable_accessibilities=local -dotnet_naming_symbols.stylecop_local_fields_group.applicable_kinds=local -dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.symbols=stylecop_local_fields_group -dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.style=camel_case_style -dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.severity=warning - -# This rule should never fire. However, it's included for at least two purposes: -# First, it helps to understand, reason about, and root-case certain types of issues, such as bugs in .editorconfig parsers. -# Second, it helps to raise immediate awareness if a new field type is added (as occurred recently in C#). -dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_accessibilities=* -dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_kinds=field -dotnet_naming_rule.sanity_check_uncovered_field_case_rule.symbols=sanity_check_uncovered_field_case_group -dotnet_naming_rule.sanity_check_uncovered_field_case_rule.style=internal_error_style -dotnet_naming_rule.sanity_check_uncovered_field_case_rule.severity=error - - -########################################## -# Other Naming Rules -########################################## - -# All of the following must be PascalCase: -# - Namespaces -# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-namespaces -# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md -# - Classes and Enumerations -# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces -# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md -# - Delegates -# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces#names-of-common-types -# - Constructors, Properties, Events, Methods -# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-type-members -dotnet_naming_symbols.element_group.applicable_kinds=namespace, class, enum, struct, delegate, event, method, property -dotnet_naming_rule.element_rule.symbols=element_group -dotnet_naming_rule.element_rule.style=pascal_case_style -dotnet_naming_rule.element_rule.severity=warning - -# Interfaces use PascalCase and are prefixed with uppercase 'I' -# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces -dotnet_naming_symbols.interface_group.applicable_kinds=interface -dotnet_naming_rule.interface_rule.symbols=interface_group -dotnet_naming_rule.interface_rule.style=prefix_interface_with_i_style -dotnet_naming_rule.interface_rule.severity=warning - -# Generics Type Parameters use PascalCase and are prefixed with uppercase 'T' -# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces -dotnet_naming_symbols.type_parameter_group.applicable_kinds=type_parameter -dotnet_naming_rule.type_parameter_rule.symbols=type_parameter_group -dotnet_naming_rule.type_parameter_rule.style=prefix_type_parameters_with_t_style -dotnet_naming_rule.type_parameter_rule.severity=warning - -# Function parameters use camelCase -# https://docs.microsoft.com/dotnet/standard/design-guidelines/naming-parameters -dotnet_naming_symbols.parameters_group.applicable_kinds=parameter -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_new_line_between_query_expression_clauses=true -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 +# JetBrains Rider custom properties for code inspections +resharper_possible_null_reference_exception_highlighting=error +resharper_replace_with_string_is_null_or_empty_highlighting=none # ReSharper properties +resharper_accessor_owner_body=expression_body +resharper_align_linq_query=true resharper_align_multiline_argument=true resharper_align_multiline_calls_chain=true -resharper_braces_redundant=true +resharper_align_multiline_expression=true +resharper_align_multiline_extends_list=true +resharper_align_multiline_for_stmt=true +resharper_align_multiline_parameter=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_allow_comment_after_lbrace=true +resharper_apply_auto_detected_rules=false +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_csharp_blank_lines_around_region=2 +resharper_csharp_blank_lines_inside_region=2 +resharper_csharp_empty_block_style=together_same_line +resharper_csharp_int_align_comments=true +resharper_csharp_keep_blank_lines_in_code=1 +resharper_csharp_keep_blank_lines_in_declarations=1 +resharper_csharp_outdent_commas=true resharper_csharp_outdent_dots=true resharper_csharp_wrap_after_declaration_lpar=true +resharper_csharp_wrap_after_invocation_lpar=true +resharper_csharp_wrap_arguments_style=chop_if_long +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_fixed_stmt=true +resharper_indent_nested_foreach_stmt=true +resharper_indent_nested_for_stmt=true +resharper_indent_nested_lock_stmt=true +resharper_indent_nested_usings_stmt=true +resharper_indent_nested_while_stmt=true +resharper_keep_existing_embedded_arrangement=false +resharper_keep_existing_switch_expression_arrangement=false resharper_local_function_body=expression_body +resharper_max_array_initializer_elements_on_line=6 +resharper_max_enum_members_on_line=4 +resharper_max_formal_parameters_on_line=4 +resharper_max_initializer_elements_on_line=6 +resharper_max_invocation_arguments_on_line=6 +resharper_place_simple_embedded_statement_on_same_line=false resharper_space_within_catch_parentheses=false resharper_space_within_checked_parentheses=false resharper_space_within_foreach_parentheses=false @@ -391,40 +84,53 @@ resharper_space_within_parentheses=false resharper_space_within_switch_parentheses=false resharper_space_within_using_parentheses=false resharper_space_within_while_parentheses=false -resharper_wrap_before_linq_expression=true -resharper_wrap_linq_expressions=chop_always +resharper_wrap_array_initializer_style=chop_if_long +resharper_wrap_before_linq_expression=false +resharper_wrap_chained_method_calls=chop_if_long +resharper_wrap_enum_declaration=chop_if_long +resharper_wrap_linq_expressions=chop_if_long +resharper_xmldoc_wrap_lines=false -########################################## -# License -########################################## -# The following applies as to the .editorconfig file ONLY, and is -# included below for reference, per the requirements of the license -# corresponding to this .editorconfig file. -# See: https://github.com/RehanSaeed/EditorConfig -# -# MIT License -# -# Copyright (c) 2017-2019 Muhammad Rehan Saeed -# Copyright (c) 2019 Henry Gabryjelski -# -# Permission is hereby granted, free of charge, to any -# person obtaining a copy of this software and associated -# documentation files (the "Software"), to deal in the -# Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, -# sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject -# to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. -########################################## +# Microsoft .NET properties +csharp_new_line_before_members_in_object_initializers=true +csharp_new_line_between_query_expression_clauses=true +csharp_preferred_modifier_order=public, private, protected, internal, new, abstract, virtual, sealed, override, static, readonly, extern, unsafe, volatile, async:suggestion +csharp_style_expression_bodied_accessors=true:suggestion +csharp_style_expression_bodied_constructors=true:none +csharp_style_expression_bodied_methods=true:none +csharp_style_expression_bodied_properties=true:suggestion +csharp_style_var_elsewhere=true:suggestion +csharp_style_var_when_type_is_apparent=true:suggestion +dotnet_diagnostic.sa1101.severity=none +dotnet_diagnostic.sa1124.severity=suggestion +dotnet_diagnostic.sa1128.severity=none +dotnet_diagnostic.sa1200.severity=none +dotnet_diagnostic.sa1201.severity=none +dotnet_diagnostic.sa1202.severity=none +dotnet_diagnostic.sa1203.severity=none +dotnet_diagnostic.sa1204.severity=none +dotnet_diagnostic.sa1401.severity=none +dotnet_diagnostic.sa1502.severity=none +dotnet_diagnostic.sa1503.severity=none +dotnet_diagnostic.sa1519.severity=none +dotnet_diagnostic.sa1600.severity=none +dotnet_diagnostic.sa1602.severity=none +dotnet_diagnostic.sa1610.severity=none +dotnet_diagnostic.sa1616.severity=none +dotnet_diagnostic.sa1633.severity=none +dotnet_diagnostic.sa1648.severity=none +dotnet_style_parentheses_in_arithmetic_binary_operators=never_if_unnecessary:none +dotnet_style_parentheses_in_other_binary_operators=never_if_unnecessary:none +dotnet_style_parentheses_in_relational_binary_operators=never_if_unnecessary:none +dotnet_style_predefined_type_for_locals_parameters_members=true:suggestion +dotnet_style_predefined_type_for_member_access=true:suggestion +dotnet_style_qualification_for_event=true:suggestion +dotnet_style_qualification_for_field=true:suggestion +dotnet_style_qualification_for_method=true:suggestion +dotnet_style_qualification_for_property=true:suggestion +dotnet_style_require_accessibility_modifiers=for_non_interface_members:suggestion + +[*.{appxmanifest,asax,ascx,aspx,build,cg,cginc,compute,cs,cshtml,dtd,fs,fsi,fsscript,fsx,hlsl,hlsli,hlslinc,master,ml,mli,nuspec,razor,resw,resx,shader,skin,usf,ush,vb,xaml,xamlx,xoml,xsd}] +indent_style=space +indent_size=4 +tab_width=4 diff --git a/src/Collections/Interval.cs b/src/Collections/Interval.cs index 4a7c82e..5a73b27 100644 --- a/src/Collections/Interval.cs +++ b/src/Collections/Interval.cs @@ -22,6 +22,7 @@ public Interval(double start, double end) this.End = end; } + /// /// Initializes a new instance of the struct from another interval. /// @@ -30,6 +31,7 @@ public Interval(double start, double end) public Interval(Interval interval) : this(interval.Start, interval.End) { } + /// /// Gets a new unit interval. /// @@ -40,21 +42,13 @@ public Interval(Interval interval) /// Gets or sets the starting value of the interval. /// /// Value will always be lower unless interval is inverted. - public double Start - { - get; - set; - } + public double Start { get; set; } /// /// Gets or sets the ending value of the interval. /// /// Value will always be the biggest unless interval is inverted. - public double End - { - get; - set; - } + public double End { get; set; } /// /// Gets the space between the start and end of the interval. @@ -66,6 +60,7 @@ public double End /// public bool HasInvertedDirection => this.Length < 0; + /// /// Crop a number so that it's contained on the given interval. /// @@ -81,6 +76,7 @@ public static double CropNumber(double number, Interval interval) return number; } + /// /// Remap a number from one interval to another. /// @@ -93,9 +89,10 @@ public static double RemapNumber(double number, Interval fromInterval, Interval var cropped = fromInterval.Contains(number) ? number : fromInterval.Crop(number); var proportion = (cropped - fromInterval.Start) / Math.Abs(fromInterval.Length); - return toInterval.Start + (toInterval.Length * proportion); + return toInterval.Start + toInterval.Length * proportion; } + /// /// Crop a number so that it is contained inside this interval. /// @@ -103,13 +100,16 @@ public static double RemapNumber(double number, Interval fromInterval, Interval /// Cropped number. public double Crop(double number) => CropNumber(number, this); + /// /// Remap a number from this interval to a given one. /// /// Number to remap. /// Interval to remap number to. /// Remapped number inside given interval. - public double Remap(double number, Interval toInterval) => RemapNumber(number, this, toInterval); + public double Remap(double number, Interval toInterval) => + RemapNumber(number, this, toInterval); + /// /// Remap a number from this interval to a unit interval. @@ -118,6 +118,7 @@ public static double RemapNumber(double number, Interval fromInterval, Interval /// Value remaped from 0 to 1. public double RemapToUnit(double number) => this.Remap(number, Unit); + /// /// Remap a number from a unit interval to this interval. /// @@ -125,6 +126,7 @@ public static double RemapNumber(double number, Interval fromInterval, Interval /// Remapped number. public double RemapFromUnit(double number) => Unit.Remap(number, this); + /// /// Check if a number is contained inside this interval. /// @@ -137,6 +139,7 @@ public bool Contains(double number) return min <= number && number <= max; } + /// /// Swap the Start and End values of this interval. /// diff --git a/src/Collections/Matrix{T}.cs b/src/Collections/Matrix{T}.cs index 3d489c8..69d61a5 100644 --- a/src/Collections/Matrix{T}.cs +++ b/src/Collections/Matrix{T}.cs @@ -14,12 +14,14 @@ public class Matrix // https://codereview.stackexchange.com/questions/194732/class-matrix-implementation private T[,] data; + /// /// Initializes a new instance of the class. /// /// Size of the square Matrix. public Matrix(int n) => this.data = new T[n, n]; + /// /// Initializes a new instance of the class of the specified size. /// @@ -27,12 +29,14 @@ public class Matrix /// Row size. public Matrix(int n, int m) => this.data = new T[n, m]; + /// /// Initializes a new instance of the class from a 2D array. /// /// 2D array of data. public Matrix(T[,] data) => this.data = data; + /// /// Gets columns. /// @@ -52,6 +56,7 @@ public class Matrix /// Column. public ref T this[int row, int column] => ref this.data[row, column]; + /// /// Get the row of a matrix at the specified index. /// @@ -66,6 +71,7 @@ public T[] Row(int n) return row; } + /// /// Get the column of a matrix at the specified index. /// @@ -80,34 +86,47 @@ public T[] Column(int m) return col; } + // ----- ORDERING METHODS ----- + /// /// Turns columns into rows and rows into columns. /// public void FlipMatrix() => throw - // TODO: Implement FlipMatrix() - new NotImplementedException(); + // TODO: Implement FlipMatrix() + new NotImplementedException(); + /// /// Increment Matrix column size by a specified amount. /// It accepts both increasing and decreasing the size. /// /// Positive or negative increment. - public void IncrementColumns(int incrementN) => this.ResizeMatrix(ref this.data, this.N + incrementN, this.M); + public void IncrementColumns(int incrementN) => this.ResizeMatrix( + ref this.data, + this.N + incrementN, + this.M); + /// /// Increment Matrix row size by a specified amount. /// It accepts both increasing and decreasing the size. /// /// Positive or negative increment. - public void IncrementRows(int incrementM) => this.ResizeMatrix(ref this.data, this.N, this.M + incrementM); + public void IncrementRows(int incrementM) => this.ResizeMatrix( + ref this.data, + this.N, + this.M + incrementM); + /// /// Increase or decrease the matrix size symetrically. /// /// Symetric increase/decrease. - public void IncrementMatrixSize(int symetricIncrement) => this.IncrementMatrixSize(symetricIncrement, symetricIncrement); + public void IncrementMatrixSize(int symetricIncrement) => + this.IncrementMatrixSize(symetricIncrement, symetricIncrement); + /// /// Increase or decrease the column size of the matrix. @@ -120,6 +139,7 @@ public void IncrementMatrixSize(int columnIncrement, int rowIncrement) this.IncrementRows(rowIncrement); } + /// /// Obtains all neighbour entities surrounding the specified matrix coordinates. /// @@ -135,6 +155,7 @@ public List GetAllNeighboursAt(int column, int row) return neighbours; } + /// /// Obtains corner neighbour entities surrounding the specified matrix coordinates. /// @@ -145,6 +166,7 @@ public List GetAllNeighboursAt(int column, int row) // TODO: Implement GetCornerNeighboursOfEntityAt() new NotImplementedException(); + /// /// Obtains contiguous neighbour entities surrounding the specified matrix coordinates. /// @@ -155,10 +177,12 @@ public List GetAllNeighboursAt(int column, int row) // TODO: Implement GetContiguousNeighboursOfEntityAt() new NotImplementedException(); + /// /// Resizes any given 2 dimensional array. /// It accepts smaller and bigger array outputs. - /// Obtained from: https://stackoverflow.com/questions/6539571/how-to-resize-multidimensional-2d-array-in-c . + /// Obtained from: + /// https://stackoverflow.com/questions/6539571/how-to-resize-multidimensional-2d-array-in-c . /// /// 2D Array to resize. /// Number of resulting columns in the array. diff --git a/src/Curves/Geodesics.cs b/src/Curves/Geodesics.cs index 4923f4a..4205bc2 100644 --- a/src/Curves/Geodesics.cs +++ b/src/Curves/Geodesics.cs @@ -19,7 +19,12 @@ public static class Geodesics /// Maximum iterations. /// Geodesic curves. /// True if successful. - public static bool StartDir(MeshPoint meshPoint, Vector3d vector, Mesh mesh, int maxIter, out List geodesic) + public static bool StartDir( + MeshPoint meshPoint, + Vector3d vector, + Mesh mesh, + int maxIter, + out List geodesic) { // Get initial face on the mesh var initialFace = mesh.Faces[meshPoint.FaceIndex]; @@ -48,8 +53,12 @@ public static bool StartDir(MeshPoint meshPoint, Vector3d vector, Mesh mesh, int var nextFace = halfEdge.Twin.Face; // Flip vector to next face - var perpVector = Vector3d.CrossProduct(thisDirection, MeshGeometry.FaceNormal(thisFace)); - var nextVector = Vector3d.CrossProduct(MeshGeometry.FaceNormal(nextFace), perpVector); + var perpVector = Vector3d.CrossProduct( + thisDirection, + MeshGeometry.FaceNormal(thisFace)); + var nextVector = Vector3d.CrossProduct( + MeshGeometry.FaceNormal(nextFace), + perpVector); // Assign iteration variables to current thisPoint = nextPoint; diff --git a/src/Curves/LevelSets.cs b/src/Curves/LevelSets.cs index 0b7b2a1..1f1c2f4 100644 --- a/src/Curves/LevelSets.cs +++ b/src/Curves/LevelSets.cs @@ -16,14 +16,17 @@ public static class LevelSets /// List of level values to be computed. /// The mesh to compute the level-sets in. /// Resulting level sets. - public static void ComputeLevels(string valueKey, List levels, Mesh mesh, out List> levelSets) + public static void ComputeLevels( + string valueKey, + List levels, + Mesh mesh, + out List> levelSets) { var resultLines = new List>(); for (var i = 0; i < levels.Count; i++) resultLines.Add(new List()); - var iter = 0; foreach (var face in mesh.Faces) { var count = 0; @@ -34,13 +37,12 @@ public static void ComputeLevels(string valueKey, List levels, Mesh mesh count++; } - - iter++; } levelSets = resultLines; } + /// /// Compute the level on a specified face. /// @@ -52,16 +54,23 @@ public static void ComputeLevels(string valueKey, List levels, Mesh mesh public static bool GetFaceLevel(string valueKey, double level, MeshFace face, out Line line) { var adj = face.AdjacentVertices(); - var vertexValues = new List {adj[0].UserValues[valueKey], adj[1].UserValues[valueKey], adj[2].UserValues[valueKey]}; + var vertexValues = new List + { + adj[0].UserValues[valueKey], + adj[1].UserValues[valueKey], + adj[2].UserValues[valueKey] + }; var above = new List(); var below = new List(); for (var i = 0; i < vertexValues.Count; i++) + { if (vertexValues[i] < level) below.Add(i); else above.Add(i); + } if (above.Count == 3 || below.Count == 3) { @@ -74,20 +83,23 @@ public static bool GetFaceLevel(string valueKey, double level, MeshFace face, ou var intersectionPoints = new List(); foreach (var i in above) - foreach (var j in below) { - var diff = vertexValues[i] - vertexValues[j]; - var desiredDiff = level - vertexValues[j]; - var unitizedDistance = desiredDiff / diff; - var edgeV = adj[i] - adj[j]; - var levelPoint = adj[j] + (edgeV * unitizedDistance); - intersectionPoints.Add(levelPoint); + foreach (var j in below) + { + var diff = vertexValues[i] - vertexValues[j]; + var desiredDiff = level - vertexValues[j]; + var unitizedDistance = desiredDiff / diff; + var edgeV = adj[i] - adj[j]; + var levelPoint = adj[j] + edgeV * unitizedDistance; + intersectionPoints.Add(levelPoint); + } } line = new Line(intersectionPoints[0], intersectionPoints[1]); return true; } + /// /// Compute the gradient on a given mesh given some per-vertex values. /// @@ -103,6 +115,7 @@ public static List ComputeGradientField(string valueKey, Mesh mesh) return gradientField; } + /// /// Compute the gradient on a given mesh face given some per-vertex values. /// @@ -121,7 +134,7 @@ public static Vector3d ComputeFaceGradient(string valueKey, MeshFace face) var gk = adjacentVertices[2].UserValues[valueKey]; var faceNormal = face.Normal / (2 * face.Area); - var rotatedGradient = ((gi * (k - j)) + (gj * (i - k)) + (gk * (j - i))) / (2 * face.Area); + var rotatedGradient = (gi * (k - j) + gj * (i - k) + gk * (j - i)) / (2 * face.Area); var gradient = rotatedGradient.Cross(faceNormal); return gradient; diff --git a/src/Exceptions/UnsetGeometryException.cs b/src/Exceptions/UnsetGeometryException.cs index 52b5ddb..3726a77 100644 --- a/src/Exceptions/UnsetGeometryException.cs +++ b/src/Exceptions/UnsetGeometryException.cs @@ -10,10 +10,14 @@ public class UnsetGeometryException : Exception /// public UnsetGeometryException() { } + /// public UnsetGeometryException(string message) : base(message) { } + /// - public UnsetGeometryException(string message, Exception innerException) : base(message, innerException) { } + public UnsetGeometryException(string message, Exception innerException) : base( + message, + innerException) { } } } \ No newline at end of file diff --git a/src/Extensions/Lists.cs b/src/Extensions/Lists.cs index 262f83b..fba4b2f 100644 --- a/src/Extensions/Lists.cs +++ b/src/Extensions/Lists.cs @@ -16,6 +16,7 @@ public static class Lists /// //TODO. public static List RepeatedDefault(int count) => Repeated(default(T), count); + /// /// Initializes a new list full of objects initialized the values of the specified instance of T. /// diff --git a/src/Geometry/2D/BoundingBox2d.cs b/src/Geometry/2D/BoundingBox2d.cs index b563386..8b09639 100644 --- a/src/Geometry/2D/BoundingBox2d.cs +++ b/src/Geometry/2D/BoundingBox2d.cs @@ -22,6 +22,7 @@ public BoundingBox2d(Point2d bottomLeftCorner, Point2d topRightCorner) this.YDomain.FlipDirection(); } + /// /// Initializes a new instance of the class from a polyline. /// @@ -33,42 +34,36 @@ public BoundingBox2d(Polyline2d polyline) var xMax = polyline.Vertices[0].X; var yMax = polyline.Vertices[0].Y; - polyline.Vertices.ForEach(vertex => - { - if (vertex.X < xMin) - xMin = vertex.X; - if (vertex.X > xMax) - xMax = vertex.X; + polyline.Vertices.ForEach( + vertex => + { + if (vertex.X < xMin) + xMin = vertex.X; + if (vertex.X > xMax) + xMax = vertex.X; - if (vertex.Y < yMin) - yMin = vertex.Y; - if (vertex.X > yMax) - yMax = vertex.Y; - }); + if (vertex.Y < yMin) + yMin = vertex.Y; + if (vertex.X > yMax) + yMax = vertex.Y; + }); this.XDomain = new Interval(xMin, xMax); this.YDomain = new Interval(yMin, yMax); } + /// /// Gets or sets the Domain in the X direction. /// /// - public Interval XDomain - { - get; - set; - } + public Interval XDomain { get; set; } /// /// Gets or sets the Domain in the Y direction. /// /// - public Interval YDomain - { - get; - set; - } + public Interval YDomain { get; set; } /// /// Gets the Bottom left corner of the BBox. @@ -94,28 +89,59 @@ public Interval YDomain /// public Point2d TopRight => new Point2d(this.XDomain.End, this.YDomain.End); + /// + /// Gets the midpoint at the left edge of the box. + /// public Point2d MidLeft => new Point2d(this.XDomain.Start, this.YDomain.RemapFromUnit(0.5)); + /// + /// Gets the midpoint at the right edge of the box. + /// public Point2d MidRight => new Point2d(this.XDomain.End, this.YDomain.RemapFromUnit(0.5)); - public Point2d MidBottom => new Point2d(this.XDomain.RemapFromUnit(0.5), this.YDomain.Start); + /// + /// Gets the midpoint at the bottom edge of the box. + /// + public Point2d MidBottom => + new Point2d(this.XDomain.RemapFromUnit(0.5), this.YDomain.Start); + /// + /// Gets the midpoint at the top edge of the box. + /// public Point2d MidTop => new Point2d(this.XDomain.RemapFromUnit(0.5), this.YDomain.End); /// /// Gets the center of the bounding BBox. /// - public Point2d Center => new Point2d(this.XDomain.RemapFromUnit(0.5), this.YDomain.RemapFromUnit(0.5)); + public Point2d Center => + new Point2d(this.XDomain.RemapFromUnit(0.5), this.YDomain.RemapFromUnit(0.5)); - public bool ContainsPoint(Point2d pt) => this.XDomain.Contains(pt.X) && this.YDomain.Contains(pt.Y); + + /// + /// Checks if a point is contained inside the box. + /// + /// Point to test containment. + /// True if point is contained inside the bounding box. + public bool ContainsPoint(Point2d pt) => + this.XDomain.Contains(pt.X) && this.YDomain.Contains(pt.Y); + /// + /// Checks if a box intersects with this instance. + /// + /// Box to check intersection against. + /// True if intersection exists. public bool IntersectsBox(BoundingBox2d box) { - var xCheck = this.XDomain.Contains(box.XDomain.Start) || this.XDomain.Contains(box.XDomain.End); - var yCheck = this.YDomain.Contains(box.YDomain.Start) || this.YDomain.Contains(box.YDomain.End); + var xCheck = this.XDomain.Contains(box.XDomain.Start) + || this.XDomain.Contains(box.XDomain.End); + var yCheck = this.YDomain.Contains(box.YDomain.Start) + || this.YDomain.Contains(box.YDomain.End); return xCheck && yCheck; } - public override string ToString() => $"BBox2d [{this.XDomain.Start};{this.YDomain.Start}]-[{this.XDomain.End};{this.YDomain.End}]"; + + /// + public override string ToString() => + $"BBox2d [{this.XDomain.Start};{this.YDomain.Start}]-[{this.XDomain.End};{this.YDomain.End}]"; } } \ No newline at end of file diff --git a/src/Geometry/2D/Delaunay.cs b/src/Geometry/2D/Delaunay.cs index ace8670..a49a264 100644 --- a/src/Geometry/2D/Delaunay.cs +++ b/src/Geometry/2D/Delaunay.cs @@ -4,17 +4,19 @@ namespace Paramdigma.Core.Geometry { /// - /// Class holding all the delaunay and Voronoi classes in 2 dimensions. + /// Class holding all the delaunay and Voronoi classes in 2 dimensions. /// public static class Delaunay { /// - /// Compute the delaunay triangulation of a given list of points. + /// Compute the delaunay triangulation of a given list of points. /// /// Points to find delaunay tessellation. /// Border to start from. - /// List of . - public static IEnumerable Compute(IEnumerable points, IEnumerable border) + /// List of . + public static IEnumerable Compute( + IEnumerable points, + IEnumerable border) { var triangulation = new List(border); foreach (var point in points) @@ -24,37 +26,42 @@ public static IEnumerable Compute(IEnumerable p foreach (var triangle in badTriangles) { foreach (var vertex in triangle.Vertices) - { vertex.AdjacentTriangles.Remove(triangle); - } if (triangulation.Contains(triangle)) triangulation.Remove(triangle); } - triangulation.AddRange(polygon.Select(edge => new DelaunayTriangle(point, edge.StartPoint, edge.EndPoint))); + triangulation.AddRange( + polygon.Select( + edge => new DelaunayTriangle(point, edge.StartPoint, edge.EndPoint))); } return triangulation; } + /// - /// Computes the Voronoi diagram of a given Delaunay triangulation as a list of instances. + /// Computes the Voronoi diagram of a given Delaunay triangulation as a list of + /// instances. /// /// Delaunay triangulation. /// Collection of lines representing the Voronoi cells. public static IEnumerable Voronoi(IEnumerable triangulation) - => from triangle in triangulation - from neighbour in triangle.TrianglesWithSharedEdges() - select new Line2d(triangle.Circumcenter, neighbour.Circumcenter); + => + from triangle in triangulation + from neighbour in triangle.TrianglesWithSharedEdges() + select new Line2d(triangle.Circumcenter, neighbour.Circumcenter); + - private static IEnumerable FindHoleBoundaries(IEnumerable badTriangles) + private static IEnumerable FindHoleBoundaries( + IEnumerable badTriangles) { var boundaryEdges = new List(); var duplicateEdges = new List(); foreach (var triangle in badTriangles) { - for (int i = 0; i < triangle.Vertices.Count; i++) + for (var i = 0; i < triangle.Vertices.Count; i++) { var e = new DelaunayEdge( triangle.Vertices[i], @@ -66,7 +73,6 @@ private static IEnumerable FindHoleBoundaries(IEnumerable= 0; i--) { var e = boundaryEdges[i]; @@ -77,7 +83,10 @@ private static IEnumerable FindHoleBoundaries(IEnumerable FindBadTriangles(Point2d point, IEnumerable triangles) + + private static IEnumerable FindBadTriangles( + Point2d point, + IEnumerable triangles) => triangles.Where(triangle => triangle.IsPointInsideCircumcircle(point)); } } \ No newline at end of file diff --git a/src/Geometry/2D/DelaunayEdge.cs b/src/Geometry/2D/DelaunayEdge.cs index 5dc5938..ee5c493 100644 --- a/src/Geometry/2D/DelaunayEdge.cs +++ b/src/Geometry/2D/DelaunayEdge.cs @@ -1,45 +1,52 @@ namespace Paramdigma.Core.Geometry { /// - /// Represents a connection between two points in a Delaunay triangulation. + /// Represents a connection between two points in a Delaunay triangulation. /// public class DelaunayEdge { /// - /// The edge's start point. + /// The edge's end point. /// - public DelaunayPoint StartPoint; + public DelaunayPoint EndPoint; /// - /// The edge's end point. + /// The edge's start point. /// - public DelaunayPoint EndPoint; + public DelaunayPoint StartPoint; + /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Start point. /// End point. public DelaunayEdge(DelaunayPoint startPoint, DelaunayPoint endPoint) { - StartPoint = startPoint; - EndPoint = endPoint; + this.StartPoint = startPoint; + this.EndPoint = endPoint; } + /// public override bool Equals(object obj) { if (!(obj is DelaunayEdge edge)) return false; - var samePoints = StartPoint == edge.StartPoint && EndPoint == edge.EndPoint; - var samePointsReversed = StartPoint == edge.EndPoint && EndPoint == edge.StartPoint; + var samePoints = this.StartPoint == edge.StartPoint && this.EndPoint == edge.EndPoint; + var samePointsReversed = + this.StartPoint == edge.EndPoint && this.EndPoint == edge.StartPoint; return samePoints || samePointsReversed; } + /// public override int GetHashCode() { - int hCode = (int)StartPoint.X ^ (int)StartPoint.Y ^ (int)EndPoint.X ^ (int)EndPoint.Y; + var hCode = ( int ) this.StartPoint.X + ^ ( int ) this.StartPoint.Y + ^ ( int ) this.EndPoint.X + ^ ( int ) this.EndPoint.Y; return hCode.GetHashCode(); } } diff --git a/src/Geometry/2D/DelaunayPoint.cs b/src/Geometry/2D/DelaunayPoint.cs index f866399..f95b367 100644 --- a/src/Geometry/2D/DelaunayPoint.cs +++ b/src/Geometry/2D/DelaunayPoint.cs @@ -3,29 +3,30 @@ namespace Paramdigma.Core.Geometry { /// - /// Represents a point in a delaunay triangulation with adjacency information. + /// Represents a point in a delaunay triangulation with adjacency information. /// public class DelaunayPoint : Point2d { /// - /// List of adjacent triangles of this point. + /// List of adjacent triangles of this point. /// public List AdjacentTriangles; + /// - /// Initializes a new instance of the class from it's coordinates. + /// Initializes a new instance of the class from it's coordinates. /// /// X Coordinate. /// Y Coordinate. - public DelaunayPoint(double x, double y) : base(x, y) - { - AdjacentTriangles = new List(); - } + public DelaunayPoint(double x, double y) : base(x, y) => + this.AdjacentTriangles = new List(); + /// - /// Initializes a new instance of the class from a instance. + /// Initializes a new instance of the class from a + /// instance. /// - /// Point to create from. + /// Point to create from. public DelaunayPoint(Point2d point) : this(point.X, point.Y) { } } } \ No newline at end of file diff --git a/src/Geometry/2D/DelaunayTriangle.cs b/src/Geometry/2D/DelaunayTriangle.cs index 372b3a3..9c0d38d 100644 --- a/src/Geometry/2D/DelaunayTriangle.cs +++ b/src/Geometry/2D/DelaunayTriangle.cs @@ -5,25 +5,26 @@ namespace Paramdigma.Core.Geometry { /// - /// Represents a triangle in a delaunay triangulation operation. + /// Represents a triangle in a delaunay triangulation operation. /// public class DelaunayTriangle { /// - /// Circumcenter of this triangle. + /// Circumcenter of this triangle. /// public Point2d Circumcenter; /// - /// Squared radius of the triangle's circumcircle. + /// Squared radius of the triangle's circumcircle. /// public double RadiusSquared; /// - /// List of vertices of this triangle. + /// List of vertices of this triangle. /// public List Vertices; + /// /// Initializes a new instance of the class. /// @@ -52,6 +53,7 @@ public DelaunayTriangle(DelaunayPoint point1, DelaunayPoint point2, DelaunayPoin this.UpdateCircumcircle(); } + /// /// Returns a collection of neighbouring triangles. /// @@ -59,17 +61,19 @@ public DelaunayTriangle(DelaunayPoint point1, DelaunayPoint point2, DelaunayPoin public IEnumerable TrianglesWithSharedEdges() { var neighbours = new List(); - foreach (var sharedTriangle in from vertex in this.Vertices - from sharedTriangle in vertex.AdjacentTriangles - where this.SharesEdgeWidth(sharedTriangle) - && neighbours.Contains(sharedTriangle) == false - && sharedTriangle != this - select sharedTriangle) + foreach (var sharedTriangle in + from vertex in this.Vertices + from sharedTriangle in vertex.AdjacentTriangles + where this.SharesEdgeWidth(sharedTriangle) + && neighbours.Contains(sharedTriangle) == false + && sharedTriangle != this + select sharedTriangle) neighbours.Add(sharedTriangle); return neighbours; } + /// /// Checks if a point is inside this triangle's circumcircle. /// @@ -77,52 +81,56 @@ where this.SharesEdgeWidth(sharedTriangle) /// True if inside. public bool IsPointInsideCircumcircle(Point2d point) { - var dSquared = ((point.X - this.Circumcenter.X) * (point.X - this.Circumcenter.X)) - + ((point.Y - this.Circumcenter.Y) * (point.Y - this.Circumcenter.Y)); + var dSquared = (point.X - this.Circumcenter.X) * (point.X - this.Circumcenter.X) + + (point.Y - this.Circumcenter.Y) * (point.Y - this.Circumcenter.Y); return dSquared < this.RadiusSquared; } + private static bool IsCounterClockwise(Point2d point1, Point2d point2, Point2d point3) { - var result = ((point2.X - point1.X) * (point3.Y - point1.Y)) - - ((point3.X - point1.X) * (point2.Y - point1.Y)); + var result = (point2.X - point1.X) * (point3.Y - point1.Y) + - (point3.X - point1.X) * (point2.Y - point1.Y); return result > 0; } + private void UpdateCircumcircle() { var p0 = this.Vertices[0]; var p1 = this.Vertices[1]; var p2 = this.Vertices[2]; - var dA = (p0.X * p0.X) + (p0.Y * p0.Y); - var dB = (p1.X * p1.X) + (p1.Y * p1.Y); - var dC = (p2.X * p2.X) + (p2.Y * p2.Y); - - var aux1 = (dA * (p2.Y - p1.Y)) - + (dB * (p0.Y - p2.Y)) - + (dC * (p1.Y - p0.Y)); - var aux2 = -((dA * (p2.X - p1.X)) - + (dB * (p0.X - p2.X)) - + (dC * (p1.X - p0.X))); - var div = 2 * ((p0.X * (p2.Y - p1.Y)) - + (p1.X * (p0.Y - p2.Y)) - + (p2.X * (p1.Y - p0.Y))); + var dA = p0.X * p0.X + p0.Y * p0.Y; + var dB = p1.X * p1.X + p1.Y * p1.Y; + var dC = p2.X * p2.X + p2.Y * p2.Y; + + var aux1 = dA * (p2.Y - p1.Y) + + dB * (p0.Y - p2.Y) + + dC * (p1.Y - p0.Y); + var aux2 = -(dA * (p2.X - p1.X) + + dB * (p0.X - p2.X) + + dC * (p1.X - p0.X)); + var div = 2 * (p0.X * (p2.Y - p1.Y) + + p1.X * (p0.Y - p2.Y) + + p2.X * (p1.Y - p0.Y)); if (Math.Abs(div) < Settings.Tolerance) throw new Exception("Divisor too small"); var center = new DelaunayPoint(aux1 / div, aux2 / div); this.Circumcenter = center; - this.RadiusSquared = ((center.X - p0.X) * (center.X - p0.X)) - + ((center.Y - p0.Y) * (center.Y - p0.Y)); + this.RadiusSquared = (center.X - p0.X) * (center.X - p0.X) + + (center.Y - p0.Y) * (center.Y - p0.Y); } + private bool SharesEdgeWidth(DelaunayTriangle triangle) { - var shared = from pt1 in this.Vertices - from pt2 in triangle.Vertices - where pt1 == pt2 - select pt1; + var shared = + from pt1 in this.Vertices + from pt2 in triangle.Vertices + where pt1 == pt2 + select pt1; return shared.Count() == 2; } } diff --git a/src/Geometry/2D/Line2d.cs b/src/Geometry/2D/Line2d.cs index 3c92386..a31f523 100644 --- a/src/Geometry/2D/Line2d.cs +++ b/src/Geometry/2D/Line2d.cs @@ -19,6 +19,7 @@ public Line2d(Point2d startPoint, Point2d endPoint) this.Domain = new Interval(0, this.Length); } + /// /// Initializes a new instance of the class. /// @@ -28,6 +29,7 @@ public Line2d(Point2d startPoint, Point2d endPoint) public Line2d(Point2d startPoint, Vector2d direction) : this(startPoint, startPoint + direction) { } + /// /// Initializes a new instance of the class. /// @@ -38,52 +40,44 @@ public Line2d(Point2d startPoint, Vector2d direction) public Line2d(Point2d startPoint, Vector2d direction, double length) : this(startPoint, direction.Unit() * length) { } + /// /// Gets or sets the start point of the line. /// /// 3D Point. - public Point2d StartPoint - { - get; - set; - } + public Point2d StartPoint { get; set; } /// /// Gets or sets the end point of the line. /// /// 3D Point. - public Point2d EndPoint - { - get; - set; - } + public Point2d EndPoint { get; set; } /// /// Gets or sets the line's domain. /// /// Interval. - public Interval Domain - { - get; - set; - } + public Interval Domain { get; set; } /// /// Gets the vector representation of the line. /// - public Vector2d Vector => this; // Implicit line to vector conversion (this property exists just for convenience and readability) + public Vector2d Vector => + this; // Implicit line to vector conversion (this property exists just for convenience and readability) /// /// Gets the length of the line. /// public double Length => this.Vector.Length; + /// /// Implicit conversion from line to vector. /// /// Line to be transformed into vector. public static implicit operator Vector2d(Line2d line) => line.EndPoint - line.StartPoint; + /// /// Computes if a given point is at the left, right or on the current line. /// diff --git a/src/Geometry/2D/Point2d.cs b/src/Geometry/2D/Point2d.cs index 7c37e8a..212fb22 100644 --- a/src/Geometry/2D/Point2d.cs +++ b/src/Geometry/2D/Point2d.cs @@ -13,6 +13,7 @@ public class Point2d public Point2d() : this(0, 0) { } + /// /// Initializes a new instance of the class from x and y coordinates. /// @@ -24,6 +25,7 @@ public Point2d(double x, double y) this.Y = y; } + /// /// Initializes a new instance of the class from an existing point. /// @@ -31,23 +33,16 @@ public Point2d(double x, double y) public Point2d(Point2d pt) : this(pt.X, pt.Y) { } + /// /// Gets or sets the X coordinate of the point. /// - public double X - { - get; - set; - } + public double X { get; set; } /// /// Gets or sets the Y coordinate of the point. /// - public double Y - { - get; - set; - } + public double Y { get; set; } /// /// Gets a new 2d point with all coordinates =0. @@ -57,12 +52,14 @@ public double Y // Overrided methods + /// /// String representation of a 2-dimensional point instance. /// /// Returns string representation of this Point2d instance. public override string ToString() => "Point2d{ " + this.X + "; " + this.Y + "}"; + /// /// Compares a Point2d instance to the given objects. /// @@ -72,11 +69,12 @@ public override bool Equals(object obj) { if (!(obj is Point2d)) return false; - var pt = (Point2d)obj; + var pt = ( Point2d ) obj; return Math.Abs(this.X - pt.X) <= Settings.Tolerance && Math.Abs(this.Y - pt.Y) <= Settings.Tolerance; } + /// /// Gets the hash code for the corresponding Point2d instance. /// @@ -86,11 +84,11 @@ public override int GetHashCode() unchecked { // Choose large primes to avoid hashing collisions - const int hashingBase = (int)2166136261; + const int hashingBase = ( int ) 2166136261; const int hashingMultiplier = 16777619; var tol = Settings.Tolerance * 2; - var tX = (int)(this.X * (1 / tol)) * tol; - var tY = (int)(this.Y * (1 / tol)) * tol; + var tX = ( int ) (this.X * (1 / tol)) * tol; + var tY = ( int ) (this.Y * (1 / tol)) * tol; var hash = hashingBase; hash = (hash * hashingMultiplier) ^ tX.GetHashCode(); @@ -99,13 +97,16 @@ public override int GetHashCode() } } + /// /// Add two points together. /// /// First point. /// Second point. /// Addition result. - public static Vector2d operator +(Point2d point, Point2d point2) => new Vector2d(point.X + point2.X, point.Y + point2.Y); + public static Vector2d operator +(Point2d point, Point2d point2) => + new Vector2d(point.X + point2.X, point.Y + point2.Y); + /// /// Substracts one point from another. @@ -113,7 +114,9 @@ public override int GetHashCode() /// First point. /// Second point. /// Substraction result. - public static Vector2d operator -(Point2d point, Point2d point2) => new Vector2d(point.X - point2.X, point.Y - point2.Y); + public static Vector2d operator -(Point2d point, Point2d point2) => + new Vector2d(point.X - point2.X, point.Y - point2.Y); + /// /// Negates a given point. @@ -122,13 +125,16 @@ public override int GetHashCode() /// Negation result. public static Point2d operator -(Point2d point) => new Point2d(-point.X, -point.Y); + /// /// Multiplies a point by a number. /// /// Point to multiply. /// Operand. /// Multiplication result. - public static Point2d operator *(Point2d point, double scalar) => new Point2d(point.X * scalar, point.Y * scalar); + public static Point2d operator *(Point2d point, double scalar) => + new Point2d(point.X * scalar, point.Y * scalar); + /// /// Multiplies a point by a number. @@ -136,7 +142,9 @@ public override int GetHashCode() /// Operand. /// Point to multiply. /// Multiplication result. - public static Point2d operator *(double scalar, Point2d point) => new Point2d(point.X * scalar, point.Y * scalar); + public static Point2d operator *(double scalar, Point2d point) => + new Point2d(point.X * scalar, point.Y * scalar); + /// /// Divides a point by a number. @@ -144,7 +152,9 @@ public override int GetHashCode() /// Point. /// Operand. /// Division result. - public static Point2d operator /(Point2d point, double scalar) => new Point2d(point.X / scalar, point.Y / scalar); + public static Point2d operator /(Point2d point, double scalar) => + new Point2d(point.X / scalar, point.Y / scalar); + /// /// Equality comparison between points. @@ -154,6 +164,7 @@ public override int GetHashCode() /// True if equal. public static bool operator ==(Point2d point, Point2d point2) => point.Equals(point2); + /// /// Inequality comparison between points. /// @@ -162,22 +173,27 @@ public override int GetHashCode() /// True if NOT equal. public static bool operator !=(Point2d point, Point2d point2) => !point.Equals(point2); + /// /// Divides a point by a number. /// /// Point. /// Vector. /// Division result. - public static Point2d operator +(Point2d point, Vector2d v) => new Point2d(point.X + v.X, point.Y + v.Y); + public static Point2d operator +(Point2d point, Vector2d v) => + new Point2d(point.X + v.X, point.Y + v.Y); + // Implicit conversions + /// /// Explicit conversion from 2-dimensional point to vector. /// /// Vector to convert. public static explicit operator Point2d(Vector2d v) => new Point2d(v.X, v.Y); + /// /// Implicit conversion from 2-dimensional point to vector. /// diff --git a/src/Geometry/2D/Polyline2d.cs b/src/Geometry/2D/Polyline2d.cs index c031ceb..2842b5a 100644 --- a/src/Geometry/2D/Polyline2d.cs +++ b/src/Geometry/2D/Polyline2d.cs @@ -15,6 +15,7 @@ public class Polyline2d private bool segmentsNeedUpdate; private List vertices; + /// /// Initializes a new instance of the class. /// @@ -23,10 +24,12 @@ public class Polyline2d public Polyline2d(List vertices, bool closed) { this.vertices = vertices; - this.IsClosed = closed; // Call the property (not the field), to have if add the first point at the end if necessary. + this.IsClosed = + closed; // Call the property (not the field), to have if add the first point at the end if necessary. this.RebuildSegments(); } + /// /// Gets or sets the polyline vertices. /// @@ -103,6 +106,7 @@ public bool IsClosed } } + /// /// Computes the area of the polyline. /// @@ -126,6 +130,7 @@ public double Area() return area / 2.0; } + /// /// Checks if the current polyline is CW or CCW. /// @@ -150,9 +155,11 @@ public bool IsClockwise() continue; if (this.vertices[i].Y == ymin) // just as low + { if (this.vertices[i].X < xmin) // and to left continue; + } rmin = i; // a new rightmost lowest vertex xmin = this.vertices[i].X; @@ -163,15 +170,23 @@ public bool IsClockwise() // ccw <=> the edge leaving V[rmin] is left of the entering edge double result; if (rmin == 0) - result = new Line2d(this.vertices[this.vertices.Count - 1], this.vertices[0]).IsLeft(this.vertices[1]); + { + result = + new Line2d(this.vertices[this.vertices.Count - 1], this.vertices[0]).IsLeft( + this.vertices[1]); + } else - result = new Line2d(this.vertices[rmin - 1], this.vertices[rmin]).IsLeft(this.vertices[rmin + 1]); + { + result = new Line2d(this.vertices[rmin - 1], this.vertices[rmin]).IsLeft( + this.vertices[rmin + 1]); + } if (result == 0) throw new Exception("Polyline is degenerate, cannot compute orientation."); return result < 0; } + /// /// Reparametrizes the current curve to a unit interval. /// @@ -182,16 +197,18 @@ public void Reparametrize() double currentParam = 0; - this.segments.ForEach(segment => - { - var nextParam = currentParam + (segment.Domain.Length * ratio); - segment.Domain = new Interval(currentParam, nextParam); - currentParam = nextParam; - }); + this.segments.ForEach( + segment => + { + var nextParam = currentParam + segment.Domain.Length * ratio; + segment.Domain = new Interval(currentParam, nextParam); + currentParam = nextParam; + }); this.domain = Interval.Unit; } + private void RebuildSegments() { this.segments = new List(); @@ -207,6 +224,7 @@ private void RebuildSegments() this.domain = new Interval(0, currentParam); } + private Line2d BuildSegment(ref double currentParam, Point2d vertA, Point2d vertB) { var line = new Line2d(vertA, vertB); diff --git a/src/Geometry/2D/Ray2d.cs b/src/Geometry/2D/Ray2d.cs index 62ae723..7250834 100644 --- a/src/Geometry/2D/Ray2d.cs +++ b/src/Geometry/2D/Ray2d.cs @@ -18,24 +18,17 @@ public Ray2d(Point2d origin, Vector2d direction) this.Direction = direction ?? throw new ArgumentNullException(nameof(direction)); } + /// /// Gets or sets the origin of the ray. /// /// Origin point. - public Point2d Origin - { - get; - set; - } + public Point2d Origin { get; set; } /// /// Gets or sets the direction of the ray as a unit vector. /// /// Direction vector. - public Vector2d Direction - { - get; - set; - } + public Vector2d Direction { get; set; } } } \ No newline at end of file diff --git a/src/Geometry/2D/Vector2d.cs b/src/Geometry/2D/Vector2d.cs index e473bf5..1986323 100644 --- a/src/Geometry/2D/Vector2d.cs +++ b/src/Geometry/2D/Vector2d.cs @@ -15,6 +15,7 @@ public class Vector2d public Vector2d(Vector2d vector) : this(vector.X, vector.Y) { } + /// /// Initializes a new instance of the class from a point. /// @@ -23,6 +24,7 @@ public Vector2d(Vector2d vector) public Vector2d(Point2d point) : this(point.X, point.Y) { } + /// /// Initializes a new instance of the class. /// @@ -34,30 +36,23 @@ public Vector2d(double x, double y) this.Y = y; } + /// /// Gets or sets the X Coordininate of the vector. /// /// X coordinate. - public double X - { - get; - set; - } + public double X { get; set; } /// /// Gets or sets the Y coordinate of the vector. /// /// Y coordinate. - public double Y - { - get; - set; - } + public double Y { get; set; } /// /// Gets the squared length of the vector. /// - public double LengthSquared => (this.X * this.X) + (this.Y * this.Y); + public double LengthSquared => this.X * this.X + this.Y * this.Y; /// /// Gets the length of the vector. @@ -74,12 +69,14 @@ public double Y /// public static Vector2d WorldY => new Vector2d(0, 1); + /// /// Returns a unit vector of this vector. /// /// New vector of unit lenght. public Vector2d Unit() => new Vector2d(this / this.Length); + /// /// Force this vector to be unit length. /// @@ -90,53 +87,65 @@ public void Unitize() this.Y /= length; } + /// /// Returns a CCW perpendicular vector to the current instance. /// /// public Vector2d Perp() => new Vector2d(-this.Y, this.X); + /// /// Computes the dot product between this vector and the given one. /// /// Vector to compute dot-product with. /// Dot product result. - public double DotProduct(Vector2d vector) => (this.X * vector.X) + (this.Y * vector.Y); + public double DotProduct(Vector2d vector) => this.X * vector.X + this.Y * vector.Y; + /// /// Computes the perp product between this vector and the given one. /// /// Vector to compute perp-product with. /// Perp product result. - public double PerpProduct(Vector2d vector) => (this.X * vector.Y) - (this.Y * vector.X); + public double PerpProduct(Vector2d vector) => this.X * vector.Y - this.Y * vector.X; + /// /// Sums two vectors together. /// /// Vector A. /// Vector B. - public static Vector2d operator +(Vector2d v, Vector2d v2) => new Vector2d(v.X + v2.X, v.Y + v2.Y); + public static Vector2d operator +(Vector2d v, Vector2d v2) => + new Vector2d(v.X + v2.X, v.Y + v2.Y); + /// /// Substracts one vector from another. /// /// Vector A. /// Vector B. - public static Vector2d operator -(Vector2d v, Vector2d v2) => new Vector2d(v.X - v2.X, v.Y - v2.Y); + public static Vector2d operator -(Vector2d v, Vector2d v2) => + new Vector2d(v.X - v2.X, v.Y - v2.Y); + /// /// Multiplies a vector with a number. /// /// Vector. /// Number to multiply vector with. - public static Vector2d operator *(Vector2d v, double scalar) => new Vector2d(v.X * scalar, v.Y * scalar); + public static Vector2d operator *(Vector2d v, double scalar) => + new Vector2d(v.X * scalar, v.Y * scalar); + /// /// Multiplies a vector with a number. /// /// Number to multiply vector with. /// Vector. - public static Vector2d operator *(double scalar, Vector2d v) => new Vector2d(v.X * scalar, v.Y * scalar); + public static Vector2d operator *(double scalar, Vector2d v) => + new Vector2d(v.X * scalar, v.Y * scalar); + /// /// Negates the values of the vector. @@ -144,12 +153,15 @@ public void Unitize() /// Vector. public static Vector2d operator -(Vector2d v) => new Vector2d(-v.X, -v.Y); + /// /// Divides a vector with a number. /// /// Vector. /// Number to divide vector with. - public static Vector2d operator /(Vector2d v, double scalar) => new Vector2d(v.X / scalar, v.Y / scalar); + public static Vector2d operator /(Vector2d v, double scalar) => + new Vector2d(v.X / scalar, v.Y / scalar); + /// /// Checks for equality between two vectors. @@ -158,6 +170,7 @@ public void Unitize() /// Vector B. public static bool operator ==(Vector2d v, Vector2d w) => v.Equals(w); + /// /// Checks for inequality between two vectors. /// @@ -165,12 +178,14 @@ public void Unitize() /// Vector B. public static bool operator !=(Vector2d v, Vector2d w) => !v.Equals(w); + /// /// Gets the string representation of the vector. /// /// public override string ToString() => $"Vector3d [{this.X}, {this.Y}]"; + /// /// Checks if the vector is equal to an object. /// @@ -186,6 +201,7 @@ public override bool Equals(object obj) && Math.Abs(this.Y - vect.Y) <= Settings.Tolerance; } + /// /// Get the hashCode of the vector. /// @@ -196,11 +212,11 @@ public override int GetHashCode() { // Choose large primes to avoid hashing collisions // Choose large primes to avoid hashing collisions - const int hashingBase = (int)2166136261; + const int hashingBase = ( int ) 2166136261; const int hashingMultiplier = 16777619; var tol = Settings.Tolerance * 2; - var tX = (int)(this.X * (1 / tol)) * tol; - var tY = (int)(this.Y * (1 / tol)) * tol; + var tX = ( int ) (this.X * (1 / tol)) * tol; + var tY = ( int ) (this.Y * (1 / tol)) * tol; var hash = hashingBase; hash = (hash * hashingMultiplier) ^ tX.GetHashCode(); diff --git a/src/Geometry/3D/Circle.cs b/src/Geometry/3D/Circle.cs index 7025083..60b54ba 100644 --- a/src/Geometry/3D/Circle.cs +++ b/src/Geometry/3D/Circle.cs @@ -3,17 +3,34 @@ namespace Paramdigma.Core.Geometry { + /// + /// Represents a planar circle curve. + /// public class Circle : ICurve { + /// + /// The base plane for the circle. + /// public Plane Plane; + + /// + /// The radius of the circle. + /// public double Radius; + /// + /// Initializes a new instance of by it's plane and radius. + /// + /// The plane to draw the circle at. + /// The desired radius of the circle. public Circle(Plane plane, double radius) { this.Plane = plane; this.Radius = radius; } + + /// public Point3d PointAt(double t) { var radians = t * 2 * Math.PI; @@ -22,13 +39,24 @@ public Point3d PointAt(double t) return this.Plane.PointAt(x, y, 0); } + + /// public Vector3d TangentAt(double t) => this.NormalAt(t).Cross(this.Plane.ZAxis); + + /// public Vector3d NormalAt(double t) => (this.Plane.Origin - this.PointAt(t)).Unit(); + + /// public Vector3d BinormalAt(double t) => this.TangentAt(t).Cross(this.NormalAt(t)); - public Plane FrameAt(double t) => new Plane(this.PointAt(t), this.NormalAt(t), this.BinormalAt(t), this.TangentAt(t)); + /// + public Plane FrameAt(double t) => new Plane( + this.PointAt(t), + this.NormalAt(t), + this.BinormalAt(t), + this.TangentAt(t)); } } \ No newline at end of file diff --git a/src/Geometry/3D/Line.cs b/src/Geometry/3D/Line.cs index 959b4b4..c62cb6e 100644 --- a/src/Geometry/3D/Line.cs +++ b/src/Geometry/3D/Line.cs @@ -18,8 +18,10 @@ public Line(Point3d startPoint, Point3d endPoint) this.EndPoint = endPoint; } + /// - /// Initializes a new instance of the class from an origin point, a direction and a specified + /// Initializes a new instance of the class from an origin point, a direction + /// and a specified /// length. /// /// Start point of the line. @@ -28,26 +30,20 @@ public Line(Point3d startPoint, Point3d endPoint) public Line(Point3d origin, Vector3d direction, double length) { this.StartPoint = origin; - this.EndPoint = origin + (direction.Unit() * length); + this.EndPoint = origin + direction.Unit() * length; } + /// /// Gets or sets the lines's start point. /// - public Point3d StartPoint - { - get; - set; - } + public Point3d StartPoint { get; set; } /// /// Gets or sets the line's end point. /// - public Point3d EndPoint - { - get; - set; - } + public Point3d EndPoint { get; set; } + /// /// Checks if line is valid. @@ -55,12 +51,15 @@ public Point3d EndPoint /// True if valid. public override bool CheckValidity() => this.Length >= Settings.Tolerance; + /// /// Computes thepoint at the given parameter. /// /// Parameter of the point. Must be between 0 and 1. /// Point at specified parameter. - public override Point3d PointAt(double t) => this.StartPoint + (this.Domain.RemapToUnit(t) * (this.EndPoint - this.StartPoint)); + public override Point3d PointAt(double t) => + this.StartPoint + this.Domain.RemapToUnit(t) * (this.EndPoint - this.StartPoint); + /// /// Computes the tangent at the given parameter. @@ -74,6 +73,7 @@ public override Vector3d TangentAt(double t) return tangent; } + /// /// Computes the normal at the given parameter. /// @@ -92,19 +92,27 @@ public override Vector3d NormalAt(double t) return tangent.Cross(v); } + /// /// Computes the bi-normal vector at the given parameter. /// /// Parameter of the bi-normal vector. Must be between 0 and 1. /// Bi-normal vector at specified parameter. - public override Vector3d BinormalAt(double t) => Vector3d.CrossProduct(this.TangentAt(t), this.NormalAt(t)); + public override Vector3d BinormalAt(double t) => + Vector3d.CrossProduct(this.TangentAt(t), this.NormalAt(t)); + /// /// Computes the perpendicular frame at the given parameter. /// /// Parameter of the frame. Must be between 0 and 1. /// Frame at specified parameter. - public override Plane FrameAt(double t) => new Plane(this.PointAt(t), this.TangentAt(t), this.NormalAt(t), this.BinormalAt(t)); + public override Plane FrameAt(double t) => new Plane( + this.PointAt(t), + this.TangentAt(t), + this.NormalAt(t), + this.BinormalAt(t)); + /// /// Computes the length of the line. @@ -112,6 +120,11 @@ public override Vector3d NormalAt(double t) /// Line length. protected override double ComputeLength() => this.StartPoint.DistanceTo(this.EndPoint); + /// + /// Explicitly converts a line to it's vector representation. + /// + /// Line to convert. + /// Vector defining the line direction and length. public static explicit operator Vector3d(Line line) => line.EndPoint - line.StartPoint; } } \ No newline at end of file diff --git a/src/Geometry/3D/Mesh/Mesh.cs b/src/Geometry/3D/Mesh/Mesh.cs index 97539d8..44e88fc 100644 --- a/src/Geometry/3D/Mesh/Mesh.cs +++ b/src/Geometry/3D/Mesh/Mesh.cs @@ -21,6 +21,7 @@ public Mesh() this.Boundaries = new List(); } + /// /// Initializes a new instance of the class from verticees and faces. /// @@ -37,6 +38,7 @@ public Mesh(List vertices, List> faceIndexes) this.CreateFaces(faceIndexes); } + /// /// Initializes a new instance of the class from verticees and faces. /// @@ -51,6 +53,7 @@ public Mesh(List vertices, List> faceIndexes) this.CreateFaces(faceIndexes); } + /// /// Initializes a new instance of the class from an existing one. /// @@ -65,64 +68,42 @@ public Mesh(Mesh halfEdgeMesh) this.Boundaries = new List(halfEdgeMesh.Boundaries); } + /// /// Gets or sets the vertices of the mesh. /// - public List Vertices - { - get; - set; - } + public List Vertices { get; set; } /// /// Gets or sets the edges of the mesh. /// - public List Edges - { - get; - set; - } + public List Edges { get; set; } /// /// Gets or sets the faces of the mesh. /// - public List Faces - { - get; - set; - } + public List Faces { get; set; } /// /// Gets or sets the corners of the mesh. /// - public List Corners - { - get; - set; - } + public List Corners { get; set; } /// /// Gets or sets the half-edges of the mesh. /// - public List HalfEdges - { - get; - set; - } + public List HalfEdges { get; set; } /// /// Gets or sets the boundaries of the mesh. /// - public List Boundaries - { - get; - set; - } + public List Boundaries { get; set; } /// /// Gets the euler characteristic of the mesh. /// - public int EulerCharacteristic => (this.Vertices.Count - this.Edges.Count) + this.Faces.Count; + public int EulerCharacteristic => this.Vertices.Count - this.Edges.Count + this.Faces.Count; + /// /// Check if the mesh has isolated vertices. @@ -131,12 +112,15 @@ public List Boundaries public bool HasIsolatedVertices() { foreach (var v in this.Vertices) + { if (v.IsIsolated()) return true; + } return false; } + /// /// Check if the mesh contains isolated faces. /// @@ -148,8 +132,10 @@ public bool HasIsolatedFaces() var boundaryEdges = 0; var adjacent = f.AdjacentHalfEdges(); foreach (var e in adjacent) + { if (e.OnBoundary) boundaryEdges++; + } if (boundaryEdges == adjacent.Count) return true; @@ -158,6 +144,7 @@ public bool HasIsolatedFaces() return false; } + /// /// Check if the mesh contains non-manifold edges. /// @@ -165,12 +152,15 @@ public bool HasIsolatedFaces() public bool HasNonManifoldEdges() { foreach (var edge in this.Edges) + { if (edge.AdjacentFaces().Count > 2) return true; + } return false; } + /// /// Assign an index number to each mesh member. /// @@ -219,6 +209,7 @@ public void IndexElements() } } + /// /// Assign an index to each vertex of the mesh. /// @@ -232,6 +223,7 @@ public Dictionary IndexVertices() return index; } + /// /// Assign an index to each face of the mesh. /// @@ -245,6 +237,7 @@ public Dictionary IndexFaces() return index; } + /// /// Assign an index to each edge of the mesh. /// @@ -258,6 +251,7 @@ public Dictionary IndexEdges() return index; } + /// /// Assign an index to each Half-Edge of the mesh. /// @@ -271,6 +265,7 @@ public Dictionary IndexHalfEdes() return index; } + /// /// Assign an index to each corner of the mesh. /// @@ -284,24 +279,28 @@ public Dictionary IndexCorners() return index; } + /// /// Check if a mesh is triangular. /// /// Returns true if all faces are triangular. public bool IsTriangularMesh() => this.IsMesh() == IsMeshResult.Triangular; + /// /// Check if a mesh is quad. /// /// Returns true if all faces are quads. public bool IsQuadMesh() => this.IsMesh() == IsMeshResult.Quad; + /// /// Check if a mesh is n-gonal. /// /// Returns true if the mesh contains ANY ngons. public bool IsNgonMesh() => this.IsMesh() == IsMeshResult.Ngon; + /// /// Returns an enum corresponding to the mesh face topology (triangular, quad or ngon). /// @@ -314,9 +313,10 @@ private IsMeshResult IsMesh() return IsMeshResult.Quad; if (count.Ngons != 0) return IsMeshResult.Ngon; - return IsMeshResult.ERROR; + return IsMeshResult.Error; } + /// /// Get human readable description of this mesh. /// @@ -325,8 +325,10 @@ public string GetMeshInfo() { const string head = "--- Mesh Info ---\n"; - var vef = "V: " + this.Vertices.Count + "; F: " + this.Faces.Count + "; E:" + this.Edges.Count + "\n"; - var hec = "Half-edges: " + this.HalfEdges.Count + "; Corners: " + this.Corners.Count + "\n"; + var vef = "V: " + this.Vertices.Count + "; F: " + this.Faces.Count + "; E:" + + this.Edges.Count + "\n"; + var hec = "Half-edges: " + this.HalfEdges.Count + "; Corners: " + this.Corners.Count + + "\n"; var bounds = "Boundaries: " + this.Boundaries.Count + "\n"; var euler = "Euler characteristic: " + this.EulerCharacteristic + "\n"; var isoVert = "Isolated vertices: " + this.HasIsolatedVertices() + "\n"; @@ -340,19 +342,24 @@ public string GetMeshInfo() const string tail = "----- -----\n\n"; - return head + vef + hec + bounds + euler + isoVert + isoFace + manifold + triangles + quads + ngons + tail; + return head + vef + hec + bounds + euler + isoVert + isoFace + manifold + triangles + + quads + ngons + tail; } + /// /// Gets string representation of the mesh. /// /// Mesh string. public override string ToString() { - var vefh = "V: " + this.Vertices.Count + "; F: " + this.Faces.Count + "; E:" + this.Edges.Count + "; hE: " + this.HalfEdges.Count; + var vefh = "V: " + this.Vertices.Count + "; F: " + this.Faces.Count + "; E:" + + this.Edges.Count + + "; hE: " + this.HalfEdges.Count; return "HE_Mesh{" + vefh + "}"; } + private void CreateVertices(List points) { var verts = new List(points.Count); @@ -366,6 +373,7 @@ private void CreateVertices(List points) this.Vertices = verts; } + // Takes a List containing another List per face with the vertex indexes belonging to that face private bool CreateFaces(List> faceIndexes) { @@ -399,7 +407,7 @@ private bool CreateFaces(List> faceIndexes) // Set previous and next h.Next = tempHEdges[(i + 1) % indexes.Count]; - h.Prev = tempHEdges[((i + indexes.Count) - 1) % indexes.Count]; + h.Prev = tempHEdges[(i + indexes.Count - 1) % indexes.Count]; h.OnBoundary = false; hasTwinHalfEdge.Add(h, false); @@ -486,7 +494,7 @@ private bool CreateFaces(List> faceIndexes) var n = boundaryCycle.Count; for (var j = 0; j < n; j++) { - boundaryCycle[j].Next = boundaryCycle[((j + n) - 1) % n]; + boundaryCycle[j].Next = boundaryCycle[(j + n - 1) % n]; boundaryCycle[j].Prev = boundaryCycle[(j + 1) % n]; hasTwinHalfEdge[boundaryCycle[j]] = true; hasTwinHalfEdge[boundaryCycle[j].Twin] = true; @@ -511,11 +519,13 @@ private bool CreateFaces(List> faceIndexes) return true; } + private FaceData CountFaceEdges() { FaceData data = default; foreach (var face in this.Faces) + { switch (face.AdjacentCorners().Count) { case 3: @@ -528,17 +538,21 @@ private FaceData CountFaceEdges() data.Ngons++; break; } + } return data; } + /// /// Type of mesh (Triangular, Quad, Ngon or Error). /// private enum IsMeshResult { - Triangular, Quad, Ngon, - ERROR + Triangular, + Quad, + Ngon, + Error } private struct FaceData diff --git a/src/Geometry/3D/Mesh/MeshCorner.cs b/src/Geometry/3D/Mesh/MeshCorner.cs index 55be38c..f53d78c 100644 --- a/src/Geometry/3D/Mesh/MeshCorner.cs +++ b/src/Geometry/3D/Mesh/MeshCorner.cs @@ -10,23 +10,16 @@ public class MeshCorner /// public MeshCorner() => this.Index = -1; + /// /// Gets or sets the corner's first half-edge. /// - public MeshHalfEdge HalfEdge - { - get; - set; - } + public MeshHalfEdge HalfEdge { get; set; } /// /// Gets or sets the index of the mesh corner. /// - public int Index - { - get; - set; - } + public int Index { get; set; } /// /// Gets the mesh corner vertex. diff --git a/src/Geometry/3D/Mesh/MeshEdge.cs b/src/Geometry/3D/Mesh/MeshEdge.cs index 6fe0c35..58a5ea3 100644 --- a/src/Geometry/3D/Mesh/MeshEdge.cs +++ b/src/Geometry/3D/Mesh/MeshEdge.cs @@ -13,29 +13,23 @@ public class MeshEdge /// public MeshEdge() => this.Index = -1; + /// /// Gets or sets the half-edge linked to this edge. /// - public MeshHalfEdge HalfEdge - { - get; - set; - } + public MeshHalfEdge HalfEdge { get; set; } /// /// Gets or sets the index of this Mesh Edge. /// - public int Index - { - get; - set; - } + public int Index { get; set; } /// /// Gets a value indicating whether the mesh edge lies on a boundary. /// public bool OnBoundary => this.HalfEdge.OnBoundary || this.HalfEdge.Twin.OnBoundary; + /// /// Gets the adjacent vertices of this given edge. /// @@ -46,16 +40,21 @@ public List AdjacentVertices() return vertices; } + /// /// Gets the adjacent faces of this edge. /// /// public List AdjacentFaces() { - var faces = new List {this.HalfEdge.AdjacentFace, this.HalfEdge.Twin.AdjacentFace}; + var faces = new List + { + this.HalfEdge.AdjacentFace, this.HalfEdge.Twin.AdjacentFace + }; return faces; } + /// /// Gets the adjacent edges of this edge. /// diff --git a/src/Geometry/3D/Mesh/MeshFace.cs b/src/Geometry/3D/Mesh/MeshFace.cs index 6026c4c..beb07f4 100644 --- a/src/Geometry/3D/Mesh/MeshFace.cs +++ b/src/Geometry/3D/Mesh/MeshFace.cs @@ -17,23 +17,16 @@ public MeshFace() this.Index = -1; } + /// /// Gets or sets one of the half-edges surrounding the face. /// - public MeshHalfEdge HalfEdge - { - get; - set; - } + public MeshHalfEdge HalfEdge { get; set; } /// /// Gets or sets the face index on the mesh face list. /// - public int Index - { - get; - set; - } + public int Index { get; set; } /// /// Gets the area of the face. @@ -47,6 +40,7 @@ public int Index /// Returns the perpendicular vector to the face. public Vector3d Normal => MeshGeometry.FaceNormal(this); + /// /// Get all adjacent edges to this face. /// @@ -64,6 +58,7 @@ public List AdjacentEdges() return edges; } + /// /// Get all adjacent half-edges to this face. /// @@ -81,6 +76,7 @@ public List AdjacentHalfEdges() return halfEdges; } + /// /// Get all adjacent vertices to this face. /// @@ -98,6 +94,7 @@ public List AdjacentVertices() return vertices; } + /// /// Get all adjacent faces to this face. /// @@ -116,6 +113,7 @@ public List AdjacentFaces() return faces; } + /// /// Get all adjacent corners to this face. /// @@ -133,12 +131,14 @@ public List AdjacentCorners() return corners; } + /// /// Checks if the current face is a boundary face. /// /// Returns true if the face is a boundary face, false if not. public bool IsBoundaryLoop() => this.HalfEdge.OnBoundary; + /// /// Convert the mesh face to string. /// diff --git a/src/Geometry/3D/Mesh/MeshGeometry.cs b/src/Geometry/3D/Mesh/MeshGeometry.cs index 095d733..84d3b8c 100644 --- a/src/Geometry/3D/Mesh/MeshGeometry.cs +++ b/src/Geometry/3D/Mesh/MeshGeometry.cs @@ -13,7 +13,9 @@ public static class MeshGeometry /// /// The half-edge vector. /// Half edge. - public static Vector3d Vector(MeshHalfEdge halfEdge) => halfEdge.Vertex - halfEdge.Next.Vertex; + public static Vector3d Vector(MeshHalfEdge halfEdge) => + halfEdge.Vertex - halfEdge.Next.Vertex; + /// /// Calculates the length of the specified edge. @@ -22,6 +24,7 @@ public static class MeshGeometry /// Edge. public static double Length(MeshEdge edge) => Vector(edge.HalfEdge).Length; + /// /// Calculates the midpoint of the specifiec edge. /// @@ -35,6 +38,7 @@ public static Point3d MidPoint(MeshEdge edge) return (a + b) / 2; } + /// /// Calculates the mean edge length of the mesh. /// @@ -48,6 +52,7 @@ public static double MeanEdgeLength(Mesh mesh) return sum / mesh.Edges.Count; } + /// /// Computes the area of the specified face. /// @@ -63,6 +68,7 @@ public static double Area(MeshFace face) return 0.5 * u.Cross(v).Length; } + /// /// Computes the total area of the mesh. /// @@ -76,6 +82,7 @@ public static double TotalArea(Mesh mesh) return sum; } + /// /// Compute the normal vector of the specified face. /// @@ -91,6 +98,7 @@ public static Vector3d FaceNormal(MeshFace face) return u.Cross(v).Unit(); } + /// /// Compute the centroid of the specified face. /// @@ -109,6 +117,7 @@ public static Point3d Centroid(MeshFace face) return (a + b + c) / 3; } + /// /// Compute the circumcenter the specified face. /// @@ -132,11 +141,12 @@ public static Point3d Circumcenter(MeshFace face) var u = w.Cross(ab) * ac.LengthSquared; var v = ac.Cross(w) * ab.LengthSquared; - var x = (Point3d)(u + v) / (2 * w.LengthSquared); + var x = ( Point3d ) (u + v) / (2 * w.LengthSquared); return x + a; } + /// /// Compute the orthonormal bases of the specified face. /// @@ -151,6 +161,7 @@ public static Vector3d[] OrthonormalBases(MeshFace face) return new[] {e1, e2}; } + /// /// Compute the angle (in radians) at the specified corner. /// @@ -164,6 +175,7 @@ public static double Angle(MeshCorner corner) return Math.Acos(Math.Max(-1, Math.Min(1.0, u.Dot(v)))); } + /// /// Computes the cotangent of the angle opposite to a halfedge. /// @@ -180,6 +192,7 @@ public static double Cotan(MeshHalfEdge hE) return u.Dot(v) / u.Cross(v).Length; } + /// /// Computes the signed angle (in radians) between the faces adjacent to the specified half-edge. /// @@ -200,6 +213,7 @@ public static double DihedralAngle(MeshHalfEdge hE) return Math.Atan2(sinTheta, cosTheta); } + /// /// Computes the barycentric dual area around a given mesh vertex. /// @@ -213,6 +227,7 @@ public static double BarycentricDualArea(MeshVertex vertex) return area; } + /// /// Computes the circumcentric dual area around a given mesh vertex. /// @@ -228,12 +243,13 @@ public static double CircumcentricDualarea(MeshVertex vertex) var cotAlpha = Cotan(hE.Prev); var cotBeta = Cotan(hE); - area += ((u2 * cotAlpha) + (v2 * cotBeta)) / 8; + area += (u2 * cotAlpha + v2 * cotBeta) / 8; } return area; } + /// /// Computes the equally weighted normal arround the specified vertex. /// @@ -248,6 +264,7 @@ public static Vector3d VertexNormalEquallyWeighted(MeshVertex vertex) return n.Unit(); } + /// /// Computes the area weighted normal arround the specified vertex. /// @@ -267,6 +284,7 @@ public static Vector3d VertexNormalAreaWeighted(MeshVertex vertex) return n.Unit(); } + /// /// Computes the angle weighted normal arround the specified vertex. /// @@ -286,6 +304,7 @@ public static Vector3d VertexNormalAngleWeighted(MeshVertex vertex) return n.Unit(); } + /// /// Computes the gauss curvature weighted normal arround the specified vertex. /// @@ -296,13 +315,14 @@ public static Vector3d VertexNormalGaussCurvature(MeshVertex vertex) var n = new Vector3d(); foreach (var hE in vertex.AdjacentHalfEdges()) { - var weight = (0.5 * DihedralAngle(hE)) / Length(hE.Edge); + var weight = 0.5 * DihedralAngle(hE) / Length(hE.Edge); n -= Vector(hE) * weight; } return n.Unit(); } + /// /// Computes the mean curvature weighted normal arround the specified vertex. /// @@ -313,13 +333,14 @@ public static Vector3d VertexNormalMeanCurvature(MeshVertex vertex) var n = new Vector3d(); foreach (var hE in vertex.AdjacentHalfEdges()) { - var weight = (0.5 * Cotan(hE)) + Cotan(hE.Twin); + var weight = 0.5 * Cotan(hE) + Cotan(hE.Twin); n -= Vector(hE) * weight; } return n.Unit(); } + /// /// Computes the sphere inscribed normal arround the specified vertex. /// @@ -339,6 +360,7 @@ public static Vector3d VertexNormalSphereInscribed(MeshVertex vertex) return n.Unit(); } + /// /// Computes the angle defect at the given vertex. /// @@ -351,15 +373,18 @@ public static double AngleDefect(MeshVertex vertex) angleSum += Angle(c); // if (vertex.OnBoundary()) angleSum = Math.PI - angleSum; - return vertex.OnBoundary() ? Math.PI - angleSum : (2 * Math.PI) - angleSum; + return vertex.OnBoundary() ? Math.PI - angleSum : 2 * Math.PI - angleSum; } + /// /// Compute the Gaussian curvature at the given vertex. /// /// Vertex to compute Gaussian curvature. /// Number representing the gaussian curvature at that vertex. - public static double ScalarGaussCurvature(MeshVertex vertex) => AngleDefect(vertex) / CircumcentricDualarea(vertex); + public static double ScalarGaussCurvature(MeshVertex vertex) => + AngleDefect(vertex) / CircumcentricDualarea(vertex); + /// /// Compute the Mean curvature at the given vertex. @@ -374,6 +399,7 @@ public static double ScalarMeanCurvature(MeshVertex vertex) return sum; } + /// /// Compute the total angle defect of the mesh. /// @@ -387,6 +413,7 @@ public static double TotalAngleDefect(Mesh mesh) return totalDefect; } + /// /// Compute the principal curvature scalar values at a given vertes. /// @@ -398,7 +425,7 @@ public static double[] PrincipalCurvatures(MeshVertex vertex) var h = ScalarMeanCurvature(vertex) / a; var k = AngleDefect(vertex) / a; - var discriminant = (h * h) - k; + var discriminant = h * h - k; if (discriminant > 0) discriminant = Math.Sqrt(discriminant); else diff --git a/src/Geometry/3D/Mesh/MeshHalfEdge.cs b/src/Geometry/3D/Mesh/MeshHalfEdge.cs index 30bb1dd..18b176a 100644 --- a/src/Geometry/3D/Mesh/MeshHalfEdge.cs +++ b/src/Geometry/3D/Mesh/MeshHalfEdge.cs @@ -10,86 +10,51 @@ public class MeshHalfEdge /// public MeshHalfEdge() => this.Index = -1; + /// /// Gets or sets the vertex linked to this half-edge. /// - public MeshVertex Vertex - { - get; - set; - } + public MeshVertex Vertex { get; set; } /// /// Gets or sets the edge linked to this half-edge. /// - public MeshEdge Edge - { - get; - set; - } + public MeshEdge Edge { get; set; } /// /// Gets or sets the face linked to this half-edge. /// - public MeshFace Face - { - get; - set; - } + public MeshFace Face { get; set; } /// /// Gets or sets the corner linked to this half-edge. /// - public MeshCorner Corner - { - get; - set; - } + public MeshCorner Corner { get; set; } /// /// Gets or sets the next half-edge in a face. /// - public MeshHalfEdge Next - { - get; - set; - } + public MeshHalfEdge Next { get; set; } /// /// Gets or sets the previous half-edge in a face. /// - public MeshHalfEdge Prev - { - get; - set; - } + public MeshHalfEdge Prev { get; set; } /// /// Gets or sets the opposite half-edge. /// - public MeshHalfEdge Twin - { - get; - set; - } + public MeshHalfEdge Twin { get; set; } /// /// Gets or sets a value indicating whether the half-edge lies on a boundary. /// - public bool OnBoundary - { - get; - set; - } + public bool OnBoundary { get; set; } /// /// Gets or sets the half-edge index. /// - public int Index - { - get; - set; - } + public int Index { get; set; } /// /// Gets the previous vertex of the half-edge. @@ -101,6 +66,7 @@ public int Index /// public MeshFace AdjacentFace => this.Twin.Face; + /// /// Gets the string representation of the half-edge. /// diff --git a/src/Geometry/3D/Mesh/MeshPoint.cs b/src/Geometry/3D/Mesh/MeshPoint.cs index b264cd4..5629003 100644 --- a/src/Geometry/3D/Mesh/MeshPoint.cs +++ b/src/Geometry/3D/Mesh/MeshPoint.cs @@ -22,6 +22,7 @@ public MeshPoint(int faceIndex, double u, double v, double w) this.W = w; } + /// /// Initializes a new instance of the class. /// @@ -36,46 +37,33 @@ public MeshPoint(MeshFace face, Point3d point) this.W = bary[2]; } + /// /// Gets or sets the index of the face this point lies in. /// - public int FaceIndex - { - get; - set; - } + public int FaceIndex { get; set; } /// /// Gets or sets the U coordinate at the face. /// - public double U - { - get; - set; - } + public double U { get; set; } /// /// Gets or sets the V coordinate at the face. /// - public double V - { - get; - set; - } + public double V { get; set; } /// /// Gets or sets the W coordinate at the face. /// - public double W - { - get; - set; - } + public double W { get; set; } + /// /// Converts a mesh point into a string. /// /// String representation of the mesh point. - public override string ToString() => "MeshPoint{ " + this.FaceIndex + "; " + this.U + ", " + this.V + ", " + this.W + " }"; + public override string ToString() => + "MeshPoint{ " + this.FaceIndex + "; " + this.U + ", " + this.V + ", " + this.W + " }"; } } \ No newline at end of file diff --git a/src/Geometry/3D/Mesh/MeshTopology.cs b/src/Geometry/3D/Mesh/MeshTopology.cs index 3ca6797..19e70ea 100644 --- a/src/Geometry/3D/Mesh/MeshTopology.cs +++ b/src/Geometry/3D/Mesh/MeshTopology.cs @@ -11,6 +11,7 @@ public class MeshTopology // Returns 2 dimensional array: 1 array per vertex index containing an array with the corresponding adjacent member index private readonly Mesh mesh; + /// /// Initializes a new instance of the class. /// @@ -30,77 +31,52 @@ public MeshTopology(Mesh mesh) this.EdgeEdge = new Dictionary>(); } + /// /// Gets vertex-Vertex topological connections. /// - public Dictionary> VertexVertex - { - get; - } + public Dictionary> VertexVertex { get; } /// /// Gets vertex-Face topological connections. /// - public Dictionary> VertexFaces - { - get; - } + public Dictionary> VertexFaces { get; } /// /// Gets vertex-Edge topological connections. /// - public Dictionary> VertexEdges - { - get; - } + public Dictionary> VertexEdges { get; } /// /// Gets edge-Edge topological connections. /// - public Dictionary> EdgeEdge - { - get; - } + public Dictionary> EdgeEdge { get; } /// /// Gets edge-Vertex topological connections. /// - public Dictionary> EdgeVertex - { - get; - } + public Dictionary> EdgeVertex { get; } /// /// Gets edge-Face topological connections. /// - public Dictionary> EdgeFace - { - get; - } + public Dictionary> EdgeFace { get; } /// /// Gets face-Vertex topological connections. /// - public Dictionary> FaceVertex - { - get; - } + public Dictionary> FaceVertex { get; } /// /// Gets face-Edge topological connections. /// - public Dictionary> FaceEdge - { - get; - } + public Dictionary> FaceEdge { get; } /// /// Gets face-Face topological connections. /// - public Dictionary> FaceFace - { - get; - } + public Dictionary> FaceFace { get; } + /// /// Computes vertex adjacency for the whole mesh and stores it in the appropriate dictionaries. @@ -110,25 +86,32 @@ public void ComputeVertexAdjacency() foreach (var vertex in this.mesh.Vertices) { foreach (var adjacent in vertex.AdjacentVertices()) + { if (!this.VertexVertex.ContainsKey(vertex.Index)) this.VertexVertex.Add(vertex.Index, new List {adjacent.Index}); else this.VertexVertex[vertex.Index].Add(adjacent.Index); + } foreach (var adjacent in vertex.AdjacentFaces()) + { if (!this.VertexFaces.ContainsKey(vertex.Index)) this.VertexFaces.Add(vertex.Index, new List {adjacent.Index}); else this.VertexFaces[vertex.Index].Add(adjacent.Index); + } foreach (var adjacent in vertex.AdjacentEdges()) + { if (!this.VertexEdges.ContainsKey(vertex.Index)) this.VertexEdges.Add(vertex.Index, new List {adjacent.Index}); else this.VertexEdges[vertex.Index].Add(adjacent.Index); + } } } + /// /// Computes face adjacency for the whole mesh and stores it in the appropriate dictionaries. /// @@ -137,25 +120,32 @@ public void ComputeFaceAdjacency() foreach (var face in this.mesh.Faces) { foreach (var adjacent in face.AdjacentVertices()) + { if (!this.FaceVertex.ContainsKey(face.Index)) this.FaceVertex.Add(face.Index, new List {adjacent.Index}); else this.FaceVertex[face.Index].Add(adjacent.Index); + } foreach (var adjacent in face.AdjacentFaces()) + { if (!this.FaceFace.ContainsKey(face.Index)) this.FaceFace.Add(face.Index, new List {adjacent.Index}); else this.FaceFace[face.Index].Add(adjacent.Index); + } foreach (var adjacent in face.AdjacentEdges()) + { if (!this.FaceEdge.ContainsKey(face.Index)) this.FaceEdge.Add(face.Index, new List {adjacent.Index}); else this.FaceEdge[face.Index].Add(adjacent.Index); + } } } + /// /// Computes edge adjacency for the whole mesh and stores it in the appropriate dictionaries. /// @@ -164,25 +154,32 @@ public void ComputeEdgeAdjacency() foreach (var edge in this.mesh.Edges) { foreach (var adjacent in edge.AdjacentVertices()) + { if (!this.EdgeVertex.ContainsKey(edge.Index)) this.EdgeVertex.Add(edge.Index, new List {adjacent.Index}); else this.EdgeVertex[edge.Index].Add(adjacent.Index); + } foreach (var adjacent in edge.AdjacentFaces()) + { if (!this.EdgeFace.ContainsKey(edge.Index)) this.EdgeFace.Add(edge.Index, new List {adjacent.Index}); else this.EdgeFace[edge.Index].Add(adjacent.Index); + } foreach (var adjacent in edge.AdjacentEdges()) + { if (!this.EdgeEdge.ContainsKey(edge.Index)) this.EdgeEdge.Add(edge.Index, new List {adjacent.Index}); else this.EdgeEdge[edge.Index].Add(adjacent.Index); + } } } + /// /// Gets the string representation of a given topology dictionary. /// diff --git a/src/Geometry/3D/Mesh/MeshVertex.cs b/src/Geometry/3D/Mesh/MeshVertex.cs index d8da16f..0454d04 100644 --- a/src/Geometry/3D/Mesh/MeshVertex.cs +++ b/src/Geometry/3D/Mesh/MeshVertex.cs @@ -13,11 +13,13 @@ public class MeshVertex : Point3d // Constructor + /// /// Initializes a new instance of the class. /// public MeshVertex() => this.userValues = new Dictionary(); + /// /// Initializes a new instance of the class from a 3D point. /// @@ -26,8 +28,10 @@ public MeshVertex(Point3d pt) : base(pt) => this.userValues = new Dictionary(); + /// - /// Initializes a new instance of the class from it's cartesian coordiantes. + /// Initializes a new instance of the class from it's cartesian + /// coordiantes. /// /// X Coordiante. /// Y Coordinate. @@ -36,23 +40,16 @@ public MeshVertex(double x, double y, double z) : base(x, y, z) => this.userValues = new Dictionary(); + /// /// Gets or sets the half-edge this vertex is attached to. /// - public MeshHalfEdge HalfEdge - { - get; - set; - } + public MeshHalfEdge HalfEdge { get; set; } /// /// Gets or sets the index of the vertex. /// - public int Index - { - get; - set; - } + public int Index { get; set; } /// /// Gets dictionary of user values. @@ -64,24 +61,28 @@ public int Index // Calculate the valence of a vertex + /// /// Computes the valence of the vertex. /// /// public int Valence() => this.AdjacentHalfEdges().Count; + /// /// Check if vertex is isolated, meaning corresponding half-edge is null. /// /// public bool IsIsolated() => this.HalfEdge == null; + /// /// Check if vertex is on mesh boundary. /// /// public bool OnBoundary() => this.AdjacentHalfEdges().Any(halfEdge => halfEdge.OnBoundary); + /// /// Returns a list with all adjacent HE_HalfEdge of this vertex. /// @@ -99,6 +100,7 @@ public List AdjacentHalfEdges() return halfEdges; } + /// /// Returns a list with all adjacent HE_Face of a vertex. /// @@ -117,6 +119,7 @@ public List AdjacentFaces() return faces; } + /// /// Returns a list with all the adjacent HE_Vertex of this vertex. /// @@ -134,6 +137,7 @@ public List AdjacentVertices() return vertices; } + /// /// Returns a list with all the adjacent HE_Edge of this vertex. /// @@ -151,6 +155,7 @@ public List AdjacentEdges() return edges; } + /// /// Returns a list with all the adjacent HE_Corners of this vertex. /// @@ -169,6 +174,7 @@ public List AdjacentCorners() return corners; } + /// /// Returns the string representation of this vertex. /// diff --git a/src/Geometry/3D/Nurbs/NurbsCalculator.cs b/src/Geometry/3D/Nurbs/NurbsCalculator.cs index f8b1836..7eb4239 100644 --- a/src/Geometry/3D/Nurbs/NurbsCalculator.cs +++ b/src/Geometry/3D/Nurbs/NurbsCalculator.cs @@ -5,7 +5,8 @@ namespace Paramdigma.Core.Geometry { /// - /// Contains all methods related to 'The Nurbs Book 2nd Edition' implementation of NURBS curves and surfaces. + /// Contains all methods related to 'The Nurbs Book 2nd Edition' implementation of NURBS curves and + /// surfaces. /// public static class NurbsCalculator { @@ -24,12 +25,13 @@ public static double[] CreateUnitKnotVector(int controlPointCount, int degree) for (var i = 0; i <= degree; i++) knotVector[i] = 0.0; for (var i = degree + 1; i < controlPointCount; i++) - knotVector[i] = ((double)i - degree) / (controlPointCount - degree); + knotVector[i] = (( double ) i - degree) / (controlPointCount - degree); for (var i = controlPointCount; i < controlPointCount + degree + 1; i++) knotVector[i] = 1.0; return knotVector; } + /// /// Compute a point on a power basis curve. /// @@ -41,10 +43,11 @@ public static Point3d Horner1(Point3d[] points, int degree, double t) { var c = points[degree]; for (var i = degree - 1; i >= 0; i--) - c = (c * t) + points[i]; + c = c * t + points[i]; return c; } + /// /// Compute the value of a Bernstein polynomial. /// @@ -64,12 +67,13 @@ public static double Bernstein(int index, int degree, double t) for (var k = 1; k <= degree; k++) { for (var j = degree; j >= k; j--) - temp[j] = (u1 * temp[j]) + (t * temp[j - 1]); + temp[j] = u1 * temp[j] + t * temp[j - 1]; } return temp[degree]; } + /// /// Compute point on a power basis surface. /// @@ -79,7 +83,12 @@ public static double Bernstein(int index, int degree, double t) /// U parameter to compute. /// V parameter to compute. /// Computed point on the surface. - public static Point3d Horner2(Matrix controlPoints, int degreeU, int degreeV, double u, double v) + public static Point3d Horner2( + Matrix controlPoints, + int degreeU, + int degreeV, + double u, + double v) { var b = new Point3d[degreeU]; for (var i = 0; i <= degreeU; i++) @@ -87,6 +96,7 @@ public static Point3d Horner2(Matrix controlPoints, int degreeU, int de return Horner1(b, degreeU, u); } + /// /// Compute all nth-degree Bernstein polynomials. /// @@ -104,7 +114,7 @@ public static double[] AllBernstein(int degree, double t) for (var k = 0; k < j; k++) { var temp = b[k]; - b[k] = saved + (u1 * temp); + b[k] = saved + u1 * temp; saved = t * temp; } @@ -114,6 +124,7 @@ public static double[] AllBernstein(int degree, double t) return b; } + /// /// Compute point on Bezier curve. /// @@ -132,6 +143,7 @@ public static Point3d PointOnBezierCurve(List controlPoints, int degree return c; } + /// /// Compute point on a Bézier curve by deCasteljau. /// @@ -146,12 +158,15 @@ public static Point3d DeCasteljau1(Point3d[] controlPoints, int degree, double t q[i] = new Point3d(controlPoints[i]); for (var k = 1; k <= degree; k++) - for (var i = 0; i <= degree - k; i++) - q[i] = ((1.0 - t) * q[i]) + (t * q[i + 1]); + { + for (var i = 0; i <= degree - k; i++) + q[i] = (1.0 - t) * q[i] + t * q[i + 1]; + } return q[0]; } + /// /// Compute a point on a Bézier surface by deCasteljau. /// @@ -161,7 +176,12 @@ public static Point3d DeCasteljau1(Point3d[] controlPoints, int degree, double t /// U parameter to compute. /// V parameter to compute. /// The computed point. - public static Point3d DeCasteljau2(Matrix controlPoints, int degreeU, int degreeV, double u, double v) + public static Point3d DeCasteljau2( + Matrix controlPoints, + int degreeU, + int degreeV, + double u, + double v) { var q = new List(); if (degreeU <= degreeV) @@ -177,12 +197,13 @@ public static Point3d DeCasteljau2(Matrix controlPoints, int degreeU, i return DeCasteljau1(q.ToArray(), degreeU, u); } + /// /// Determine the knot span index. /// /// Degree. /// ????. - /// Paramter. + /// Parameter. /// Knot vector. /// The knot span index. public static int FindSpan(int n, int degree, double t, IList knotVector) @@ -206,6 +227,7 @@ public static int FindSpan(int n, int degree, double t, IList knotVector return mid; } + /// /// Compute all non-zero basis functions of all degrees from 0 to "degree". /// @@ -214,18 +236,30 @@ public static int FindSpan(int n, int degree, double t, IList knotVector /// Degree. /// The knot vector. /// List with all non-zero basis functions up to the specified degree. - public static double[,] AllBasisFuns(int span, double param, int degree, IList knotVector) + public static double[,] AllBasisFuns( + int span, + double param, + int degree, + IList knotVector) { var n = new double[degree + 1, degree + 1]; for (var i = 0; i <= degree; i++) { for (var j = 0; j <= i; j++) - n[j, i] = OneBasisFun(degree, knotVector.Count - 1, knotVector, (span - i) + j, param); + { + n[j, i] = OneBasisFun( + degree, + knotVector.Count - 1, + knotVector, + span - i + j, + param); + } } return n; } + /// /// Computes the basis functions of a span. /// @@ -234,21 +268,26 @@ public static int FindSpan(int n, int degree, double t, IList knotVector /// Degree. /// Knot vector. /// List of the basis functions of the specific span. - public static double[] BasisFuns(int span, double param, int degree, IList knotVector) + public static double[] BasisFunctions( + int span, + double param, + int degree, + IList knotVector) { + // INFO: This method is called 'BasisFuns' in the book. var basisFunctions = new double[degree + 1]; var left = new double[degree + 1]; var right = new double[degree + 1]; basisFunctions[0] = 1.0; for (var j = 1; j <= degree; j++) { - left[j] = param - knotVector[(span + 1) - j]; + left[j] = param - knotVector[span + 1 - j]; right[j] = knotVector[span + j] - param; var saved = 0.0; for (var r = 0; r < j; r++) { var temp = basisFunctions[r] / (right[r + 1] + left[j - r]); - basisFunctions[r] = saved + (right[r + 1] * temp); + basisFunctions[r] = saved + right[r + 1] * temp; saved = left[j - r] * temp; } @@ -258,6 +297,7 @@ public static double[] BasisFuns(int span, double param, int degree, IList /// Compute nonzero basis functions and their derivatives at a specified parameter. /// @@ -266,9 +306,18 @@ public static double[] BasisFuns(int span, double param, int degree, IListDegree. /// Derivatives to compute. /// Knot vector. - /// Multidimensional array holding the basis functions and their derivatives for that parameter. - public static Matrix DersBasisFuns(int span, double param, int degree, int n, IList knotVector) + /// + /// Multidimensional array holding the basis functions and their derivatives for that + /// parameter. + /// + public static Matrix DerivativeBasisFunctions( + int span, + double param, + int degree, + int n, + IList knotVector) { + // INFO: This method is called 'DersBasisFuns' in the book. var ders = new Matrix(n + 1, degree + 1); var ndu = new double[degree + 1, degree + 1]; var a = new double[2, degree + 1]; @@ -278,14 +327,14 @@ public static Matrix DersBasisFuns(int span, double param, int degree, i ndu[0, 0] = 1.0; for (var j = 1; j <= degree; j++) { - left[j] = param - knotVector[(span + 1) - j]; + left[j] = param - knotVector[span + 1 - j]; right[j] = knotVector[span + j] - param; var saved = 0.0; for (var r = 0; r < j; r++) { ndu[j, r] = right[r + 1] + left[j - r]; var temp = ndu[r, j - 1] / ndu[j, r]; - ndu[r, j] = saved + (right[r + 1] * temp); + ndu[r, j] = saved + right[r + 1] * temp; saved = left[j - r] * temp; } @@ -346,6 +395,7 @@ public static Matrix DersBasisFuns(int span, double param, int degree, i return ders; } + /// /// Compute the basis function 'Nip'. /// @@ -355,9 +405,15 @@ public static Matrix DersBasisFuns(int span, double param, int degree, i /// Knot span index. /// Parameter to compute. /// - public static double OneBasisFun(int degree, int m, IList knotVector, int span, double param) + public static double OneBasisFun( + int degree, + int m, + IList knotVector, + int span, + double param) { - if ((span == 0 && param == knotVector[0]) || (span == m - degree - 1 && param == knotVector[m])) + if (span == 0 && param == knotVector[0] + || span == m - degree - 1 && param == knotVector[m]) return 1.0; if (param < knotVector[span] || param >= knotVector[span + degree + 1]) @@ -376,9 +432,10 @@ public static double OneBasisFun(int degree, int m, IList knotVector, in for (var k = 1; k <= degree; k++) { var saved = n[0] == 0.0 - ? 0.0 - : ((param - knotVector[span]) * n[0]) / (knotVector[span + k] - knotVector[span]); - for (var j = 0; j < (degree - k) + 1; j++) + ? 0.0 + : (param - knotVector[span]) * n[0] + / (knotVector[span + k] - knotVector[span]); + for (var j = 0; j < degree - k + 1; j++) { var uLeft = knotVector[span + j + 1]; var uRight = knotVector[span + j + k + 1]; @@ -390,7 +447,7 @@ public static double OneBasisFun(int degree, int m, IList knotVector, in else { var temp = n[j + 1] / (uRight - uLeft); - n[j] = saved + ((uRight - param) * temp); + n[j] = saved + (uRight - param) * temp; saved = (param - uLeft) * temp; } } @@ -399,6 +456,7 @@ public static double OneBasisFun(int degree, int m, IList knotVector, in return n[0]; } + /// /// Compute derivatives of basis function 'Nip'. /// @@ -409,7 +467,13 @@ public static double OneBasisFun(int degree, int m, IList knotVector, in /// /// /// - public static double[] DersOneBasisFun(int p, int m, IList knotVector, int i, double u, int n) + public static double[] DersOneBasisFun( + int p, + int m, + IList knotVector, + int i, + double u, + int n) { // TODO: Check unused m parameter. var ders = new double[n + 1]; @@ -433,9 +497,12 @@ public static double[] DersOneBasisFun(int p, int m, IList knotVector, i if (tmpN[0, k - 1] == 0.0) saved = 0.0; else - saved = ((u - knotVector[i]) * tmpN[0, k - 1]) / (knotVector[i + k] - knotVector[i]); + { + saved = (u - knotVector[i]) * tmpN[0, k - 1] + / (knotVector[i + k] - knotVector[i]); + } - for (var j = 0; j < (p - k) + 1; j++) + for (var j = 0; j < p - k + 1; j++) { var uLeft = knotVector[i + j + 1]; var uRight = knotVector[i + j + k + 1]; @@ -447,7 +514,7 @@ public static double[] DersOneBasisFun(int p, int m, IList knotVector, i else { var temp = tmpN[j + 1, k - 1] / (uRight - uLeft); - tmpN[j, k] = saved + ((uRight - u) * temp); + tmpN[j, k] = saved + (uRight - u) * temp; saved = (u - uLeft) * temp; } } @@ -467,20 +534,20 @@ public static double[] DersOneBasisFun(int p, int m, IList knotVector, i if (tempND[0] == 0.0) saved = 0.0; else - saved = tempND[0] / (knotVector[((i + p) - k) + jj] - knotVector[i]); - for (var j = 0; j < (k - jj) + 1; j++) + saved = tempND[0] / (knotVector[i + p - k + jj] - knotVector[i]); + for (var j = 0; j < k - jj + 1; j++) { var uLeft = knotVector[i + j + 1]; var uRight = knotVector[i + j + p + jj + 1]; if (tempND[j + 1] == 0.0) { - tempND[j] = ((p - k) + jj) * saved; + tempND[j] = (p - k + jj) * saved; saved = 0.0; } else { var temp = tempND[j + 1] / (uRight - uLeft); - tempND[j] = ((p - k) + jj) * (saved - temp); + tempND[j] = (p - k + jj) * (saved - temp); saved = temp; } } @@ -492,8 +559,9 @@ public static double[] DersOneBasisFun(int p, int m, IList knotVector, i return ders; } + /// - /// Computes a point on a nurbs curve. + /// Computes a point on a nurbs curve. /// /// /// @@ -501,16 +569,22 @@ public static double[] DersOneBasisFun(int p, int m, IList knotVector, i /// /// /// - public static Point3d CurvePoint(int n, int p, IList knotVector, IList controlPoints, double u) + public static Point3d CurvePoint( + int n, + int p, + IList knotVector, + IList controlPoints, + double u) { var span = FindSpan(n, p, u, knotVector); - var basisFuns = BasisFuns(span, u, p, knotVector); + var basisFuns = BasisFunctions(span, u, p, knotVector); var c = Point3d.Unset; for (var i = 0; i <= p; i++) - c += basisFuns[i] * controlPoints[(span - p) + i]; + c += basisFuns[i] * controlPoints[span - p + i]; return c; } + public static Vector3d[] CurveDerivsAlg1( int n, int p, @@ -524,17 +598,18 @@ public static Vector3d[] CurveDerivsAlg1( for (var k = p + 1; k <= d; k++) ck[k] = new Vector3d(); var span = FindSpan(n, p, u, knotVector); - var nders = DersBasisFuns(span, u, p, du, knotVector); + var nders = DerivativeBasisFunctions(span, u, p, du, knotVector); for (var k = 0; k <= du; k++) { ck[k] = new Vector3d(); for (var j = 0; j <= p; j++) - ck[k] += nders[k, j] * (Vector3d)controlPoints[(span - p) + j]; + ck[k] += nders[k, j] * ( Vector3d ) controlPoints[span - p + j]; } return ck; } + public static Point3d[,] CurveDerivCpts( int n, int p, @@ -551,10 +626,10 @@ public static Vector3d[] CurveDerivsAlg1( for (var k = 1; k <= d; k++) { - var tmp = (p - k) + 1; + var tmp = p - k + 1; for (var i = 0; i <= r - k; i++) { - pk[k, i] = (tmp * (Point3d)(pk[k - 1, i + 1] - pk[k - 1, i])) / + pk[k, i] = tmp * ( Point3d ) (pk[k - 1, i + 1] - pk[k - 1, i]) / (knotVector[r1 + i + p + 1] - knotVector[r1 + i + k]); } } @@ -562,6 +637,7 @@ public static Vector3d[] CurveDerivsAlg1( return pk; } + public static Vector3d[] CurveDerivsAlg2( int n, int p, @@ -576,21 +652,30 @@ public static Vector3d[] CurveDerivsAlg2( ck[k] = new Vector3d(); var span = FindSpan(n, p, u, knotVector); var basisFuns = AllBasisFuns(span, u, p, knotVector); - var pk = CurveDerivCpts(n, p, knotVector, controlPoints, du, span - p, span); + var pk = CurveDerivCpts( + n, + p, + knotVector, + controlPoints, + du, + span - p, + span); for (var k = 0; k <= du; k++) { ck[k] = new Vector3d(); for (var j = 0; j <= p - k; j++) - ck[k] += basisFuns[j, p - k] * (Vector3d)pk[k, j]; + ck[k] += basisFuns[j, p - k] * ( Vector3d ) pk[k, j]; } return ck; } + // B-Spline Surfaces + /// - /// Computes a point on a nurbs surface. + /// Computes a point on a nurbs surface. /// /// /// @@ -614,9 +699,9 @@ public static Point3d SurfacePoint( double v) { var uspan = FindSpan(n, p, u, knotVectorU); - var nU = BasisFuns(uspan, u, p, knotVectorU); + var nU = BasisFunctions(uspan, u, p, knotVectorU); var vspan = FindSpan(m, q, v, knotVectorV); - var nV = BasisFuns(vspan, v, q, knotVectorV); + var nV = BasisFunctions(vspan, v, q, knotVectorV); var uind = uspan - p; var surfPt = Point3d.Unset; for (var l = 0; l <= q; l++) @@ -631,6 +716,7 @@ public static Point3d SurfacePoint( return surfPt; } + public static Point3d[,] SurfaceDerivsAlg1( int n, int p, @@ -646,18 +732,22 @@ public static Point3d SurfacePoint( var sKL = new Point3d[derivCount + 1, derivCount + 1]; var du = Math.Min(derivCount, p); for (var k = p + 1; k <= derivCount; k++) - for (var l = 0; l <= derivCount - k; l++) - sKL[k, l] = Point3d.Unset; + { + for (var l = 0; l <= derivCount - k; l++) + sKL[k, l] = Point3d.Unset; + } var dv = Math.Min(derivCount, q); for (var l = q + 1; l <= derivCount; l++) - for (var k = 0; k <= derivCount - 1; k++) - sKL[k, l] = Point3d.Unset; + { + for (var k = 0; k <= derivCount - 1; k++) + sKL[k, l] = Point3d.Unset; + } var uSpan = FindSpan(n, p, u, knotVectorU); - var nU = DersBasisFuns(uSpan, u, p, du, knotVectorU); + var nU = DerivativeBasisFunctions(uSpan, u, p, du, knotVectorU); var vSpan = FindSpan(m, q, v, knotVectorV); - var nV = DersBasisFuns(vSpan, v, q, dv, knotVectorV); + var nV = DerivativeBasisFunctions(vSpan, v, q, dv, knotVectorV); for (var k = 0; k <= du; k++) { @@ -666,7 +756,7 @@ public static Point3d SurfacePoint( { temp[s] = Point3d.Unset; for (var r = 0; r <= p; r++) - temp[s] += nU[k, r] * controlPoints[(uSpan - p) + r, (vSpan - q) + s]; + temp[s] += nU[k, r] * controlPoints[uSpan - p + r, vSpan - q + s]; var dd = Math.Min(derivCount - k, dv); @@ -684,6 +774,7 @@ public static Point3d SurfacePoint( return sKL; } + public static Point3d[][][][] SurfaceDerivCpts( int n, int p, @@ -707,25 +798,46 @@ public static Point3d[][][][] SurfaceDerivCpts( for (var j = s1; j <= s2; j++) { - var temp = CurveDerivCpts(n, p, knotVectorU, controlPoints.Column(j), du, r1, r2); + var temp = CurveDerivCpts( + n, + p, + knotVectorU, + controlPoints.Column(j), + du, + r1, + r2); for (var k = 0; k <= du; k++) - for (var i = 0; i <= r - k; i++) - pkl[k][0][i][j - s1] = temp[k, i]; + { + for (var i = 0; i <= r - k; i++) + pkl[k][0][i][j - s1] = temp[k, i]; + } } for (var k = 0; k <= du; k++) - for (var i = 0; i <= r - k; i++) { - var dd = Math.Min(d - k, dv); - var temp = CurveDerivCpts(m, q, knotVectorV, pkl[k][0][i], dd, 0, s); - for (var l = i; k <= dd; k++) - for (var j = 0; j <= s - l; j++) - pkl[k][l][i][j] = temp[l, j]; + for (var i = 0; i <= r - k; i++) + { + var dd = Math.Min(d - k, dv); + var temp = CurveDerivCpts( + m, + q, + knotVectorV, + pkl[k][0][i], + dd, + 0, + s); + for (var l = i; k <= dd; k++) + { + for (var j = 0; j <= s - l; j++) + pkl[k][l][i][j] = temp[l, j]; + } + } } return pkl; } + public static Point3d[,] SurfaceDerivsAlg2( int n, int p, @@ -742,20 +854,35 @@ public static Point3d[][][][] SurfaceDerivCpts( var du = Math.Min(d, p); for (var k = p + 1; k <= d; k++) - for (var l = 0; l <= d - k; l++) - skl[k, l] = Point3d.Unset; + { + for (var l = 0; l <= d - k; l++) + skl[k, l] = Point3d.Unset; + } var dv = Math.Min(d, q); for (var l = q + 1; l <= d; l++) - for (var k = 0; k <= d - l; k++) - skl[k, l] = Point3d.Unset; + { + for (var k = 0; k <= d - l; k++) + skl[k, l] = Point3d.Unset; + } var uSpan = FindSpan(n, p, u, knotVectorU); var nV = AllBasisFuns(uSpan, u, p, knotVectorU); var vSpan = FindSpan(m, q, v, knotVectorV); var nU = AllBasisFuns(vSpan, v, q, knotVectorV); - var pkl = SurfaceDerivCpts(n, p, knotVectorU, m, q, knotVectorV, controlPoints, d, uSpan - p, uSpan, - vSpan - q, vSpan); + var pkl = SurfaceDerivCpts( + n, + p, + knotVectorU, + m, + q, + knotVectorV, + controlPoints, + d, + uSpan - p, + uSpan, + vSpan - q, + vSpan); for (var k = 0; k <= du; k++) { @@ -776,18 +903,25 @@ public static Point3d[][][][] SurfaceDerivCpts( return skl; } + // Nubs methods - public static Point4d CurvePoint(int n, int p, IList knotVector, IList controlPoints, double u) + public static Point4d CurvePoint( + int n, + int p, + IList knotVector, + IList controlPoints, + double u) { var span = FindSpan(n, p, u, knotVector); - var N = BasisFuns(span, u, p, knotVector); + var N = BasisFunctions(span, u, p, knotVector); var cw = new Point4d(); for (var j = 0; j <= p; j++) - cw += N[j] * controlPoints[(span - p) + j]; + cw += N[j] * controlPoints[span - p + j]; return cw / cw.Weight; } + /// /// Compute C(u) derivatives from Cw(u) derivatives. /// @@ -811,6 +945,7 @@ public static Vector3d[] RatCurveDerivs(IList aDers, IList wDe return ders; } + /// /// Compute a point on a nurbs surface. /// @@ -836,23 +971,23 @@ public static Point3d SurfacePoint( double v) { var uspan = FindSpan(n, p, u, knotVectorU); - var nU = BasisFuns(uspan, u, p, knotVectorU); + var nU = BasisFunctions(uspan, u, p, knotVectorU); var vspan = FindSpan(m, q, v, knotVectorV); - var nV = BasisFuns(vspan, v, q, knotVectorV); + var nV = BasisFunctions(vspan, v, q, knotVectorV); var temp = new Point4d[q]; for (var l = 0; l <= q; l++) { temp[l] = new Point4d(); for (var k = 0; k <= p; k++) - temp[l] += nU[k] * controlPoints[(uspan - p) + k, (vspan - q) + l]; + temp[l] += nU[k] * controlPoints[uspan - p + k, vspan - q + l]; } var sW = new Point4d(); for (var l = 0; l <= q; l++) sW += nV[l] * temp[l]; - return (Point3d)(sW / sW.Weight); + return ( Point3d ) (sW / sW.Weight); } } } \ No newline at end of file diff --git a/src/Geometry/3D/Nurbs/NurbsCurve.cs b/src/Geometry/3D/Nurbs/NurbsCurve.cs index 574fc5c..787285e 100644 --- a/src/Geometry/3D/Nurbs/NurbsCurve.cs +++ b/src/Geometry/3D/Nurbs/NurbsCurve.cs @@ -8,10 +8,27 @@ namespace Paramdigma.Core.Geometry /// public class NurbsCurve : BaseCurve { + /// + /// The control points of the nurbs curve. + /// public List ControlPoints; + + /// + /// The degree of the curve. + /// public int Degree; + + /// + /// The nurbs curve knot vector. + /// public List Knots; + + /// + /// Initializes a new instance of by it's control points and degree. + /// + /// The control points to create the curve with. + /// The desired degree of the curve. Degree cannot be > (ControlPoints - 1) public NurbsCurve(List controlPoints, int degree) { this.ControlPoints = controlPoints; @@ -19,10 +36,11 @@ public NurbsCurve(List controlPoints, int degree) this.Degree = degree; } + /// /// Gets the count of the control points - 1. /// - private int n => this.ControlPoints.Count - 1; + private int N => this.ControlPoints.Count - 1; /// /// The start point of the curve. @@ -44,6 +62,7 @@ public NurbsCurve(List controlPoints, int degree) /// public Vector3d EndTangent => this.TangentAt(this.Domain.End); + /// /// Computes the specific amount of derivatives on the specified parameter. /// @@ -52,7 +71,7 @@ public NurbsCurve(List controlPoints, int degree) /// Array containing the private IList DerivativesAt(double t, int count) => NurbsCalculator.CurveDerivsAlg1( - this.n, + this.N, this.Degree, this.Knots, this.ControlPoints, @@ -63,27 +82,33 @@ private IList DerivativesAt(double t, int count) => /// public override Point3d PointAt(double t) => - NurbsCalculator.CurvePoint(this.n, this.Degree, this.Knots, this.ControlPoints, t); + NurbsCalculator.CurvePoint(this.N, this.Degree, this.Knots, this.ControlPoints, t); + /// public override Vector3d TangentAt(double t) => this.DerivativesAt(t, 1)[1].Unit(); + /// public override Vector3d NormalAt(double t) => this.DerivativesAt(t, 2)[2].Unit(); + /// public override Vector3d BinormalAt(double t) => this.DerivativesAt(t, 3)[3].Unit(); + /// public override Plane FrameAt(double t) { var ders = this.DerivativesAt(t, 3); - return new Plane((Point3d)ders[0], ders[1], ders[2], ders[3]); + return new Plane(( Point3d ) ders[0], ders[1], ders[2], ders[3]); } + /// public override bool CheckValidity() => true; + /// protected override double ComputeLength() => throw new NotImplementedException(); } diff --git a/src/Geometry/3D/Plane.cs b/src/Geometry/3D/Plane.cs index f48da6a..44be5d2 100644 --- a/src/Geometry/3D/Plane.cs +++ b/src/Geometry/3D/Plane.cs @@ -15,7 +15,12 @@ public class Plane /// /// Plane to copy values from. public Plane(Plane plane) - : this(new Point3d(plane.Origin), new Vector3d(plane.XAxis), new Vector3d(plane.YAxis), new Vector3d(plane.ZAxis)) { } + : this( + new Point3d(plane.Origin), + new Vector3d(plane.XAxis), + new Vector3d(plane.YAxis), + new Vector3d(plane.ZAxis)) { } + /// /// Initializes a new instance of the class given it's origin at the specified point. @@ -24,6 +29,7 @@ public Plane(Plane plane) public Plane(Point3d origin) : this(origin, Vector3d.UnitX, Vector3d.UnitY) { } + /// /// Initializes a new instance of the class given a point and two vectors. /// Vectors do not necessarily have to be perpendicular. @@ -35,6 +41,7 @@ public Plane(Point3d origin) public Plane(Point3d origin, Vector3d xAxis, Vector3d yAxis) : this(origin, xAxis, yAxis, xAxis.Cross(yAxis)) { } + /// /// Initializes a new instance of the class given a point and three vectors. /// Will throw an error if vectors are not perpendicular to each other. @@ -51,6 +58,7 @@ public Plane(Point3d origin, Vector3d xAxis, Vector3d yAxis, Vector3d zAxis) this.ZAxis = zAxis; } + /// /// Initializes a new instance of the class given 3 non co-linear points. /// @@ -77,66 +85,61 @@ public Plane(Point3d ptA, Point3d ptB, Point3d ptC) this.ZAxis = normal; } + /// /// Gets or sets the plane origin. /// /// - public Point3d Origin - { - get; - set; - } + public Point3d Origin { get; set; } /// /// Gets or sets the plane X axis. /// /// - public Vector3d XAxis - { - get; - set; - } + public Vector3d XAxis { get; set; } /// /// Gets or sets the plane Y axis. /// /// - public Vector3d YAxis - { - get; - set; - } + public Vector3d YAxis { get; set; } /// /// Gets or sets the plane Z axis. /// /// - public Vector3d ZAxis - { - get; - set; - } + public Vector3d ZAxis { get; set; } /// /// Gets plane with axis' UnitX and UnitY. /// /// - public static Plane WorldXY => new Plane(Point3d.WorldOrigin, Vector3d.UnitX, Vector3d.UnitY); + public static Plane WorldXY => new Plane( + Point3d.WorldOrigin, + Vector3d.UnitX, + Vector3d.UnitY); /// /// Gets plane with axis' UnitX and UnitZ. /// /// - public static Plane WorldXZ => new Plane(Point3d.WorldOrigin, Vector3d.UnitX, Vector3d.UnitZ); + public static Plane WorldXZ => new Plane( + Point3d.WorldOrigin, + Vector3d.UnitX, + Vector3d.UnitZ); /// /// Gets plane with axis' UnitY and UnitZ. /// /// - public static Plane WorldYZ => new Plane(Point3d.WorldOrigin, Vector3d.UnitY, Vector3d.UnitZ); + public static Plane WorldYZ => new Plane( + Point3d.WorldOrigin, + Vector3d.UnitY, + Vector3d.UnitZ); // TODO: Add utility methods to Plane class (flip Axis, relative coordinates...) + /// /// Flips the plane by interchanging the X and Y axis and negating the Z axis. /// @@ -148,6 +151,7 @@ public void Flip() this.ZAxis = -this.ZAxis; } + /// /// Computes the point at the specified Plane parameters. /// @@ -156,6 +160,7 @@ public void Flip() /// public Point3d PointAt(double u, double v) => this.PointAt(u, v, 0); + /// /// Computes a 3D point in the coordinate space of this plane. /// @@ -163,7 +168,9 @@ public void Flip() /// Coordinate for the Y axis. /// Coordinate for the Z axis. /// Computed point. - public Point3d PointAt(double u, double v, double w) => this.Origin + ((u * this.XAxis) + (v * this.YAxis) + (w * this.ZAxis)); + public Point3d PointAt(double u, double v, double w) => + this.Origin + ((u * this.XAxis) + (v * this.YAxis) + (w * this.ZAxis)); + /// /// Remap a given point to this plane's coordinate system. @@ -180,12 +187,15 @@ public Point3d RemapToPlaneSpace(Point3d point) return new Point3d(u, v, w); } + /// /// Remap a given point to the XY Plane coordiante system. /// /// Point to remap. /// Point with relative coordinates to the plane. - public Point3d RemapToWorldXYSpace(Point3d point) => this.Origin + (point.X * this.XAxis) + (point.Y * this.YAxis) + (point.Z * this.ZAxis); + public Point3d RemapToWorldXYSpace(Point3d point) => + this.Origin + (point.X * this.XAxis) + (point.Y * this.YAxis) + (point.Z * this.ZAxis); + /// /// Project a point to the plane. @@ -201,6 +211,7 @@ public Point3d ClosestPoint(Point3d point) return this.PointAt(u, v); } + /// /// Compute the distance from a point to the plane. /// @@ -208,36 +219,45 @@ public Point3d ClosestPoint(Point3d point) /// Distance to point. public double DistanceTo(Point3d point) => (point - this.Origin).Dot(this.ZAxis); + /// /// Returns the parametric equation for this plane. /// /// List with equation values. public double[] GetPlaneEquation() => throw new NotImplementedException(); + /// /// Performs a deep copy of this plane. /// /// Plane clone. - public Plane Clone() => new Plane(new Point3d(this.Origin), new Vector3d(this.XAxis), new Vector3d(this.YAxis), new Vector3d(this.ZAxis)); + public Plane Clone() => new Plane( + new Point3d(this.Origin), + new Vector3d(this.XAxis), + new Vector3d(this.YAxis), + new Vector3d(this.ZAxis)); + + /// public override bool Equals(object obj) { if (!(obj is Plane)) return false; - var plane = (Plane)obj; + var plane = ( Plane ) obj; return plane.Origin == this.Origin && plane.XAxis == this.XAxis && plane.YAxis == this.YAxis; } + /// public override int GetHashCode() { unchecked { // Choose large primes to avoid hashing collisions - const int hashingBase = (int)2166136261; + const int hashingBase = ( int ) 2166136261; const int hashingMultiplier = 16777619; var hash = hashingBase; diff --git a/src/Geometry/3D/Point3d.cs b/src/Geometry/3D/Point3d.cs index 63ca23d..85a69af 100644 --- a/src/Geometry/3D/Point3d.cs +++ b/src/Geometry/3D/Point3d.cs @@ -13,6 +13,7 @@ public class Point3d : BasePoint /// . public Point3d() { } + /// /// Initializes a new instance of the class by cartesian coordinates. /// @@ -23,6 +24,7 @@ public Point3d() { } public Point3d(double xCoord, double yCoord, double zCoord) : base(xCoord, yCoord, zCoord) { } + /// /// Initializes a new instance of the class from a 2-dimensional point. /// @@ -31,6 +33,7 @@ public Point3d(double xCoord, double yCoord, double zCoord) public Point3d(Point2d point) : base(point.X, point.Y, 0) { } + /// /// Initializes a new instance of the class. /// @@ -39,8 +42,10 @@ public Point3d(Point2d point) public Point3d(Point3d point) : base(point) { } + /// - /// Initializes a new instance of the class from a 4-dimensional point by dividing the cartesian + /// Initializes a new instance of the class from a 4-dimensional point by + /// dividing the cartesian /// coordinates by the weight. /// /// 4d point to convert. @@ -48,6 +53,7 @@ public Point3d(Point3d point) public Point3d(Point4d point) : this(point.X / point.Weight, point.Y / point.Weight, point.Z / point.Weight) { } + /// /// Gets a new Unset point. /// @@ -60,18 +66,23 @@ 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. /// /// Point. /// - public double DistanceTo(Point3d point) => Math.Sqrt(Math.Pow(point.X - this.X, 2) + Math.Pow(point.Y - this.Y, 2) + Math.Pow(point.Z - this.Z, 2)); + public double DistanceTo(Point3d point) => Math.Sqrt( + Math.Pow(point.X - this.X, 2) + Math.Pow(point.Y - this.Y, 2) + + Math.Pow(point.Z - this.Z, 2)); + /// public override bool Equals(object obj) => base.Equals(obj); @@ -79,16 +90,22 @@ public Point3d(Point4d point) /// public override int GetHashCode() => base.GetHashCode(); + /// public override string ToString() => "Point3d" + base.ToString(); + /// /// Adds a vector to a point. /// /// Point. /// Vector. /// . - public static Point3d operator +(Point3d point, Vector3d v) => new Point3d(point.X + v.X, point.Y + v.Y, point.Z + v.Z); + public static Point3d operator +(Point3d point, Vector3d v) => new Point3d( + point.X + v.X, + point.Y + v.Y, + point.Z + v.Z); + /// /// Substracts a point from another point. @@ -96,7 +113,11 @@ public Point3d(Point4d point) /// Point A. /// Point B. /// . - public static Vector3d operator -(Point3d point, Point3d point2) => new Vector3d(point.X - point2.X, point.Y - point2.Y, point.Z - point2.Z); + public static Vector3d operator -(Point3d point, Point3d point2) => new Vector3d( + point.X - point2.X, + point.Y - point2.Y, + point.Z - point2.Z); + /// /// Substracts a vector from a point. @@ -104,7 +125,11 @@ public Point3d(Point4d point) /// Point. /// Vector. /// . - public static Vector3d operator -(Point3d point, Vector3d vector) => new Vector3d(point.X - vector.X, point.Y - vector.Y, point.Z - vector.Z); + public static Vector3d operator -(Point3d point, Vector3d vector) => new Vector3d( + point.X - vector.X, + point.Y - vector.Y, + point.Z - vector.Z); + /// /// Negates a point. @@ -117,13 +142,18 @@ public Point3d(Point4d point) point.Y != 0 ? -point.Y : 0, point.Z != 0 ? -point.Z : 0); + /// /// Multiplies a point with a number. /// /// Point. /// Number. /// . - public static Point3d operator *(Point3d point, double scalar) => new Point3d(point.X * scalar, point.Y * scalar, point.Z * scalar); + public static Point3d operator *(Point3d point, double scalar) => new Point3d( + point.X * scalar, + point.Y * scalar, + point.Z * scalar); + /// /// Multiplies a point with a number. @@ -131,7 +161,11 @@ public Point3d(Point4d point) /// Number. /// Point. /// . - public static Point3d operator *(double scalar, Point3d point) => new Point3d(point.X * scalar, point.Y * scalar, point.Z * scalar); + public static Point3d operator *(double scalar, Point3d point) => new Point3d( + point.X * scalar, + point.Y * scalar, + point.Z * scalar); + /// /// Divides a point with a number. @@ -139,7 +173,12 @@ public Point3d(Point4d point) /// Point. /// Number. /// . - public static Point3d operator /(Point3d point, double scalar) => new Point3d(point.X / scalar, point.Y / scalar, point.Z / scalar); + public static Point3d operator /(Point3d point, double scalar) => + new Point3d( + point.X / scalar, + point.Y / scalar, + point.Z / scalar); + /// /// Checks equality between two points. @@ -147,7 +186,9 @@ public Point3d(Point4d point) /// Point A. /// Point B. /// . - public static bool operator ==(Point3d point, Point3d point2) => point != null && point.Equals(point2); + public static bool operator ==(Point3d point, Point3d point2) => + point != null && point.Equals(point2); + /// /// Checks inequality between two points. @@ -155,26 +196,34 @@ public Point3d(Point4d point) /// Point A. /// Point B. /// . - public static bool operator !=(Point3d point, Point3d point2) => !point.Equals(point2); + public static bool operator !=(Point3d point, Point3d point2) => + !point?.Equals(point2) ?? true; + // Implicit conversions + /// /// Explicit conversion from vector to point. /// /// 3d Vector to convert. - public static explicit operator Point3d(Vector3d v) => new Point3d(v.X, v.Y, v.Z); + public static explicit operator Point3d(Vector3d v) => + new Point3d(v.X, v.Y, v.Z); + /// /// Implicit conversion from point to vector. /// /// 3d Point to convert. - public static implicit operator Vector3d(Point3d pt) => new Vector3d(pt.X, pt.Y, pt.Z); + public static implicit operator Vector3d(Point3d pt) => + new Vector3d(pt.X, pt.Y, pt.Z); + /// /// Explicit conversion from 4-dimensional point to 3-dimensional point. (X/W,Y/W,Z/W). /// /// 3d Point to convert. - public static explicit operator Point3d(Point4d point) => new Point3d(point); + public static explicit operator Point3d(Point4d point) => + new Point3d(point); } } \ No newline at end of file diff --git a/src/Geometry/3D/Point4d.cs b/src/Geometry/3D/Point4d.cs index a9f239c..868f140 100644 --- a/src/Geometry/3D/Point4d.cs +++ b/src/Geometry/3D/Point4d.cs @@ -9,14 +9,17 @@ public class Point4d : BasePoint { private double weight; + /// /// Initializes a new instance of the class. /// /// Point with all values to zero. public Point4d() => this.weight = 0; + /// - /// Initializes a new instance of the class by cartesian coordinates and weight. + /// Initializes a new instance of the class by cartesian coordinates and + /// weight. /// /// X Coordinate. /// Y Coordinate. @@ -27,8 +30,10 @@ public Point4d(double x, double y, double z, double w) : base(x, y, z) => this.weight = w; + /// - /// Initializes a new instance of the class from a 3-dimensional point and a weight. + /// Initializes a new instance of the class from a 3-dimensional point and a + /// weight. /// /// Point. /// Weight. @@ -37,8 +42,10 @@ public Point4d(Point3d pt, double w) : base(pt) => this.weight = w; + /// - /// Initializes a new instance of the class from a 3-dimensional point and a weight. + /// Initializes a new instance of the class from a 3-dimensional point and a + /// weight. /// /// Point. /// New 4-dimensional point with the specified values. @@ -46,6 +53,7 @@ public Point4d(Point3d pt) : base(pt) => this.weight = 1; + /// /// Gets or sets the weight of this point. /// @@ -65,47 +73,136 @@ public double Weight /// public Point3d Position => new Point3d(this.X, this.Y, this.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); - /// - 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); + /// + /// Adds to points together. + /// + /// First point to add. + /// Second point to add. + /// A new instance. + 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); - /// - public static Point4d operator -(Point4d point) => new Point4d(-point.X, -point.Y, -point.Z, point.Weight); - /// - public static Point4d operator *(Point4d point, double scalar) => new Point4d(point.X * scalar, point.Y * scalar, point.Z * scalar, point.Weight * scalar); + /// + /// Subtracts one point from another. + /// + /// Point to subtract from. + /// Point to be subtracted. + /// A new instance. + 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); - /// - public static Point4d operator *(double scalar, Point4d point) => new Point4d(point.X * scalar, point.Y * scalar, point.Z * scalar, point.Weight * scalar); - /// - public static Point4d operator /(Point4d point, double scalar) => new Point4d(point.X / scalar, point.Y / scalar, point.Z / scalar, point.Weight / scalar); + /// + /// Negates a point. + /// + /// Point to be negated. + /// A new instance. + public static Point4d operator -(Point4d point) => new Point4d( + -point.X, + -point.Y, + -point.Z, + point.Weight); - /// - public static bool operator ==(Point4d point, Point4d point2) => point.Equals(point2); - /// - public static bool operator !=(Point4d point, Point4d point2) => !point.Equals(point2); + /// + /// Multiply a point by a scalar. + /// + /// Point to be multiplied. + /// Number to multiply point with. + /// A new instance. + public static Point4d operator *(Point4d point, double scalar) => new Point4d( + point.X * scalar, + point.Y * scalar, + point.Z * scalar, + point.Weight * scalar); + + + /// + /// Multiply a point by a scalar. + /// + /// Number to multiply point with. + /// Point to be multiplied. + /// A new instance. + public static Point4d operator *(double scalar, Point4d point) => new Point4d( + point.X * scalar, + point.Y * scalar, + point.Z * scalar, + point.Weight * scalar); + + + /// + /// Divides a point by a scalar value. + /// + /// Point to divide. + /// Number to divide point with. + /// A new instance. + public static Point4d operator /(Point4d point, double scalar) => new Point4d( + point.X / scalar, + point.Y / scalar, + point.Z / scalar, + point.Weight / scalar); + + + /// + /// Equality check between two instances. + /// + /// Point to check equality from. + /// Point to check equality to. + /// True if points are equal. + public static bool operator ==(Point4d point, Point4d point2) => + point?.Equals(point2) ?? false; + + + /// + /// Inequality check between two instances. + /// + /// Point to check inequality from. + /// Point to check inequality to. + /// True if points are NOT equal. + public static bool operator !=(Point4d point, Point4d point2) => + !point?.Equals(point2) ?? true; + + + /// + /// Adds a vector and a point. + /// + /// A 4d point + /// A 3d vector + /// A new instance with the resulting coordinates. + public static Point4d operator +(Point4d point, Vector3d v) => new Point4d( + point.X + v.X, + point.Y + v.Y, + point.Z + v.Z, + point.Weight); - /// - public static Point4d operator +(Point4d point, Vector3d v) => new Point4d(point.X + v.X, point.Y + v.Y, point.Z + v.Z, point.Weight); /// public override bool Equals(object obj) { if (obj is Point4d pt) + { return base.Equals(obj) && Math.Abs(this.Weight - pt.Weight) < Settings.Tolerance; + } + return false; } + /// public override int GetHashCode() => // TODO: Non consistent getHashCode implementation base.GetHashCode() ^ this.weight.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 83f4673..e1d097d 100644 --- a/src/Geometry/3D/Polyline.cs +++ b/src/Geometry/3D/Polyline.cs @@ -16,6 +16,7 @@ public class Polyline : BaseCurve, IEnumerable private List segments; private bool segmentsNeedUpdate; + /// /// Initializes a new instance of the class. /// @@ -26,6 +27,7 @@ public Polyline() this.segmentsNeedUpdate = false; } + /// /// Initializes a new instance of the class from a list of points. /// @@ -37,6 +39,7 @@ public Polyline(List knots) this.RebuildSegments(); } + /// /// Gets the segment lines of the polyline. /// @@ -60,10 +63,7 @@ public List Segments /// /// Gets the list of knots for this polyline. /// - public List Knots - { - get; - } + public List Knots { get; } /// /// Gets a value indicating whether the polyline is closed (first point == last point). @@ -75,11 +75,16 @@ public List Knots /// public bool IsUnset => this.Knots.Count == 0; + /// - public IEnumerator GetEnumerator() => ((IEnumerable)this.Knots).GetEnumerator(); + public IEnumerator GetEnumerator() => + (( IEnumerable ) this.Knots).GetEnumerator(); + /// - IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this.Knots).GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => + (( IEnumerable ) this.Knots).GetEnumerator(); + /// /// Add a new knot vertex at the end of the polyline. @@ -91,6 +96,7 @@ public void AddKnot(Point3d knot) this.segmentsNeedUpdate = true; } + /// /// Add a new knot vertex at the specified index. /// @@ -102,6 +108,7 @@ public void InsertKnot(Point3d knot, int index) this.segmentsNeedUpdate = true; } + /// /// Delete a specific knot if it exists in the polyline. /// If the point exists multiple times, it will remove the first occurrence. @@ -115,6 +122,7 @@ public void RemoveKnot(Point3d knot) this.segmentsNeedUpdate = true; } + /// /// Delete a knot at a specific index. /// @@ -129,6 +137,7 @@ public void RemoveKnotAt(int index) this.segmentsNeedUpdate = true; } + private void RebuildSegments() { this.segments = new List(this.Knots.Count - 1); @@ -144,30 +153,45 @@ private void RebuildSegments() } } - /// - 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) => (from segment in this.segments - where segment.Domain.Contains(t) - select segment.NormalAt(t)).FirstOrDefault(); + public override Vector3d BinormalAt(double t) => ( + from segment in this.segments + where segment.Domain.Contains(t) + select segment.BinormalAt(t)) + .FirstOrDefault(); + /// - public override Point3d PointAt(double t) => (from segment in this.segments - where segment.Domain.Contains(t) - select segment.PointAt(t)).FirstOrDefault(); + public override Vector3d NormalAt(double t) => ( + from segment in this.segments + where segment.Domain.Contains(t) + select segment.NormalAt(t)) + .FirstOrDefault(); + /// - public override Vector3d TangentAt(double t) => (from segment in this.segments + public override Point3d PointAt(double t) => ( + from segment in this.segments where segment.Domain.Contains(t) - select segment.TangentAt(t)).FirstOrDefault(); + select segment.PointAt(t)) + .FirstOrDefault(); + /// - public override Plane FrameAt(double t) => (from segment in this.segments - where segment.Domain.Contains(t) - select segment.FrameAt(t)).FirstOrDefault(); + 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) => ( + from segment in this.segments + where segment.Domain.Contains(t) + select segment.FrameAt(t)).FirstOrDefault(); + /// protected override double ComputeLength() @@ -177,8 +201,10 @@ protected override double ComputeLength() return length; } + /// - /// Checks the validity of the polyline. Currently only checks if some segments are collapsed (length == 0). + /// 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() diff --git a/src/Geometry/3D/Primitives/Box.cs b/src/Geometry/3D/Primitives/Box.cs index 6fe43ac..5fe3ae8 100644 --- a/src/Geometry/3D/Primitives/Box.cs +++ b/src/Geometry/3D/Primitives/Box.cs @@ -22,8 +22,10 @@ public Box(Plane plane, Interval domainX, Interval domainY, Interval domainZ) this.DomainZ = domainZ; } + /// - /// Initializes a new instance of the class from 2 corners. Both corners will form the diagonal of + /// Initializes a new instance of the class from 2 corners. Both corners will + /// form the diagonal of /// the box. /// /// Lower left corner point. @@ -36,51 +38,39 @@ public Box(Point3d lower, Point3d upper) this.DomainZ = new Interval(lower.Z, upper.Z); } + /// /// Gets or sets the box's base plane. /// /// . - public Plane Plane - { - get; - set; - } + public Plane Plane { get; set; } /// /// Gets or sets the box's X axis domain. /// /// . - public Interval DomainX - { - get; - set; - } + public Interval DomainX { get; set; } /// /// Gets or sets the box's Y axis domain. /// /// . - public Interval DomainY - { - get; - set; - } + public Interval DomainY { get; set; } /// /// Gets or sets the box's Z axis domain. /// /// . - public Interval DomainZ - { - get; - set; - } + public Interval DomainZ { get; set; } /// /// Gets the corner point with lowest values. /// /// . - public Point3d Min => new Point3d(this.DomainX.Start, this.DomainY.Start, this.DomainZ.Start); + public Point3d Min => new Point3d( + this.DomainX.Start, + this.DomainY.Start, + this.DomainZ.Start); /// /// Gets the corner point with highest values. @@ -92,6 +82,9 @@ public Interval DomainZ /// Gets the center point of the box. /// /// . - public Point3d Center => new Point3d(this.DomainX.RemapFromUnit(0.5), this.DomainY.RemapFromUnit(0.5), this.DomainZ.RemapFromUnit(0.5)); + public Point3d Center => new Point3d( + this.DomainX.RemapFromUnit(0.5), + this.DomainY.RemapFromUnit(0.5), + this.DomainZ.RemapFromUnit(0.5)); } } \ No newline at end of file diff --git a/src/Geometry/3D/Primitives/Cylinder.cs b/src/Geometry/3D/Primitives/Cylinder.cs index 1eb00b3..4856d0b 100644 --- a/src/Geometry/3D/Primitives/Cylinder.cs +++ b/src/Geometry/3D/Primitives/Cylinder.cs @@ -10,7 +10,8 @@ namespace Paramdigma.Core.Geometry public class Cylinder : ISurface { /// - /// Initializes a new instance of the class from it's individual components. + /// Initializes a new instance of the class from it's individual + /// components. /// /// The plane of the cylinder. /// The radius of the cylinder. @@ -31,35 +32,24 @@ public Cylinder(Plane plane, double radius, Interval domain) this.DomainV = Interval.Unit; } + /// /// Gets or sets the base plane of the cylinder. /// /// . - public Plane Plane - { - get; - set; - } + public Plane Plane { get; set; } /// /// Gets or sets the radius of the cylinder. /// /// . - public double Radius - { - get; - set; - } + public double Radius { get; set; } /// /// Gets or sets the height range of the cylinder. /// /// . - public Interval HeightRange - { - get; - set; - } + public Interval HeightRange { get; set; } /// /// Gets the cylinder height. @@ -67,18 +57,11 @@ public Interval HeightRange public double Height => this.HeightRange.Length; /// - public Interval DomainU - { - get; - set; - } + public Interval DomainU { get; set; } /// - public Interval DomainV - { - get; - set; - } + public Interval DomainV { get; set; } + /// public Plane FrameAt(double u, double v) @@ -87,6 +70,7 @@ public Plane FrameAt(double u, double v) throw new NotImplementedException(); } + /// /// Compute the distance from a point to this cylinder. /// @@ -94,6 +78,7 @@ public Plane FrameAt(double u, double v) /// Number representing the distance. public double DistanceTo(Point3d point) => throw new NotImplementedException(); + /// /// Compute the closes point of a point in this cylinder. /// @@ -101,6 +86,7 @@ public Plane FrameAt(double u, double v) /// Point3d instance of the closest point in the cylinder. public Point3d ClosestPointTo(Point3d point) => throw new NotImplementedException(); + /// public Vector3d NormalAt(double u, double v) { @@ -108,6 +94,7 @@ public Vector3d NormalAt(double u, double v) throw new NotImplementedException(); } + /// public Point3d PointAt(double u, double v) { @@ -122,6 +109,7 @@ public Point3d PointAt(double u, double v) return this.Plane.PointAt(x, y, z); } + private void CheckParameters(double u, double v) { if (!this.DomainU.Contains(u)) diff --git a/src/Geometry/3D/Primitives/Sphere.cs b/src/Geometry/3D/Primitives/Sphere.cs index 7af9a30..1693529 100644 --- a/src/Geometry/3D/Primitives/Sphere.cs +++ b/src/Geometry/3D/Primitives/Sphere.cs @@ -9,6 +9,12 @@ namespace Paramdigma.Core.Geometry /// public class Sphere : ISurface { + /// + /// Initializes a new instance of given it's base plane and radius. + /// + /// + /// + /// Throws when radius is smaller than 0. public Sphere(Plane plane, double radius) { if (Math.Abs(radius) < Settings.Tolerance) @@ -19,53 +25,49 @@ public Sphere(Plane plane, double radius) this.DomainV = Interval.Unit; } + + /// + /// Initializes a new instance of around the World origin with unit radius. + /// public Sphere() : this(Plane.WorldXY, 1) { } + /// /// Gets or sets the base plane of the sphere. /// /// . - public Plane Plane - { - get; - set; - } + public Plane Plane { get; set; } /// /// Gets or sets the radius of the sphere. /// /// . - public double Radius - { - get; - set; - } + public double Radius { get; set; } /// - public Interval DomainU - { - get; - set; - } + public Interval DomainU { get; set; } /// - public Interval DomainV - { - get; - set; - } + public Interval DomainV { get; set; } + /// - public double DistanceTo(Point3d point) => this.Plane.Origin.DistanceTo(point) - this.Radius; + public double DistanceTo(Point3d point) => + this.Plane.Origin.DistanceTo(point) - this.Radius; + /// - public Point3d ClosestPointTo(Point3d point) => this.Plane.Origin + ((point - this.Plane.Origin).Unit() * this.Radius); + public Point3d ClosestPointTo(Point3d point) => + this.Plane.Origin + (point - this.Plane.Origin).Unit() * this.Radius; + /// public Plane FrameAt(double u, double v) => throw new NotImplementedException(); + /// - public Vector3d NormalAt(double u, double v) => (this.PointAt(u, v) - this.Plane.Origin).Unit(); + public Vector3d NormalAt(double u, double v) => + (this.PointAt(u, v) - this.Plane.Origin).Unit(); /// @@ -80,6 +82,7 @@ public Point3d PointAt(double u, double v) return this.Plane.PointAt(x, y, z); } + /// /// Returns the closest point on the sphere as a 2D point containing it's UV coordinates. /// @@ -88,12 +91,13 @@ public Point3d PointAt(double u, double v) public Point2d ClosestParam(Point3d pt) { var rho = Math.Atan(pt.Y / pt.X); - var tau = Math.Atan(Math.Sqrt((pt.X * pt.X) + (pt.Y * pt.Y)) / pt.Z); + var tau = Math.Atan(Math.Sqrt(pt.X * pt.X + pt.Y * pt.Y) / pt.Z); var u = new Interval(0, 2 * Math.PI).RemapToUnit(rho); var v = new Interval(0, Math.PI).RemapToUnit(tau); return new Point2d(u, v); } + /// /// Computes the point at a specified parameter, provided as a instance. /// diff --git a/src/Geometry/3D/Primitives/Torus.cs b/src/Geometry/3D/Primitives/Torus.cs index 1d85855..6f0eeb6 100644 --- a/src/Geometry/3D/Primitives/Torus.cs +++ b/src/Geometry/3D/Primitives/Torus.cs @@ -22,62 +22,48 @@ public Torus(Plane plane, double majorRadius, double minorRadius) this.MinorRadius = minorRadius; } + /// /// Gets or sets the torus base plane. /// /// . - public Plane Plane - { - get; - set; - } + public Plane Plane { get; set; } /// /// Gets or sets the torus major radius. /// /// . - public double MajorRadius - { - get; - set; - } + public double MajorRadius { get; set; } /// /// Gets or sets the torus minor radius. /// /// . - public double MinorRadius - { - get; - set; - } + public double MinorRadius { get; set; } /// - public Interval DomainU - { - get; - set; - } + public Interval DomainU { get; set; } /// - public Interval DomainV - { - get; - set; - } + public Interval DomainV { get; set; } + /// public Plane FrameAt(double u, double v) => throw new NotImplementedException(); + /// public double DistanceTo(Point3d point) => throw new NotImplementedException(); + /// public Point3d ClosestPointTo(Point3d point) => throw new NotImplementedException(); + /// public Vector3d NormalAt(double u, double v) => throw new NotImplementedException(); + /// public Point3d PointAt(double u, double v) => throw new NotImplementedException(); } diff --git a/src/Geometry/3D/Ray.cs b/src/Geometry/3D/Ray.cs index e9cf317..d107daa 100644 --- a/src/Geometry/3D/Ray.cs +++ b/src/Geometry/3D/Ray.cs @@ -18,29 +18,23 @@ public Ray(Point3d origin, Vector3d direction) this.Direction = direction ?? throw new ArgumentNullException(nameof(direction)); } + /// /// Gets or sets the origin point of the ray. /// - public Point3d Origin - { - get; - set; - } + public Point3d Origin { get; set; } /// /// Gets or sets the direction vector of the ray. /// - public Vector3d Direction - { - get; - set; - } + public Vector3d Direction { get; set; } + /// /// Computes a point in the ray at the given parameter. /// /// Parameter to obtain point. /// Returns a point at the specified parameter of the Ray. - public Point3d PointAt(double t) => this.Origin + (t * this.Direction); + public Point3d PointAt(double t) => this.Origin + t * this.Direction; } } \ No newline at end of file diff --git a/src/Geometry/3D/Vector3d.cs b/src/Geometry/3D/Vector3d.cs index 2a41455..344eca8 100644 --- a/src/Geometry/3D/Vector3d.cs +++ b/src/Geometry/3D/Vector3d.cs @@ -12,13 +12,16 @@ public class Vector3d : BasePoint /// public Vector3d() { } + /// - /// Initializes a new instance of the class with the same values as the provided vector. + /// Initializes a new instance of the class with the same values as the + /// provided vector. /// /// Vector to copy values from. public Vector3d(Vector3d vector) : base(vector) { } + /// /// Initializes a new instance of the class from a v. /// @@ -27,6 +30,7 @@ public Vector3d(Vector3d vector) public Vector3d(Point3d point) : base(point) { } + /// /// Initializes a new instance of the class given it's 3 coordinates. /// @@ -37,6 +41,7 @@ public Vector3d(Point3d point) public Vector3d(double xCoord, double yCoord, double zCoord) : base(xCoord, yCoord, zCoord) { } + /// /// Gets the Euclidean length squared of this vector. /// @@ -67,6 +72,7 @@ public Vector3d(double xCoord, double yCoord, double zCoord) /// Vector {0,1,0}. public static Vector3d UnitZ => new Vector3d(0, 0, 1); + /// /// Divides this vector by it's euclidean length. /// @@ -78,6 +84,7 @@ public void Unitize() this.Z /= length; } + /// /// Returns a normalized copy of this vector. /// @@ -91,6 +98,7 @@ public Vector3d Unit() return new Vector3d(x, y, z); } + /// /// Computes the dot product of this vector and v. /// @@ -98,6 +106,7 @@ public Vector3d Unit() /// Dot product. public double Dot(Vector3d v) => DotProduct(this, v); + /// /// Returns the cross product of this vector and v. /// @@ -105,6 +114,7 @@ public Vector3d Unit() /// Cross product vector. public Vector3d Cross(Vector3d v) => CrossProduct(this, v); + /// /// Gets the scalar product (dot product) of two given vectors /// Dot product = u1*v1 + u2*v2 + u3*v3. @@ -112,7 +122,9 @@ public Vector3d Unit() /// First vector. /// Second vector. /// Numerical value of the dot product. - public static double DotProduct(Vector3d u, Vector3d v) => (u.X * v.X) + (u.Y * v.Y) + (u.Z * v.Z); + public static double DotProduct(Vector3d u, Vector3d v) => + u.X * v.X + u.Y * v.Y + u.Z * v.Z; + /// /// Computes the vector product (cross product) of two given vectors @@ -123,13 +135,14 @@ public Vector3d Unit() /// Vector result of the cross product. public static Vector3d CrossProduct(Vector3d u, Vector3d v) { - var x = (u.Y * v.Z) - (u.Z * v.Y); - var y = (u.Z * v.X) - (u.X * v.Z); - var z = (u.X * v.Y) - (u.Y * v.X); + var x = u.Y * v.Z - u.Z * v.Y; + var y = u.Z * v.X - u.X * v.Z; + var z = u.X * v.Y - u.Y * v.X; return new Vector3d(x, y, z); } + /// /// Computes the angle in Radians between two given vectors /// Angle = Arcosine of the CrossProduct of UxV divided with their multiplied lengths. @@ -137,7 +150,9 @@ public static Vector3d CrossProduct(Vector3d u, Vector3d v) /// First vector. /// Second vector. /// Angle formed between u and v. - public static double Angle(Vector3d u, Vector3d v) => Math.Acos(DotProduct(u, v) / (u.Length * v.Length)); + public static double Angle(Vector3d u, Vector3d v) => + Math.Acos(DotProduct(u, v) / (u.Length * v.Length)); + /// /// Adds one vector to another. @@ -145,7 +160,9 @@ public static Vector3d CrossProduct(Vector3d u, Vector3d v) /// First vector to add. /// Second vector to add. /// New vector entity with the result of the addition. - public static Vector3d operator +(Vector3d v, Vector3d v2) => new Vector3d(v.X + v2.X, v.Y + v2.Y, v.Z + v2.Z); + public static Vector3d operator +(Vector3d v, Vector3d v2) => + new Vector3d(v.X + v2.X, v.Y + v2.Y, v.Z + v2.Z); + /// /// Substracts one vector from another. @@ -153,7 +170,9 @@ public static Vector3d CrossProduct(Vector3d u, Vector3d v) /// Vector to substract from. /// Vector to be substracted. /// New vector entity with the result of the substraction. - public static Vector3d operator -(Vector3d v, Vector3d v2) => new Vector3d(v.X - v2.X, v.Y - v2.Y, v.Z - v2.Z); + public static Vector3d operator -(Vector3d v, Vector3d v2) => + new Vector3d(v.X - v2.X, v.Y - v2.Y, v.Z - v2.Z); + /// /// Multiply one vector by a number. @@ -161,7 +180,9 @@ public static Vector3d CrossProduct(Vector3d u, Vector3d v) /// Vector to multiply. /// Number to multiply with. /// New vector entity with the result of the multiplication. - public static Vector3d operator *(Vector3d v, double scalar) => new Vector3d(v.X * scalar, v.Y * scalar, v.Z * scalar); + public static Vector3d operator *(Vector3d v, double scalar) => + new Vector3d(v.X * scalar, v.Y * scalar, v.Z * scalar); + /// /// Multiply one vector by a number. @@ -169,7 +190,9 @@ public static Vector3d CrossProduct(Vector3d u, Vector3d v) /// Number to multiply with. /// Vector to multiply. /// New vector entity with the result of the multiplication. - public static Vector3d operator *(double scalar, Vector3d v) => new Vector3d(v.X * scalar, v.Y * scalar, v.Z * scalar); + public static Vector3d operator *(double scalar, Vector3d v) => + new Vector3d(v.X * scalar, v.Y * scalar, v.Z * scalar); + /// /// Negate a vector. @@ -182,13 +205,16 @@ public static Vector3d CrossProduct(Vector3d u, Vector3d v) v.Y != 0 ? -v.Y : 0, v.Z != 0 ? -v.Z : 0); + /// /// Divide a vector by a number. /// /// Vector to be divided. /// Number to be divided by. /// New vector entity with the result of the division. - public static Vector3d operator /(Vector3d v, double scalar) => new Vector3d(v.X / scalar, v.Y / scalar, v.Z / scalar); + public static Vector3d operator /(Vector3d v, double scalar) => + new Vector3d(v.X / scalar, v.Y / scalar, v.Z / scalar); + /// /// Checks if two vectors are equal. @@ -198,6 +224,7 @@ public static Vector3d CrossProduct(Vector3d u, Vector3d v) /// Result of the comparison between v and w. public static bool operator ==(Vector3d v, Vector3d w) => v.Equals(w); + /// /// Checks if two vectors are not equal. /// @@ -206,15 +233,18 @@ public static Vector3d CrossProduct(Vector3d u, Vector3d v) /// Result of the comparison between v and w. public static bool operator !=(Vector3d v, Vector3d w) => !v.Equals(w); + /// public override bool Equals(object obj) => base.Equals(obj); + /// /// Converts a vector into a string. /// /// Returns a string representation of this vector. public override string ToString() => "Vector3d" + base.ToString(); + /// public override int GetHashCode() => base.GetHashCode(); } diff --git a/src/Geometry/3D/VectorNd.cs b/src/Geometry/3D/VectorNd.cs index af6ac18..54593c9 100644 --- a/src/Geometry/3D/VectorNd.cs +++ b/src/Geometry/3D/VectorNd.cs @@ -12,12 +12,14 @@ public class VectorNd : IEnumerable, IEquatable { private List values; + /// /// Initializes a new instance of the class. /// /// Vector to copy. public VectorNd(VectorNd vector) => this.values = new List(vector); + /// /// Initializes a new instance of the class. /// Constructs a zero vector of a given dimension. @@ -25,18 +27,23 @@ public class VectorNd : IEnumerable, IEquatable /// Dimension. public VectorNd(int dimension) => this.InitializeZeroVector(dimension); + /// - /// Initializes a new instance of the class from a given list of coordinates. + /// Initializes a new instance of the class from a given list of + /// coordinates. /// /// List of values for the vector. public VectorNd(List values) => this.values = values; + /// - /// Initializes a new instance of the class from a given list of parameters. + /// Initializes a new instance of the class from a given list of + /// parameters. /// /// Number parameters. public VectorNd(params double[] values) : this(values.ToList()) { } + /// /// Gets or sets the coordinate at the given dimension. /// @@ -62,11 +69,14 @@ public double this[int dimension] /// public double Length2 => this.ComputeLength2(); + /// public IEnumerator GetEnumerator() => this.values.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => this.values.GetEnumerator(); + /// /// Compare this vector with another. /// @@ -87,6 +97,7 @@ public bool Equals(VectorNd vector) return true; } + /// /// Gets the dot product of this vector with another. /// @@ -94,6 +105,7 @@ public bool Equals(VectorNd vector) /// Dot product result. public double Dot(VectorNd vector) => DotProduct(this, vector); + private double ComputeLength2() { var length = .0; @@ -101,6 +113,7 @@ private double ComputeLength2() return length; } + private void InitializeZeroVector(int dimension) { this.values = new List(dimension); @@ -108,6 +121,7 @@ private void InitializeZeroVector(int dimension) this.values.Add(.0); } + /// /// Computes the distance between two N-dimensional vectors. /// @@ -116,6 +130,7 @@ private void InitializeZeroVector(int dimension) /// Distance between vectors. public static double Distance(VectorNd a, VectorNd b) => Math.Sqrt(Distance2(a, b)); + /// /// Computes the square distance between two N-dimensional vectors. /// @@ -135,13 +150,16 @@ public static double Distance2(VectorNd a, VectorNd b) return dist; } + /// /// Computes the cosine similarity between two vectors. /// /// Vector A. /// Vector B. /// Cosine similarity value. - public static double CosineSimilarity(VectorNd a, VectorNd b) => a.Dot(b) / (a.Length * b.Length); + public static double CosineSimilarity(VectorNd a, VectorNd b) => + a.Dot(b) / (a.Length * b.Length); + /// /// Computes the angular distance between two vectors. @@ -149,7 +167,9 @@ public static double Distance2(VectorNd a, VectorNd b) /// Vector A. /// Vector B. /// Angular distance value. - public static double AngularDistance(VectorNd a, VectorNd b) => Math.Acos(CosineSimilarity(a, b)) / Math.PI; + public static double AngularDistance(VectorNd a, VectorNd b) => + Math.Acos(CosineSimilarity(a, b)) / Math.PI; + /// /// Angular similarity value between two vectors. @@ -159,6 +179,7 @@ public static double Distance2(VectorNd a, VectorNd b) /// Angular similarity value. public static double AngularSimilarity(VectorNd a, VectorNd b) => 1 - AngularDistance(a, b); + /// /// Adds two N dimensional vectors. /// @@ -179,6 +200,7 @@ public static VectorNd Add(VectorNd a, VectorNd b) return result; } + /// /// Subtract two N dimensional vectors. /// @@ -187,6 +209,7 @@ public static VectorNd Add(VectorNd a, VectorNd b) /// Vector substraction result. public static VectorNd Substract(VectorNd a, VectorNd b) => Add(a, Negate(b)); + /// /// Multiply an N dimensional vector by a number. /// @@ -201,13 +224,16 @@ public static VectorNd Multiply(VectorNd vector, double scalar) return result; } + /// /// Divide an N dimensional vector by a number. /// /// Vector to divide. /// Number to divide by. /// Vector division result. - public static VectorNd Divide(VectorNd vector, double scalar) => Multiply(vector, 1 / scalar); + public static VectorNd Divide(VectorNd vector, double scalar) => + Multiply(vector, 1 / scalar); + /// /// Negate a given vector. @@ -222,6 +248,7 @@ public static VectorNd Negate(VectorNd vector) return result; } + /// /// Computes the dot product between two vectors. /// @@ -242,18 +269,22 @@ public static double DotProduct(VectorNd vectorA, VectorNd vectorB) return result; } - /// - public static VectorNd operator +(VectorNd vectorA, VectorNd vectorB) => Add(vectorA, vectorB); - /// - public static VectorNd operator -(VectorNd vectorA, VectorNd vectorB) => Substract(vectorA, vectorB); + public static VectorNd operator +(VectorNd vectorA, VectorNd vectorB) => + Add(vectorA, vectorB); + + + public static VectorNd operator -(VectorNd vectorA, VectorNd vectorB) => + Substract(vectorA, vectorB); + + + public static VectorNd operator *(VectorNd vector, double scalar) => + Multiply(vector, scalar); - /// - public static VectorNd operator *(VectorNd vector, double scalar) => Multiply(vector, scalar); - /// public static VectorNd operator /(VectorNd vector, double scalar) => Divide(vector, scalar); + /// /// Compare this vector with another object. /// @@ -267,20 +298,21 @@ public override bool Equals(object obj) return false; } + /// public override int GetHashCode() { unchecked { // Choose large primes to avoid hashing collisions - const int hashingBase = (int)2166136261; + const int hashingBase = ( int ) 2166136261; const int hashingMultiplier = 16777619; var tol = Settings.Tolerance * 2; var hash = hashingBase; foreach (var coord in this.values) { - var tCoord = (int)(coord * (1 / tol)) * tol; // Round to tolerance + var tCoord = ( int ) (coord * (1 / tol)) * tol; // Round to tolerance hash = (hash * hashingMultiplier) ^ tCoord.GetHashCode(); } @@ -288,7 +320,9 @@ public override int GetHashCode() } } + /// - public override string ToString() => "VectorNd[" + this[0] + "," + this[1] + "," + this[2] + ",...]"; + public override string ToString() => + "VectorNd[" + this[0] + "," + this[1] + "," + this[2] + ",...]"; } } \ No newline at end of file diff --git a/src/Geometry/Base/BaseCurve.cs b/src/Geometry/Base/BaseCurve.cs index 00b18bb..15ab134 100644 --- a/src/Geometry/Base/BaseCurve.cs +++ b/src/Geometry/Base/BaseCurve.cs @@ -5,7 +5,8 @@ namespace Paramdigma.Core.Geometry { /// - /// Represents a generic curve. This class is abstract and all curve classes should inherit from it. + /// Represents a generic curve. This class is abstract and all curve classes should inherit from + /// it. /// public abstract class BaseCurve { @@ -15,14 +16,11 @@ public abstract class BaseCurve protected BaseCurve() => this.Domain = Interval.Unit; // Public properties + /// /// Gets or sets the curve's domain. /// - public Interval Domain - { - get; - set; - } + public Interval Domain { get; set; } /// /// Gets a value indicating whether the curve is valid. @@ -32,6 +30,7 @@ public Interval Domain public double Length => this.ComputeLength(); + /// /// Compute a point along the curve at a specified parameter. /// @@ -39,6 +38,7 @@ public Interval Domain /// Point at the parameter specified. public abstract Point3d PointAt(double t); + /// /// Compute the tangent vector along the curve at a specified parameter. /// @@ -46,6 +46,7 @@ public Interval Domain /// Tangent vector at the parameter specified. public abstract Vector3d TangentAt(double t); + /// /// Compute normal vector along the curve at a specified parameter. /// @@ -53,6 +54,7 @@ public Interval Domain /// Normal vector at the parameter specified. public abstract Vector3d NormalAt(double t); + /// /// Compute a binormal vector along the curve at a specified parameter. /// @@ -60,6 +62,7 @@ public Interval Domain /// Binormal vector at the parameter specified. public abstract Vector3d BinormalAt(double t); + /// /// Compute the perpendicular frame along the curve at a specified parameter. /// @@ -67,12 +70,14 @@ public Interval Domain /// Perpendicular plane at the parameter specified. public abstract Plane FrameAt(double t); + /// /// Checks the validity of the curve. /// /// True if valid. public abstract bool CheckValidity(); + /// /// Computes the length of the curve. /// diff --git a/src/Geometry/Base/BasePoint.cs b/src/Geometry/Base/BasePoint.cs index 40ce1da..9897cf1 100644 --- a/src/Geometry/Base/BasePoint.cs +++ b/src/Geometry/Base/BasePoint.cs @@ -13,6 +13,7 @@ public abstract class BasePoint private double y; private double z; + /// /// Initializes a new instance of the class. /// @@ -21,6 +22,7 @@ protected BasePoint() : this(0, 0, 0) => this.IsUnset = true; + /// /// Initializes a new instance of the class. /// @@ -29,6 +31,7 @@ protected BasePoint() protected BasePoint(BasePoint point) : this(point.X, point.Y, point.Z) { } + /// /// Initializes a new instance of the class by cartesian coordinates. /// @@ -43,6 +46,7 @@ protected BasePoint(double xCoord, double yCoord, double zCoord) this.IsUnset = false; } + /// /// Gets or sets x Coordinate. /// @@ -92,11 +96,8 @@ 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; } + /// /// Add a point to this point. @@ -110,6 +111,7 @@ public void Add(BasePoint point) this.IsUnset = false; } + /// /// Substract a point from this one. /// @@ -122,6 +124,7 @@ public void Substract(BasePoint point) this.IsUnset = false; } + /// /// Multiply this point by a number. /// @@ -133,6 +136,7 @@ public void Multiply(double scalar) this.z *= scalar; } + /// /// Divide this point by a number. /// @@ -144,6 +148,7 @@ public void Divide(double scalar) this.z /= scalar; } + /// /// Negates this point. /// @@ -154,18 +159,21 @@ public void Negate() this.z = this.z != 0 ? -this.z : 0; } + /// /// Returns the string representation of this point. /// /// public override string ToString() => "{ " + this.x + ", " + this.y + ", " + this.z + " }"; + /// /// Converts a point to an array of numbers. /// /// Array with cartesian coordinates of point. public double[] ToArray() => new[] {this.x, this.y, this.z}; + /// /// Performs a deep clone of the point. /// @@ -177,24 +185,25 @@ public override bool Equals(object obj) if (!(obj is BasePoint)) return false; - var pt = (BasePoint)obj; + var pt = ( BasePoint ) obj; return Math.Abs(this.X - pt.X) <= Settings.Tolerance && Math.Abs(this.Y - pt.Y) <= Settings.Tolerance && Math.Abs(this.Z - pt.Z) <= Settings.Tolerance; } + /// public override int GetHashCode() { unchecked { // Choose large primes to avoid hashing collisions - const int hashingBase = (int)2166136261; + const int hashingBase = ( int ) 2166136261; const int hashingMultiplier = 16777619; var tol = Settings.Tolerance * 2; - var tX = (int)(this.X * (1 / tol)) * tol; - var tY = (int)(this.Y * (1 / tol)) * tol; - var tZ = (int)(this.Z * (1 / tol)) * tol; + var tX = ( int ) (this.X * (1 / tol)) * tol; + var tY = ( int ) (this.Y * (1 / tol)) * tol; + var tZ = ( int ) (this.Z * (1 / tol)) * tol; var hash = hashingBase; hash = (hash * hashingMultiplier) ^ tX.GetHashCode(); diff --git a/src/Geometry/Base/InvalidCurveException.cs b/src/Geometry/Base/InvalidCurveException.cs index a9f86ae..5c74ebc 100644 --- a/src/Geometry/Base/InvalidCurveException.cs +++ b/src/Geometry/Base/InvalidCurveException.cs @@ -10,10 +10,12 @@ public class InvalidCurveException : Exception /// public InvalidCurveException() { } + /// public InvalidCurveException(string message) : base(message) { } + /// public InvalidCurveException(string message, Exception innerException) : base(message, innerException) { } diff --git a/src/Geometry/Interfaces/ICurve.cs b/src/Geometry/Interfaces/ICurve.cs index e6e809e..ff1690a 100644 --- a/src/Geometry/Interfaces/ICurve.cs +++ b/src/Geometry/Interfaces/ICurve.cs @@ -12,6 +12,7 @@ public interface ICurve /// Point on curve. Point3d PointAt(double t); + /// /// Computes the tangent vector on the curve at the specified parameter. /// @@ -19,6 +20,7 @@ public interface ICurve /// Tangent on curve. Vector3d TangentAt(double t); + /// /// Computes the normal vector on the curve at the specified parameter. /// @@ -26,6 +28,7 @@ public interface ICurve /// Normal on curve. Vector3d NormalAt(double t); + /// /// Computes the binormal vector on the curve at the specified parameter. /// @@ -33,6 +36,7 @@ public interface ICurve /// Binormal vector on curve. Vector3d BinormalAt(double t); + /// /// Computes the perpendicular frame on the curve at the specified parameter. /// diff --git a/src/Geometry/Interfaces/ISurface.cs b/src/Geometry/Interfaces/ISurface.cs index 9809989..e7bb22c 100644 --- a/src/Geometry/Interfaces/ISurface.cs +++ b/src/Geometry/Interfaces/ISurface.cs @@ -11,19 +11,14 @@ 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. @@ -33,6 +28,7 @@ Interval DomainV /// . Point3d PointAt(double u, double v); + /// /// Compute the normal at the specified surface coordinates. /// @@ -41,6 +37,7 @@ Interval DomainV /// Normal vector. Vector3d NormalAt(double u, double v); + /// /// Compute the tangent plane at the specified surface coordinates. /// @@ -49,6 +46,7 @@ Interval DomainV /// Tangent plane. Plane FrameAt(double u, double v); + /// /// Compute the distance between this surface and a point. /// @@ -56,6 +54,7 @@ Interval DomainV /// Number representing the distance. double DistanceTo(Point3d point); + /// /// Compute the projection of a point on this surface. /// diff --git a/src/Geometry/Intersect/Intersect.cs b/src/Geometry/Intersect/Intersect.cs index c494794..737a8e1 100644 --- a/src/Geometry/Intersect/Intersect.cs +++ b/src/Geometry/Intersect/Intersect.cs @@ -49,10 +49,11 @@ public static ISLinePlane LinePlane(Line line, Plane plane, out Point3d intersec return ISLinePlane.NoIntersection; } - intersectionPoint = line.StartPoint + (u * sI); // Compute segment intersection point + intersectionPoint = line.StartPoint + u * sI; // Compute segment intersection point return ISLinePlane.Point; } + /// /// Compute the intersection between a mesh face perimeter and a ray tangent to the face. /// @@ -61,7 +62,11 @@ public static ISLinePlane LinePlane(Line line, Plane plane, out Point3d intersec /// The resulting intersection point. /// The half-edge on where the intersection lies. /// Intersection result. - public static ISRayFacePerimeter RayFacePerimeter(Ray ray, MeshFace face, out Point3d result, out MeshHalfEdge halfEdge) + public static ISRayFacePerimeter RayFacePerimeter( + Ray ray, + MeshFace face, + out Point3d result, + out MeshHalfEdge halfEdge) { var faceNormal = MeshGeometry.FaceNormal(face); var biNormal = Vector3d.CrossProduct(ray.Direction, faceNormal); @@ -93,14 +98,14 @@ public static ISRayFacePerimeter RayFacePerimeter(Ray ray, MeshFace face, out Po result = null; halfEdge = null; return ISRayFacePerimeter.NoIntersection; - } // No intersection found + } if (temp != ray.Origin && temp != null) { result = temp; halfEdge = null; return ISRayFacePerimeter.Point; - } // Intersection found + } line = new Line(vertices[2], vertices[0]); if (LinePlane(line, perpPlane, out temp) != ISLinePlane.Point) @@ -122,6 +127,7 @@ public static ISRayFacePerimeter RayFacePerimeter(Ray ray, MeshFace face, out Po return ISRayFacePerimeter.Error; } + /// /// Compute the intersection between two 3-dimensional lines. /// @@ -139,7 +145,7 @@ public static ISLineLine LineLine(Line lineA, Line lineB, out IRLineLine result) var c = v.Dot(v); // always >= 0 var d = u.Dot(w); var e = v.Dot(w); - var d2 = (a * c) - (b * b); // always >= 0 + var d2 = a * c - b * b; // always >= 0 double sc, sN, sD = d2; // sc = sN / sD, default sD = D >= 0 double tc, tN, tD = d2; // tc = tN / tD, default tD = D >= 0 @@ -155,8 +161,8 @@ public static ISLineLine LineLine(Line lineA, Line lineB, out IRLineLine result) else { // get the closest points on the infinite lines - sN = (b * e) - (c * d); - tN = (a * e) - (b * d); + sN = b * e - c * d; + tN = a * e - b * d; if (sN < 0.0) { // sc < 0 => the s=0 edge is visible @@ -211,7 +217,7 @@ public static ISLineLine LineLine(Line lineA, Line lineB, out IRLineLine result) tc = Math.Abs(tN) < Settings.Tolerance ? 0.0 : tN / tD; // get the difference of the two closest points - var dP = w + ((sc * u) - (tc * v)); // = S1(sc) - S2(tc) + var dP = w + (sc * u - tc * v); // = S1(sc) - S2(tc) result = default; result.Distance = dP.Length; // return the closest distance result.TA = sc; diff --git a/src/Geometry/Intersect/IntersectErrors.cs b/src/Geometry/Intersect/IntersectErrors.cs index d10ae97..dfbb7db 100644 --- a/src/Geometry/Intersect/IntersectErrors.cs +++ b/src/Geometry/Intersect/IntersectErrors.cs @@ -11,52 +11,38 @@ public static partial class Intersect3D { public enum ISLineLine { - NoIntersection, Point, Error + NoIntersection, + Point, + Error } // INFO: IS prefix stands for Intersection Status // INFO: IR prefix stands for Intersection Result public enum ISLinePlane { - NoIntersection, Point, OnPlane + NoIntersection, + Point, + OnPlane } public enum ISRayFacePerimeter { - NoIntersection, Point, Error + NoIntersection, + Point, + Error } public struct IRLineLine { - public double Distance - { - get; - set; - } - - public double TA - { - get; - set; - } - - public double TB - { - get; - set; - } - - public Point3d PointA - { - get; - set; - } - - public Point3d PointB - { - get; - set; - } + public double Distance { get; set; } + + public double TA { get; set; } + + public double TB { get; set; } + + public Point3d PointA { get; set; } + + public Point3d PointB { get; set; } } } } \ No newline at end of file diff --git a/src/Geometry/SpatialStructures/PointCloud.cs b/src/Geometry/SpatialStructures/PointCloud.cs index d6c20fb..cb98dbf 100644 --- a/src/Geometry/SpatialStructures/PointCloud.cs +++ b/src/Geometry/SpatialStructures/PointCloud.cs @@ -9,44 +9,55 @@ namespace Paramdigma.Core.SpatialSearch /// public class PointCloud : IList { - private List points - { - get; - } + private List points { get; } + + /// public IEnumerator GetEnumerator() => this.points.GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this.points).GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => (( IEnumerable ) this.points).GetEnumerator(); + + /// public void Add(PointCloudMember item) => this.points.Add(item); + /// public void Clear() => this.points.Clear(); + /// public bool Contains(PointCloudMember item) => this.points.Contains(item); + /// - public void CopyTo(PointCloudMember[] array, int arrayIndex) => this.points.CopyTo(array, arrayIndex); + public void CopyTo(PointCloudMember[] array, int arrayIndex) => + this.points.CopyTo(array, arrayIndex); + /// public bool Remove(PointCloudMember item) => this.points.Remove(item); + /// public int Count => this.points.Count; /// - public bool IsReadOnly => ((ICollection)this.points).IsReadOnly; + public bool IsReadOnly => (( ICollection ) this.points).IsReadOnly; + /// public int IndexOf(PointCloudMember item) => this.points.IndexOf(item); + /// public void Insert(int index, PointCloudMember item) => this.points.Insert(index, item); + /// public void RemoveAt(int index) => this.points.RemoveAt(index); + /// public PointCloudMember this[int index] { diff --git a/src/Geometry/SpatialStructures/PointCloudMember.cs b/src/Geometry/SpatialStructures/PointCloudMember.cs index f6b19b6..dcc19f6 100644 --- a/src/Geometry/SpatialStructures/PointCloudMember.cs +++ b/src/Geometry/SpatialStructures/PointCloudMember.cs @@ -12,10 +12,6 @@ public class PointCloudMember : BasePoint /// Gets or sets the color at this point. /// /// The current color if set, defaults to white. - public Color Color - { - get; - set; - } + public Color Color { get; set; } } } \ No newline at end of file diff --git a/src/Geometry/SpatialStructures/Quadtree.cs b/src/Geometry/SpatialStructures/Quadtree.cs index bb9a403..1e9333d 100644 --- a/src/Geometry/SpatialStructures/Quadtree.cs +++ b/src/Geometry/SpatialStructures/Quadtree.cs @@ -25,6 +25,7 @@ public class QuadTree private QuadTree southEast; private QuadTree southWest; + /// /// Initializes a new instance of the class. /// @@ -37,6 +38,7 @@ public QuadTree(BoundingBox2d boundary, double threshold) this.threshold = threshold; } + /// /// Insert a point in the QuadTree. /// @@ -47,8 +49,8 @@ public bool Insert(Point2d point) if (!this.Boundary.ContainsPoint(point)) return false; - - if (this.Boundary.XDomain.Length < this.threshold || this.Boundary.YDomain.Length < this.threshold) + if (this.Boundary.XDomain.Length < this.threshold + || this.Boundary.YDomain.Length < this.threshold) { this.Points.Add(point); return true; @@ -65,6 +67,7 @@ public bool Insert(Point2d point) return false; } + /// /// Query the QuadTree for all points contained in this range. /// @@ -77,14 +80,16 @@ public List QueryRange(BoundingBox2d range) if (!this.Boundary.IntersectsBox(range)) return pointsInRange; - this.Points.ForEach(pt => - { - if (range.ContainsPoint(pt)) - pointsInRange.Add(pt); - }); + this.Points.ForEach( + pt => + { + if (range.ContainsPoint(pt)) + pointsInRange.Add(pt); + }); // If we reached threshold return - if (this.Boundary.XDomain.Length < this.threshold || this.Boundary.YDomain.Length < this.threshold) + if (this.Boundary.XDomain.Length < this.threshold + || this.Boundary.YDomain.Length < this.threshold) return pointsInRange; if (this.southWest != null) @@ -98,6 +103,7 @@ public List QueryRange(BoundingBox2d range) return pointsInRange; } + private void Subdivide() { this.southWest = new QuadTree( diff --git a/src/IO/OBJMeshData.cs b/src/IO/OBJMeshData.cs index 3eddd83..4032380 100644 --- a/src/IO/OBJMeshData.cs +++ b/src/IO/OBJMeshData.cs @@ -7,34 +7,16 @@ namespace Paramdigma.Core.IO { public struct OBJMeshData { - public List Vertices - { - get; - } + public List Vertices { get; } - public List> Faces - { - get; - } + public List> Faces { get; } - public List> Edges - { - get; - } + public List> Edges { get; } - public List> TextureCoords - { - get; - } + public List> TextureCoords { get; } - public List> FaceTextureCoords - { - get; - } + public List> FaceTextureCoords { get; } - public List Normals - { - get; - } + public List Normals { get; } } } \ No newline at end of file diff --git a/src/IO/OFFMeshData.cs b/src/IO/OFFMeshData.cs index ad8427f..8649e4e 100644 --- a/src/IO/OFFMeshData.cs +++ b/src/IO/OFFMeshData.cs @@ -13,19 +13,11 @@ public class OFFMeshData /// /// Gets or sets the mesh vertices. /// - public List Vertices - { - get; - set; - } + public List Vertices { get; set; } /// /// Gets or sets the mesh face indices. /// - public List> Faces - { - get; - set; - } + public List> Faces { get; set; } } } \ No newline at end of file diff --git a/src/IO/OFFReader.cs b/src/IO/OFFReader.cs index a86fec8..3335a76 100644 --- a/src/IO/OFFReader.cs +++ b/src/IO/OFFReader.cs @@ -36,6 +36,7 @@ public static OFFResult ReadMeshFromFile(string filePath, out OFFMeshData data) var faces = new List>(); for (var i = start; i < lines.Length; i++) + { if (i < nVertex + start) { // Extract vertices @@ -73,6 +74,7 @@ public static OFFResult ReadMeshFromFile(string filePath, out OFFMeshData data) faces.Add(vertexIndexes); } + } // Set data output data.Vertices = vertices; diff --git a/src/IO/OFFResult.cs b/src/IO/OFFResult.cs index 061cac6..81879c7 100644 --- a/src/IO/OFFResult.cs +++ b/src/IO/OFFResult.cs @@ -7,8 +7,12 @@ namespace Paramdigma.Core.IO /// public enum OFFResult { - OK, IncorrectFormat, IncorrectVertex, - IncorrectFace, NonMatchingVerticesSize, NonMatchingFacesSize, + OK, + IncorrectFormat, + IncorrectVertex, + IncorrectFace, + NonMatchingVerticesSize, + NonMatchingFacesSize, FileNotFound } } \ No newline at end of file diff --git a/src/IO/OFFWritter.cs b/src/IO/OFFWritter.cs index d2049a7..bd5d116 100644 --- a/src/IO/OFFWritter.cs +++ b/src/IO/OFFWritter.cs @@ -32,6 +32,7 @@ public static OFFResult WriteMeshToFile(Mesh mesh, string filePath) } foreach (var face in mesh.Faces) + { if (!face.IsBoundaryLoop()) { var vertices = face.AdjacentVertices(); @@ -43,6 +44,7 @@ public static OFFResult WriteMeshToFile(Mesh mesh, string filePath) offLines[count] = faceString; count++; } + } File.WriteAllLines(filePath, offLines); return OFFResult.OK; diff --git a/src/LinearAlgebra/Complex.cs b/src/LinearAlgebra/Complex.cs index 2f08cce..aa2a030 100644 --- a/src/LinearAlgebra/Complex.cs +++ b/src/LinearAlgebra/Complex.cs @@ -18,43 +18,40 @@ public Complex(double real, double imaginary) this.Imaginary = imaginary; } + /// /// Gets or sets the Real component of the complex number. /// - public double Real - { - get; - set; - } + public double Real { get; set; } /// /// Gets or sets the Imaginary component of the complex number. /// - public double Imaginary - { - get; - set; - } + public double Imaginary { get; set; } // Methods + /// /// Computes the phase angle of this complex number. /// /// public double Arg() => Math.Atan2(this.Imaginary, this.Real); + /// /// Computes the length of the complex number. /// /// public double Norm() => Math.Sqrt(this.Norm2()); + /// /// Computes the squared length of the complex number. /// /// - public double Norm2() => (this.Real * this.Real) + (this.Imaginary * this.Imaginary); + public double Norm2() => this.Real * this.Real + this.Imaginary * this.Imaginary; + /// /// Conjugates complex number (negates the imaginary component). @@ -62,14 +59,17 @@ public double Imaginary /// public Complex Conjugate() => new Complex(this.Real, -this.Imaginary); + /// /// Computes the inverse of the complex number ((a + bi)^-1). /// /// public Complex Inverse() => this.Conjugate().OverReal(this.Norm2()); + /// - /// Computes the polar form ae^(iθ), where a is the norm and θ is the phase angle of this complex number. + /// Computes the polar form ae^(iθ), where a is the norm and θ is the phase angle of this complex + /// number. /// /// public Complex Polar() @@ -80,6 +80,7 @@ public Complex Polar() return new Complex(Math.Cos(theta) * a, Math.Sin(theta) * a); } + /// /// Exponentiates this complex number. /// @@ -91,15 +92,23 @@ public Complex Exp() return new Complex(Math.Cos(theta) * a, Math.Sin(theta) * a); } + // Private methods for operators - private Complex Plus(Complex v) => new Complex(this.Real + v.Real, this.Imaginary + v.Imaginary); + private Complex Plus(Complex v) => new Complex( + this.Real + v.Real, + this.Imaginary + v.Imaginary); + + + private Complex Minus(Complex v) => new Complex( + this.Real - v.Real, + this.Imaginary - v.Imaginary); - private Complex Minus(Complex v) => new Complex(this.Real - v.Real, this.Imaginary - v.Imaginary); private Complex TimesReal(double s) => new Complex(this.Real * s, this.Imaginary * s); private Complex OverReal(double s) => this.TimesReal(1 / s); + private Complex TimesComplex(Complex v) { var a = this.Real; @@ -107,16 +116,18 @@ private Complex TimesComplex(Complex v) var c = v.Real; var d = v.Imaginary; - var reNew = (a * c) - (b * d); - var imNew = (a * d) - (b * c); + var reNew = a * c - b * d; + var imNew = a * d - b * c; return new Complex(reNew, imNew); } + private Complex OverComplex(Complex v) => this.TimesComplex(v.Inverse()); // Operators + /// /// Adds to complex numbers. /// @@ -124,6 +135,7 @@ private Complex TimesComplex(Complex v) /// Second complex number. public static Complex operator +(Complex v, Complex w) => v.Plus(w); + /// /// Substracts one complex number from another. /// @@ -131,6 +143,7 @@ private Complex TimesComplex(Complex v) /// Second complex number. public static Complex operator -(Complex v, Complex w) => v.Minus(w); + /// /// Multiplies a complex number with a number. /// @@ -138,6 +151,7 @@ private Complex TimesComplex(Complex v) /// Multiplier. public static Complex operator *(Complex v, double s) => v.TimesReal(s); + /// /// Multiplies a complex number with a number. /// @@ -145,6 +159,7 @@ private Complex TimesComplex(Complex v) /// Multiplicand. public static Complex operator *(double s, Complex v) => v.TimesReal(s); + /// /// Multiplies to complex numbers. /// @@ -152,6 +167,7 @@ private Complex TimesComplex(Complex v) /// Multiplier. public static Complex operator *(Complex v, Complex w) => v.TimesComplex(w); + /// /// Divides a complex number by a number. /// @@ -159,6 +175,7 @@ private Complex TimesComplex(Complex v) /// Dividend. public static Complex operator /(Complex v, double s) => v.OverReal(s); + /// /// Divides two complex numbers. /// diff --git a/src/LinearAlgebra/LeastSquaresLinearFit.cs b/src/LinearAlgebra/LeastSquaresLinearFit.cs index b43375d..3e15b1e 100644 --- a/src/LinearAlgebra/LeastSquaresLinearFit.cs +++ b/src/LinearAlgebra/LeastSquaresLinearFit.cs @@ -13,6 +13,7 @@ public static class LeastSquaresLinearFit // Return the total error. // Found at: http://csharphelper.com/blog/2014/10/find-a-linear-least-squares-fit-for-a-set-of-points-in-c/ + /// /// Find the least squares best fitting line to the given points. /// @@ -21,7 +22,9 @@ public static class LeastSquaresLinearFit /// Slope. /// public static double FindLinearLeastSquaresFit( - List points, out double m, out double b) + List points, + out double m, + out double b) { // Perform the calculation. // Find the values S1, Sx, Sy, Sxx, and Sxy. @@ -37,19 +40,20 @@ public static double FindLinearLeastSquaresFit( } // Solve for m and b. - m = ((sxy * s1) - (sx * sy)) / ((sxx * s1) - (sx * sx)); - b = ((sxy * sx) - (sy * sxx)) / ((sx * sx) - (s1 * sxx)); + m = (sxy * s1 - sx * sy) / (sxx * s1 - sx * sx); + b = (sxy * sx - sy * sxx) / (sx * sx - s1 * sxx); return Math.Sqrt(ErrorSquared(points, m, b)); } + // Return the error squared. private static double ErrorSquared(List points, double m, double b) { double total = 0; foreach (var pt in points) { - var dy = pt.Y - ((m * pt.X) + b); + var dy = pt.Y - (m * pt.X + b); total += dy * dy; } diff --git a/src/LinearAlgebra/Triplet.cs b/src/LinearAlgebra/Triplet.cs index 7bb90d1..67aa53a 100644 --- a/src/LinearAlgebra/Triplet.cs +++ b/src/LinearAlgebra/Triplet.cs @@ -18,24 +18,17 @@ public Triplet(int m, int n) } // Public fields + /// /// Gets values held by this triplet. /// /// - public List Values - { - get; - } + public List Values { get; } - public int M - { - get; - } + public int M { get; } + + public int N { get; } - public int N - { - get; - } // Methods public void AddEntry(double value, int m, int n) @@ -48,22 +41,10 @@ public void AddEntry(double value, int m, int n) public struct TripletData { - public int Row - { - get; - set; - } + public int Row { get; set; } - public int Column - { - get; - set; - } + public int Column { get; set; } - public double Value - { - get; - set; - } + public double Value { get; set; } } } \ No newline at end of file diff --git a/src/Optimization/GradientDescent.cs b/src/Optimization/GradientDescent.cs index aef3742..54a3916 100644 --- a/src/Optimization/GradientDescent.cs +++ b/src/Optimization/GradientDescent.cs @@ -29,6 +29,7 @@ public class GradientDescent /// public GradientDescentResult Result; + /// /// Initializes a new instance of the class with given options. /// @@ -39,6 +40,7 @@ public GradientDescent(GradientDescentOptions options) this.Options = options; } + /// /// Run gradient descent algorithm. /// @@ -66,12 +68,13 @@ public void Minimize(FitnessFunction function, List inputValues) this.Result.Error = function(this.Result.Values); this.Result.GradientLength = gLength; iter++; // Increase iteration count - } while (gLength > this.Options.Limit && iter < this.Options.MaxIterations && this.Result.Error > this.Options.ErrorThreshold); - - var customError = this.Result.Error > 1E5 ? $"{this.Result.Error:0.###e-000}" : $"{this.Result.Error:0.00000}"; + } while (gLength > this.Options.Limit && iter < this.Options.MaxIterations + && this.Result.Error + > this.Options.ErrorThreshold); Console.ResetColor(); } + /// /// Computes the gradient vector of a given function at some specified input values. /// @@ -87,7 +90,11 @@ private List ComputeGradient(FitnessFunction func, List inputVal for (var i = 0; i < inputValues.Count; i++) { - var dV = this.ComputePartialDerivative(i, func, inputValues, this.Options.DerivativeStep); + var dV = this.ComputePartialDerivative( + i, + func, + inputValues, + this.Options.DerivativeStep); gradient.Add(dV * this.Options.LearningRate); derivativeSquareSum += dV * dV; } @@ -102,6 +109,7 @@ private List ComputeGradient(FitnessFunction func, List inputVal return gradient; } + /// /// Computes the partial derivative at a given input value of a given function. /// @@ -126,7 +134,7 @@ private double ComputePartialDerivative( inputValues[inputIndex] += step; // Reset value to original // Compute partial derivative using 2-point method - partialDerivative = ((error1 - error2) / 2) * step; + partialDerivative = (error1 - error2) / 2 * step; return partialDerivative; } diff --git a/src/Optimization/GradientDescentOptions.cs b/src/Optimization/GradientDescentOptions.cs index 0cc29cc..afe466e 100644 --- a/src/Optimization/GradientDescentOptions.cs +++ b/src/Optimization/GradientDescentOptions.cs @@ -30,8 +30,10 @@ public struct GradientDescentOptions /// public double ErrorThreshold; + /// - /// Initializes a new instance of the struct given an existing one. + /// Initializes a new instance of the struct given an + /// existing one. /// /// Options to duplicate. public GradientDescentOptions(GradientDescentOptions options) @@ -43,17 +45,25 @@ public GradientDescentOptions(GradientDescentOptions options) this.ErrorThreshold = options.ErrorThreshold; } + // TODO: Fill in this fields! + /// - /// Initializes a new instance of the struct given all it's values individually. + /// Initializes a new instance of the struct given all it's + /// values individually. /// /// /// /// /// /// - public GradientDescentOptions(double threshold, int maxIterations, double derivativeStep, double learningRate, double errorThreshold) + public GradientDescentOptions( + double threshold, + int maxIterations, + double derivativeStep, + double learningRate, + double errorThreshold) { this.Limit = threshold; this.MaxIterations = maxIterations; @@ -62,15 +72,18 @@ public GradientDescentOptions(double threshold, int maxIterations, double deriva this.ErrorThreshold = errorThreshold; } + /// /// Gets a GradientDescentOptions instance with the default values. /// - public static GradientDescentOptions Default => new GradientDescentOptions(0.001, 10000, 0.01, 20, .01); + public static GradientDescentOptions Default => + new GradientDescentOptions(0.001, 10000, 0.01, 20, .01); /// /// Gets a GradientDescentOptions instance with small values. /// /// - public static GradientDescentOptions DefaultSmall => new GradientDescentOptions(0.0001, 10000, 0.02, 40, .001); + public static GradientDescentOptions DefaultSmall => + new GradientDescentOptions(0.0001, 10000, 0.02, 40, .001); } } \ No newline at end of file diff --git a/src/Optimization/KMeansCluster.cs b/src/Optimization/KMeansCluster.cs index c105007..ca7915a 100644 --- a/src/Optimization/KMeansCluster.cs +++ b/src/Optimization/KMeansCluster.cs @@ -31,38 +31,49 @@ public VectorNd this[int index] /// public bool IsReadOnly => this.list.IsReadOnly; + /// /// Add a new vector to the cluster. /// /// Vector to add. public void Add(VectorNd item) => this.list.Add(item); + /// public void Clear() => this.list.Clear(); + /// public bool Contains(VectorNd item) => this.list.Contains(item); + /// public void CopyTo(VectorNd[] array, int arrayIndex) => this.list.CopyTo(array, arrayIndex); + /// public IEnumerator GetEnumerator() => this.list.GetEnumerator(); + /// public int IndexOf(VectorNd item) => this.list.IndexOf(item); + /// public void Insert(int index, VectorNd item) => this.list.Insert(index, item); + /// public bool Remove(VectorNd item) => this.list.Remove(item); + /// public void RemoveAt(int index) => this.list.RemoveAt(index); + IEnumerator IEnumerable.GetEnumerator() => this.list.GetEnumerator(); + /// /// Computes the average of this cluster. /// @@ -82,6 +93,7 @@ public VectorNd Average() return result; } + /// public override string ToString() => "Paramdigma.Core.Cluster[" + this.Count + "]"; } diff --git a/src/Optimization/KMeansClustering.cs b/src/Optimization/KMeansClustering.cs index f133cb2..c6b30dd 100644 --- a/src/Optimization/KMeansClustering.cs +++ b/src/Optimization/KMeansClustering.cs @@ -14,6 +14,7 @@ public class KMeansClustering private readonly int maxIterations; private int currentIterations; + /// /// Initializes a new instance of the class. /// @@ -27,14 +28,12 @@ public KMeansClustering(int maxIterations, int clusterCount, List data this.InitializeClusters(data); } + /// /// Gets or sets the list of clusters. /// - public List Clusters - { - get; - set; - } + public List Clusters { get; set; } + private void InitializeClusters(List data) { @@ -42,18 +41,22 @@ private void InitializeClusters(List data) for (var i = 0; i < this.clusterCount; i++) this.Clusters.Add(new KMeansCluster()); - data.ForEach(vector => this.Clusters[new Random().Next() % this.clusterCount].Add(vector)); + data.ForEach( + vector => this.Clusters[new Random().Next() % this.clusterCount].Add(vector)); } + /// /// Run the algorithm until it reaches the maximum amount of iterations. /// public void Run() => this.Run(this.maxIterations, false); + /// /// Run the k-means clustering algorithm for a specified amount of iterations. /// /// Iterations to run. + /// True to allow the optimization to leave clusters empty. public void Run(int iterations, bool allowEmptyClusters) { var rnd = new Random(); @@ -73,39 +76,46 @@ public void Run(int iterations, bool allowEmptyClusters) newClusters.Add(new KMeansCluster()); // Find the closest average for each vector in each cluster - this.Clusters.ForEach(cluster => - { - var ind = this.Clusters.IndexOf(cluster); - for (var i = 0; i < cluster.Count; i++) + this.Clusters.ForEach( + cluster => { - var vector = cluster[i]; - var simIndex = this.FindIndexOfSimilar(averages, vector); - newClusters[simIndex].Add(vector); - if (simIndex != ind) - hasChanged = true; - } - }); + var ind = this.Clusters.IndexOf(cluster); + for (var i = 0; i < cluster.Count; i++) + { + var vector = cluster[i]; + var simIndex = this.FindIndexOfSimilar(averages, vector); + newClusters[simIndex].Add(vector); + if (simIndex != ind) + hasChanged = true; + } + }); // Check for empty clusters if (!allowEmptyClusters) - newClusters.ForEach(cluster => - { - if (cluster.Count == 0) + { + newClusters.ForEach( + cluster => { - Console.WriteLine("Cluster has no mass"); - var biggest = newClusters.OrderByDescending(x => x.Count) - .First(); - - var randomVector = biggest[rnd.Next(biggest.Count)]; - - biggest.Remove(randomVector); - cluster.Add(randomVector); - } - }); + if (cluster.Count == 0) + { + Console.WriteLine("Cluster has no mass"); + var biggest = newClusters.OrderByDescending(x => x.Count) + .First(); + + var randomVector = biggest[rnd.Next(biggest.Count)]; + + biggest.Remove(randomVector); + cluster.Add(randomVector); + } + }); + } // Update clusters and increase iteration this.Clusters = newClusters; - var iterArgs = new IterationCompletedEventArgs {iteration = iteration, Clusters = newClusters}; + var iterArgs = new IterationCompletedEventArgs + { + iteration = iteration, Clusters = newClusters + }; this.OnIterationCompleted(iterArgs); iteration++; this.currentIterations++; @@ -114,6 +124,7 @@ public void Run(int iterations, bool allowEmptyClusters) && this.currentIterations < this.maxIterations); } + /// /// Find the index of the most similar vector to a given one. /// @@ -139,33 +150,29 @@ public int FindIndexOfSimilar(List pool, VectorNd vector) return minIndex; } + /// /// Raised when an iteration is completed. /// public event EventHandler IterationCompleted; + /// /// Method to call when an iteration is completed. /// /// Data for the current iteration. - protected virtual void OnIterationCompleted(IterationCompletedEventArgs iterArgs) => this.IterationCompleted?.Invoke(this, iterArgs); + protected virtual void OnIterationCompleted(IterationCompletedEventArgs iterArgs) => + this.IterationCompleted?.Invoke(this, iterArgs); + /// /// Data for the current iteration event. /// public class IterationCompletedEventArgs : EventArgs { - public int iteration - { - get; - set; - } + public int iteration { get; set; } - public List Clusters - { - get; - set; - } + public List Clusters { get; set; } } } } \ No newline at end of file diff --git a/src/Paramdigma.Core.csproj b/src/Paramdigma.Core.csproj index 534717c..1d6df96 100644 --- a/src/Paramdigma.Core.csproj +++ b/src/Paramdigma.Core.csproj @@ -24,10 +24,6 @@ - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - diff --git a/src/Utility/Convert.cs b/src/Utility/Convert.cs index dd81edf..fa0bb42 100644 --- a/src/Utility/Convert.cs +++ b/src/Utility/Convert.cs @@ -20,10 +20,10 @@ public static double[] Point3dToBarycentric(Point3d p, Point3d a, Point3d b, Poi { Vector3d v0 = b - a, v1 = c - a, v2 = p - a; - var den = (v0.X * v1.Y) - (v1.X * v0.Y); + var den = v0.X * v1.Y - v1.X * v0.Y; - var v = ((v2.X * v1.Y) - (v1.X * v2.Y)) / den; - var w = ((v0.X * v2.Y) - (v2.X * v0.Y)) / den; + var v = (v2.X * v1.Y - v1.X * v2.Y) / den; + var w = (v0.X * v2.Y - v2.X * v0.Y) / den; var u = 1.0 - v - w; double[] result = {u, v, w}; diff --git a/src/Utility/Settings.cs b/src/Utility/Settings.cs index de393a7..275cb16 100644 --- a/src/Utility/Settings.cs +++ b/src/Utility/Settings.cs @@ -14,11 +14,7 @@ public static class Settings /// /// Gets the minimum value allowed when using this library. /// - public static double Tolerance - { - get; - private set; - } = 0.0000001; + public static double Tolerance { get; private set; } = 0.0000001; /// /// Gets how many decimals are allowed when using the library. @@ -32,39 +28,47 @@ public static int MaxDecimals } } + /// /// Gets the default tessellation level when converting nurbs to meshes. /// /// Integer representing the default tessellation level. public static int GetDefaultTesselationLevel() => tesselationLevel; + /// /// Sets the default tessellation level when converting nurbs to meshes. /// private static void SetDefaultTesselationLevel(int value) => tesselationLevel = value; + /// /// Modifies the tolerance and computes the maxDecimals value accordingly. /// /// Desired tolerance. public static void SetTolerance(double tolerance) => Tolerance = tolerance; + /// /// Reset the Settings to it's default values. /// public static void Reset() { var assembly = typeof(Settings).GetTypeInfo().Assembly; - using (var stream = assembly.GetManifestResourceStream("Paramdigma.Core.Data.Settings.json")) - using (var reader = new StreamReader(stream)) + using (var stream = + assembly.GetManifestResourceStream("Paramdigma.Core.Data.Settings.json")) { - var result = reader.ReadToEnd(); - var json = JsonConvert.DeserializeObject(result); - SetTolerance(json.Tolerance); - SetDefaultTesselationLevel(json.DefaultTesselation); + using (var reader = new StreamReader(stream)) + { + var result = reader.ReadToEnd(); + var json = JsonConvert.DeserializeObject(result); + SetTolerance(json.Tolerance); + SetDefaultTesselationLevel(json.DefaultTesselation); + } } } + /// /// This struct holds the settings from the embedded json file. It is only used to reset. /// diff --git a/tests/Collections/IntervalTests.cs b/tests/Collections/IntervalTests.cs index 2ecbaf1..20e00ad 100644 --- a/tests/Collections/IntervalTests.cs +++ b/tests/Collections/IntervalTests.cs @@ -16,6 +16,7 @@ public void Can_CheckAndModifyDirection() Assert.True(dir != dir2); } + [Fact] public void Can_CheckContainment() { @@ -28,6 +29,7 @@ public void Can_CheckContainment() Assert.True(i.Contains(n3)); } + [Fact] public void Can_CropNumbers() { @@ -38,22 +40,24 @@ public void Can_CropNumbers() var n1c = i.Crop(n1); var n2c = i.Crop(n2); var n3c = i.Crop(n3); - Assert.True(n1c == i.Start); - Assert.True(n2c == i.End); - Assert.True(n3c == n3); + Assert.True(Math.Abs(n1c - i.Start) < Settings.Tolerance); + Assert.True(Math.Abs(n2c - i.End) < Settings.Tolerance); + Assert.True(Math.Abs(n3c - n3) < Settings.Tolerance); } + [Fact] public void Can_RemapNumbers() { var i = new Interval(1, 3); const double n = 2.0; var nMap = i.RemapToUnit(n); - Assert.True(nMap == 0.5); + Assert.True(Math.Abs(nMap - 0.5) < Settings.Tolerance); var nRemap = i.RemapFromUnit(nMap); - Assert.True(n == nRemap); + Assert.True(Math.Abs(n - nRemap) < Settings.Tolerance); } + [Fact] public void CanCreate_Interval() { diff --git a/tests/Curves/LevelSetsTests.cs b/tests/Curves/LevelSetsTests.cs index 2d670e0..6275039 100644 --- a/tests/Curves/LevelSetsTests.cs +++ b/tests/Curves/LevelSetsTests.cs @@ -26,6 +26,7 @@ public Mesh Triangle } } + [Fact] public void CanCompute_GradientInFace_ReturnsValidVector() { @@ -34,12 +35,17 @@ public void CanCompute_GradientInFace_ReturnsValidVector() Assert.Equal(new Vector3d(0, -1, -1).Unit(), c[0].Unit()); } + [Fact] public void CanCompute_LevelInFace_ReturnsValidLine() { - LevelSets.ComputeLevels("scalar-1", new List {0.5}, this.Triangle, out var levelSets); + LevelSets.ComputeLevels( + "scalar-1", + new List {0.5}, + this.Triangle, + out var levelSets); Assert.NotEmpty(levelSets); - var v = (Vector3d)levelSets[0][0]; + var v = ( Vector3d ) levelSets[0][0]; Assert.Equal(new Vector3d(1, 0, 0), v.Unit()); } } diff --git a/tests/Extensions/ListExtensionsTests.cs b/tests/Extensions/ListExtensionsTests.cs index 291561e..32415fd 100644 --- a/tests/Extensions/ListExtensionsTests.cs +++ b/tests/Extensions/ListExtensionsTests.cs @@ -16,6 +16,7 @@ public void CanCreate_Repeated() } } + [Fact] public void CanCreate_RepeatedDefault() { diff --git a/tests/Geometry/2D/DelaunayTests.cs b/tests/Geometry/2D/DelaunayTests.cs index 02360cb..768f806 100644 --- a/tests/Geometry/2D/DelaunayTests.cs +++ b/tests/Geometry/2D/DelaunayTests.cs @@ -21,12 +21,20 @@ public void CanComputeDelaunay() var triangle1 = new DelaunayTriangle(point0, point1, point2); var triangle2 = new DelaunayTriangle(point0, point2, point3); - var border = new List { triangle1, triangle2 }; + var border = new List {triangle1, triangle2}; var delaunay = Delaunay.Compute( - new List { point0, point1, point2, point3, point4 }, - border - ).ToList(); + new List + { + point0, + point1, + point2, + point3, + point4 + }, + border + ) + .ToList(); Assert.True(delaunay.Count == 4); var voronoi = Delaunay.Voronoi(delaunay); @@ -34,51 +42,59 @@ public void CanComputeDelaunay() Assert.True(voronoi.ToList().Count == 8); } - private List GeneratePoints(int ammount, double maxX, double maxY, out List border) - { - DelaunayPoint point0 = new DelaunayPoint(0, 0); - DelaunayPoint point1 = new DelaunayPoint(0, maxY); - DelaunayPoint point2 = new DelaunayPoint(maxX, maxY); - DelaunayPoint point3 = new DelaunayPoint(maxX, 0); - List points = new List() { point0, point1, point2, point3 }; - DelaunayTriangle triangle1 = new DelaunayTriangle(point0, point1, point2); - DelaunayTriangle triangle2 = new DelaunayTriangle(point0, point2, point3); - border = new List { triangle1, triangle2 }; - Random rnd = new Random(); - List points2 = new List(); - for (int i = 0; i < ammount - 4; i++) - { - points2.Add(RandomPoint(rnd, 0, maxX)); - } - return points2; + private List GeneratePoints( + int ammount, + double maxX, + double maxY, + out List border) + { + var point0 = new DelaunayPoint(0, 0); + var point1 = new DelaunayPoint(0, maxY); + var point2 = new DelaunayPoint(maxX, maxY); + var point3 = new DelaunayPoint(maxX, 0); + var triangle1 = new DelaunayTriangle(point0, point1, point2); + var triangle2 = new DelaunayTriangle(point0, point2, point3); + border = new List {triangle1, triangle2}; + var rnd = new Random(); + var points = new List(); + for (var i = 0; i < ammount - 4; i++) + points.Add(RandomPoint(rnd, 0, maxX)); + return points; } - private static DelaunayPoint RandomPoint(Random RandGenerator, double MinValue, double MaxValue) + private static DelaunayPoint RandomPoint( + Random randGenerator, + double minValue, + double maxValue) { - double range = MaxValue - MinValue; - DelaunayPoint randomPoint = new DelaunayPoint((RandGenerator.NextDouble() * range) + MinValue, (RandGenerator.NextDouble() * range) + MinValue); + var range = maxValue - minValue; + var randomPoint = new DelaunayPoint( + randGenerator.NextDouble() * range + minValue, + randGenerator.NextDouble() * range + minValue); return randomPoint; } + [Fact] public void CanCompare_DelaunayEdges() { - var edgeA = new DelaunayEdge(new DelaunayPoint(0,0),new DelaunayPoint(1,0) ); - var edgeB = new DelaunayEdge(new DelaunayPoint(0,0),new DelaunayPoint(1,0) ); - Assert.Equal(edgeA,edgeB); - Assert.Equal(edgeA.GetHashCode(),edgeB.GetHashCode()); + var edgeA = new DelaunayEdge(new DelaunayPoint(0, 0), new DelaunayPoint(1, 0)); + var edgeB = new DelaunayEdge(new DelaunayPoint(0, 0), new DelaunayPoint(1, 0)); + Assert.Equal(edgeA, edgeB); + Assert.Equal(edgeA.GetHashCode(), edgeB.GetHashCode()); Assert.NotNull(edgeA); } + [Fact] public void CanCreate_DelaunayPoint_FromPoint2d() { - var pt = new Point2d(.5,.5); + var pt = new Point2d(.5, .5); var dpt = new DelaunayPoint(pt); - Assert.Equal(pt.X,dpt.X); - Assert.Equal(pt.Y,dpt.Y); + Assert.Equal(pt.X, dpt.X); + Assert.Equal(pt.Y, dpt.Y); } } } \ No newline at end of file diff --git a/tests/Geometry/2D/Line2dTests.cs b/tests/Geometry/2D/Line2dTests.cs index c14f927..fe2f7d8 100644 --- a/tests/Geometry/2D/Line2dTests.cs +++ b/tests/Geometry/2D/Line2dTests.cs @@ -14,6 +14,11 @@ public void CanBe_Created() var line = new Line2d(ptA, ptB); var lineB = new Line2d(ptA, v); var lineC = new Line2d(ptA, v, 3); + + Assert.NotNull(line); + Assert.NotNull(lineB); + Assert.NotNull(lineC); + } } } \ No newline at end of file diff --git a/tests/Geometry/2D/Point2dTests.cs b/tests/Geometry/2D/Point2dTests.cs index 73c2deb..db796a8 100644 --- a/tests/Geometry/2D/Point2dTests.cs +++ b/tests/Geometry/2D/Point2dTests.cs @@ -15,6 +15,7 @@ public void Can_AddVector() Assert.True(pt2 == expected); } + [Fact] public void CanBe_Added() { @@ -28,15 +29,17 @@ public void CanBe_Added() Assert.True(ptA + ptB == ptResult); } + [Fact] public void CanBe_ConvertedToVector() { var pt = new Point2d(0, 1); Vector2d v = pt; - var pt2 = (Point2d)v; + var pt2 = ( Point2d ) v; Assert.True(pt == pt2); } + [Fact] public void CanBe_Divided() { @@ -48,6 +51,7 @@ public void CanBe_Divided() Assert.True(ptA / m == ptResult); } + [Fact] public void CanBe_Multiplied() { @@ -60,6 +64,7 @@ public void CanBe_Multiplied() Assert.True(m * ptA == ptResult); } + [Fact] public void CanBe_Negated() { @@ -70,6 +75,7 @@ public void CanBe_Negated() Assert.True(-ptA == ptResult); } + [Fact] public void CanBe_Substracted() { @@ -82,6 +88,7 @@ public void CanBe_Substracted() Assert.True(ptA - ptB == ptResult); } + [Fact] public void Create_FromPoint() { @@ -90,6 +97,7 @@ public void Create_FromPoint() Assert.True(expected == copy); } + [Fact] public void Create_Origin() { @@ -101,6 +109,7 @@ public void Create_Origin() Assert.True(empty == expected); } + [Fact] public void EqualsAndHashCode_HaveConsistentResults() { diff --git a/tests/Geometry/2D/Polyline2dTests.cs b/tests/Geometry/2D/Polyline2dTests.cs index fd47c08..21969b5 100644 --- a/tests/Geometry/2D/Polyline2dTests.cs +++ b/tests/Geometry/2D/Polyline2dTests.cs @@ -15,12 +15,26 @@ public class Polyline2dUnitSquareAndSegments : IEnumerable private readonly Point2d pt4 = new Point2d(0, 1); + public IEnumerator GetEnumerator() { - yield return new object[] {new Polyline2d(new List {this.pt1, this.pt2, this.pt3, this.pt4}, false), 3}; - yield return new object[] {new Polyline2d(new List {this.pt1, this.pt2, this.pt3, this.pt4}, true), 4}; + yield return new object[] + { + new Polyline2d( + new List {this.pt1, this.pt2, this.pt3, this.pt4}, + false), + 3 + }; + yield return new object[] + { + new Polyline2d( + new List {this.pt1, this.pt2, this.pt3, this.pt4}, + true), + 4 + }; } + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); } @@ -34,11 +48,18 @@ public class Polyline2dDataSet : IEnumerable private readonly Point2d pt4 = new Point2d(0, 1); + public IEnumerator GetEnumerator() { - yield return new object[] {new Polyline2d(new List {this.pt1, this.pt2, this.pt3, this.pt4}, false)}; + yield return new object[] + { + new Polyline2d( + new List {this.pt1, this.pt2, this.pt3, this.pt4}, + false) + }; } + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); } @@ -46,15 +67,21 @@ public class Polyline2dTests { [Theory] [ClassData(typeof(Polyline2dUnitSquareAndSegments))] - public void Constructor_ClosedOption_AddsVertexAndSegment(Polyline2d polyline, int expectedSegments) + public void Constructor_ClosedOption_AddsVertexAndSegment( + Polyline2d polyline, + int expectedSegments) { Assert.True(polyline.Vertices.Count == expectedSegments + 1); Assert.True(polyline.Segments.Count == expectedSegments); } + [Theory] [ClassData(typeof(Polyline2dUnitSquareAndSegments))] - public void DefaultDomain_IsParametrizedByArcLength(Polyline2d polyline, double expectedLength) => Assert.True(polyline.Domain.End == expectedLength); + public void DefaultDomain_IsParametrizedByArcLength( + Polyline2d polyline, + double expectedLength) => Assert.True(polyline.Domain.End == expectedLength); + [Theory] [ClassData(typeof(Polyline2dDataSet))] @@ -66,6 +93,7 @@ public void Reparametrize_SetsAllSegmentsDomain(Polyline2d polyline) Assert.True(polyline.Domain.End == 1); } + [Theory] [ClassData(typeof(Polyline2dDataSet))] public void Check_IsClockwise(Polyline2d polyline) @@ -75,6 +103,7 @@ public void Check_IsClockwise(Polyline2d polyline) Assert.False(cond); } + [Theory] [ClassData(typeof(Polyline2dDataSet))] public void CanCompute_Area(Polyline2d polyline) diff --git a/tests/Geometry/2D/Vector2dTests.cs b/tests/Geometry/2D/Vector2dTests.cs index a2b2516..1e54473 100644 --- a/tests/Geometry/2D/Vector2dTests.cs +++ b/tests/Geometry/2D/Vector2dTests.cs @@ -9,12 +9,13 @@ public class Vector2dTests public void Can_AddVector() { var pt = new Vector2d(0, 1); - var v = (Point2d)pt; + var v = ( Point2d ) pt; var pt2 = pt + v; var expected = new Vector2d(0, 2); Assert.True(pt2 == expected); } + [Fact] public void CanBe_Added() { @@ -28,15 +29,17 @@ public void CanBe_Added() Assert.True(ptA + ptB == ptResult); } + [Fact] public void CanBe_ConvertedTo() { var pt = new Vector2d(0, 1); - var v = (Point2d)pt; + var v = ( Point2d ) pt; Vector2d pt2 = v; Assert.True(pt == pt2); } + [Fact] public void CanBe_ConvertedToString() { @@ -46,6 +49,7 @@ public void CanBe_ConvertedToString() Assert.True(s == result); } + [Fact] public void CanBe_Divided() { @@ -57,6 +61,7 @@ public void CanBe_Divided() Assert.True(ptA / m == ptResult); } + [Fact] public void CanBe_Multiplied() { @@ -69,6 +74,7 @@ public void CanBe_Multiplied() Assert.True(m * ptA == ptResult); } + [Fact] public void CanBe_Negated() { @@ -79,6 +85,7 @@ public void CanBe_Negated() Assert.True(-ptA == ptResult); } + [Fact] public void CanBe_Substracted() { @@ -91,6 +98,7 @@ public void CanBe_Substracted() Assert.True(ptA - ptB == ptResult); } + [Fact] public void CanCompute_DotProduct() { @@ -99,6 +107,7 @@ public void CanCompute_DotProduct() var dot = v.DotProduct(v2); } + [Fact] public void CanCompute_PerpendicularVector() { @@ -108,6 +117,7 @@ public void CanCompute_PerpendicularVector() Assert.True(perp == expected); } + [Fact] public void CanCompute_PerpProduct() { @@ -116,6 +126,7 @@ public void CanCompute_PerpProduct() var dot = v.PerpProduct(v2); } + [Fact] public void CanUnitize() { @@ -125,6 +136,7 @@ public void CanUnitize() Assert.True(v == expected); } + [Fact] public void Create_FromPoint() { @@ -133,6 +145,7 @@ public void Create_FromPoint() Assert.True(expected == copy); } + [Fact] public void Create_Origin() { @@ -141,6 +154,7 @@ public void Create_Origin() Assert.True(empty == expected); } + [Fact] public void EqualsAndHashCode_HaveConsistentResults() { diff --git a/tests/Geometry/3D/BoxTests.cs b/tests/Geometry/3D/BoxTests.cs index 186e0a6..def56c7 100644 --- a/tests/Geometry/3D/BoxTests.cs +++ b/tests/Geometry/3D/BoxTests.cs @@ -22,6 +22,7 @@ public void CanCreate_FromCorners() Assert.Equal(new Point3d(.5, .5, .5), box.Center); } + [Fact] public void CanCreate_FromPlaneAndDimensions() { diff --git a/tests/Geometry/3D/CircleTests.cs b/tests/Geometry/3D/CircleTests.cs index 487e3be..65607b5 100644 --- a/tests/Geometry/3D/CircleTests.cs +++ b/tests/Geometry/3D/CircleTests.cs @@ -7,6 +7,7 @@ public class CircleTests { public Circle testCircle => new Circle(Plane.WorldXY, 1); + [Fact] public void CanCompute_BinormalAt() { @@ -16,8 +17,12 @@ public void CanCompute_BinormalAt() Assert.Equal(this.testCircle.BinormalAt(0.75), Vector3d.UnitZ); } + [Fact] - public void CanCompute_FrameAt() => Assert.Equal(this.testCircle.FrameAt(0), new Plane(this.testCircle.PointAt(0), -Vector3d.UnitX, Vector3d.UnitZ)); + public void CanCompute_FrameAt() => Assert.Equal( + this.testCircle.FrameAt(0), + new Plane(this.testCircle.PointAt(0), -Vector3d.UnitX, Vector3d.UnitZ)); + [Fact] public void CanCompute_NormalAt() @@ -28,6 +33,7 @@ public void CanCompute_NormalAt() Assert.Equal(this.testCircle.NormalAt(0.75), Vector3d.UnitY); } + [Fact] public void CanCompute_PointAt() { @@ -37,6 +43,7 @@ public void CanCompute_PointAt() Assert.Equal(this.testCircle.PointAt(0.75), -Vector3d.UnitY); } + [Fact] public void CanCompute_TangentAt() { diff --git a/tests/Geometry/3D/CylinderTests.cs b/tests/Geometry/3D/CylinderTests.cs index 9c72d64..d364fd0 100644 --- a/tests/Geometry/3D/CylinderTests.cs +++ b/tests/Geometry/3D/CylinderTests.cs @@ -15,6 +15,7 @@ private void CanCompute_PointAtCylinder() Assert.Equal(actual, expected); } + [Fact] public void CanCreate_FromDefaultConstructor() { @@ -24,6 +25,7 @@ public void CanCreate_FromDefaultConstructor() Assert.Equal(1, cyl.Height); } + [Fact] public void CanCreate_FromPlaneHeightRadius() { diff --git a/tests/Geometry/3D/Intersect3dTests.cs b/tests/Geometry/3D/Intersect3dTests.cs index 094a0d3..8b73d74 100644 --- a/tests/Geometry/3D/Intersect3dTests.cs +++ b/tests/Geometry/3D/Intersect3dTests.cs @@ -34,6 +34,7 @@ public void CanIntersect_Line_Plane() Assert.Equal(expected, actual); } + [Fact] public void CannotIntersect_Line_Plane_DoNotTouch() { @@ -47,6 +48,7 @@ public void CannotIntersect_Line_Plane_DoNotTouch() Assert.Null(actual); } + [Fact] public void CannotIntersect_Line_Plane_DoNotTouchAndAreParallel() { @@ -60,6 +62,7 @@ public void CannotIntersect_Line_Plane_DoNotTouchAndAreParallel() Assert.Null(actual); } + [Fact] public void CannotIntersect_Line_Plane_Parallel() { diff --git a/tests/Geometry/3D/LineTests.cs b/tests/Geometry/3D/LineTests.cs index 7b66e78..8f44fe0 100644 --- a/tests/Geometry/3D/LineTests.cs +++ b/tests/Geometry/3D/LineTests.cs @@ -8,9 +8,11 @@ public class Line3dTests : CurveBaseTests { internal Line TestLine = new Line(Point3d.WorldOrigin, new Point3d(1, 1, 1)); + [Fact] public override void CanCheck_Validity() => Assert.True(this.TestLine.IsValid); + [Fact] public override void CanGet_BiNormal() { @@ -18,9 +20,11 @@ public override void CanGet_BiNormal() Assert.True(biNorm != null); } + [Fact] public override void CanGet_Length() => Assert.True(this.TestLine.Length == Math.Sqrt(3)); + [Fact] public override void CanGet_Normal() { @@ -31,6 +35,7 @@ public override void CanGet_Normal() line.NormalAt(0.5); } + [Fact] public override void CanGet_PerpFrame() { @@ -38,6 +43,7 @@ public override void CanGet_PerpFrame() Assert.True(biNorm != null); } + [Fact] public override void CanGet_PointAt() { @@ -45,6 +51,7 @@ public override void CanGet_PointAt() Assert.True(pt == new Point3d(0.5, 0.5, 0.5)); } + [Fact] public override void CanGet_Tangent() { diff --git a/tests/Geometry/3D/MeshFaceTests.cs b/tests/Geometry/3D/MeshFaceTests.cs index 529b298..4a56a6f 100644 --- a/tests/Geometry/3D/MeshFaceTests.cs +++ b/tests/Geometry/3D/MeshFaceTests.cs @@ -23,43 +23,37 @@ private static Mesh FlatSquare } } + [Fact] public void CanCompute_FaceArea() => - FlatSquare.Faces.ForEach(face => - { - Assert.Equal(0.5, face.Area); - }); + FlatSquare.Faces.ForEach(face => { Assert.Equal(0.5, face.Area); }); + [Fact] public void CanCompute_FaceNormal() => - FlatSquare.Faces.ForEach(face => - { - Assert.Equal(Vector3d.UnitZ, face.Normal); - }); + FlatSquare.Faces.ForEach(face => { Assert.Equal(Vector3d.UnitZ, face.Normal); }); + [Fact] public void CanCompute_FaceTopology() => - FlatSquare.Faces.ForEach(face => - { - Assert.Single(face.AdjacentFaces()); - Assert.Equal(3, face.AdjacentEdges().Count); - Assert.Equal(3, face.AdjacentCorners().Count); - Assert.Equal(3, face.AdjacentHalfEdges().Count); - Assert.Equal(3, face.AdjacentVertices().Count); - }); + FlatSquare.Faces.ForEach( + face => + { + Assert.Single(face.AdjacentFaces()); + Assert.Equal(3, face.AdjacentEdges().Count); + Assert.Equal(3, face.AdjacentCorners().Count); + Assert.Equal(3, face.AdjacentHalfEdges().Count); + Assert.Equal(3, face.AdjacentVertices().Count); + }); + [Fact] public void CanConvert_ToString() => - FlatSquare.Faces.ForEach(face => - { - Assert.NotNull(face.ToString()); - }); + FlatSquare.Faces.ForEach(face => { Assert.NotNull(face.ToString()); }); + [Fact] public void CanGet_Index() => - FlatSquare.Faces.ForEach(face => - { - Assert.True(face.Index >= 0); - }); + FlatSquare.Faces.ForEach(face => { Assert.True(face.Index >= 0); }); } } \ No newline at end of file diff --git a/tests/Geometry/3D/MeshGeometryTests.cs b/tests/Geometry/3D/MeshGeometryTests.cs index f547115..1770a38 100644 --- a/tests/Geometry/3D/MeshGeometryTests.cs +++ b/tests/Geometry/3D/MeshGeometryTests.cs @@ -37,21 +37,26 @@ public Mesh FlatTriangle } } + [Fact] private void CanCompute_CornerAngles() => - this.FlatSquare.Corners.ForEach(corner => - { - var angle = MeshGeometry.Angle(corner); - Assert.True(Math.Abs(angle - (0.5 * Math.PI)) < Settings.Tolerance); - }); + this.FlatSquare.Corners.ForEach( + corner => + { + var angle = MeshGeometry.Angle(corner); + Assert.True(Math.Abs(angle - 0.5 * Math.PI) < Settings.Tolerance); + }); + [Fact] private void CanCompute_EdgeLengths() => - this.FlatSquare.Edges.ForEach(edge => - { - var length = MeshGeometry.Length(edge); - Assert.True(Math.Abs(length - 1) < Settings.Tolerance); - }); + this.FlatSquare.Edges.ForEach( + edge => + { + var length = MeshGeometry.Length(edge); + Assert.True(Math.Abs(length - 1) < Settings.Tolerance); + }); + [Fact] private void CanCompute_FaceArea() @@ -60,6 +65,7 @@ private void CanCompute_FaceArea() Assert.True(Math.Abs(area - 0.5) < Settings.Tolerance); } + [Fact] private void CanCompute_FaceNormal() { @@ -67,6 +73,7 @@ private void CanCompute_FaceNormal() Assert.Equal(Vector3d.UnitZ, normal); } + [Fact] private void CanCompute_MeshArea() { @@ -74,16 +81,18 @@ private void CanCompute_MeshArea() Assert.True(Math.Abs(area - 0.5) < Settings.Tolerance); } + [Fact] private void CanCompute_VertexNormal() => - this.FlatTriangle.Vertices.ForEach(vertex => - { - var normal = MeshGeometry.VertexNormalAngleWeighted(vertex); - Assert.Equal(Vector3d.UnitZ, normal); - normal = MeshGeometry.VertexNormalEquallyWeighted(vertex); - Assert.Equal(Vector3d.UnitZ, normal); - normal = MeshGeometry.VertexNormalAreaWeighted(vertex); - Assert.Equal(Vector3d.UnitZ, normal); - }); + this.FlatTriangle.Vertices.ForEach( + vertex => + { + var normal = MeshGeometry.VertexNormalAngleWeighted(vertex); + Assert.Equal(Vector3d.UnitZ, normal); + normal = MeshGeometry.VertexNormalEquallyWeighted(vertex); + Assert.Equal(Vector3d.UnitZ, normal); + normal = MeshGeometry.VertexNormalAreaWeighted(vertex); + Assert.Equal(Vector3d.UnitZ, normal); + }); } } \ No newline at end of file diff --git a/tests/Geometry/3D/MeshPointTests.cs b/tests/Geometry/3D/MeshPointTests.cs index bb2310e..d7c80f8 100644 --- a/tests/Geometry/3D/MeshPointTests.cs +++ b/tests/Geometry/3D/MeshPointTests.cs @@ -15,6 +15,7 @@ public void CanConstruct_FromNumbers() Assert.Equal(0.6, pt.W); } + [Fact] public void CanConvert_ToString() { diff --git a/tests/Geometry/3D/MeshTests.cs b/tests/Geometry/3D/MeshTests.cs index 9ef0c3e..a379a0e 100644 --- a/tests/Geometry/3D/MeshTests.cs +++ b/tests/Geometry/3D/MeshTests.cs @@ -22,6 +22,7 @@ public Mesh FlatSquare } } + [Fact] public void CanCheck_QuadMesh() { @@ -31,6 +32,7 @@ public void CanCheck_QuadMesh() Assert.False(mesh.IsTriangularMesh()); } + [Fact] public void CanCompute_Boundary() { @@ -39,6 +41,7 @@ public void CanCompute_Boundary() Assert.Single(mesh.Boundaries); } + [Fact] public void CanCompute_EulerCharacteristic() { @@ -46,6 +49,7 @@ public void CanCompute_EulerCharacteristic() Assert.Equal(1, mesh.EulerCharacteristic); } + [Fact] public void CanConvert_ToString() { @@ -53,6 +57,7 @@ public void CanConvert_ToString() Assert.IsType(this.FlatSquare.GetMeshInfo()); } + [Fact] public void CanCreate_Mesh() { @@ -62,6 +67,7 @@ public void CanCreate_Mesh() Assert.NotEmpty(mesh.Faces); } + [Fact] public void CanDetect_IsolatedFaces() { @@ -69,6 +75,7 @@ public void CanDetect_IsolatedFaces() Assert.False(mesh.HasIsolatedFaces()); } + [Fact] public void CanDetect_IsolatedVertices() { diff --git a/tests/Geometry/3D/MeshVertexTests.cs b/tests/Geometry/3D/MeshVertexTests.cs index 9213945..e1c3ea9 100644 --- a/tests/Geometry/3D/MeshVertexTests.cs +++ b/tests/Geometry/3D/MeshVertexTests.cs @@ -22,25 +22,26 @@ public Mesh FlatSquare } } + [Fact] public void CanCompute_Adjacencies() => - this.FlatSquare.Vertices.ForEach(vertex => - { - Assert.Single(vertex.AdjacentFaces()); - Assert.Single(vertex.AdjacentCorners()); - Assert.Equal(2, vertex.AdjacentVertices().Count); - Assert.Equal(2, vertex.AdjacentEdges().Count); - Assert.Equal(2, vertex.AdjacentHalfEdges().Count); - Assert.Equal(2, vertex.Valence()); - Assert.True(vertex.OnBoundary()); - }); + this.FlatSquare.Vertices.ForEach( + vertex => + { + Assert.Single(vertex.AdjacentFaces()); + Assert.Single(vertex.AdjacentCorners()); + Assert.Equal(2, vertex.AdjacentVertices().Count); + Assert.Equal(2, vertex.AdjacentEdges().Count); + Assert.Equal(2, vertex.AdjacentHalfEdges().Count); + Assert.Equal(2, vertex.Valence()); + Assert.True(vertex.OnBoundary()); + }); + [Fact] public void CanConvert_ToString() => - this.FlatSquare.Vertices.ForEach(vertex => - { - Assert.NotNull(vertex.ToString()); - }); + this.FlatSquare.Vertices.ForEach(vertex => { Assert.NotNull(vertex.ToString()); }); + [Fact] public void CanCreate() diff --git a/tests/Geometry/3D/NurbsCurveData.cs b/tests/Geometry/3D/NurbsCurveData.cs index df08e33..f39c4e7 100644 --- a/tests/Geometry/3D/NurbsCurveData.cs +++ b/tests/Geometry/3D/NurbsCurveData.cs @@ -20,6 +20,7 @@ public IEnumerator GetEnumerator() yield return new object[] {1.0}; } + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); } } \ No newline at end of file diff --git a/tests/Geometry/3D/NurbsCurveTests.cs b/tests/Geometry/3D/NurbsCurveTests.cs index 025a221..f1c3ac8 100644 --- a/tests/Geometry/3D/NurbsCurveTests.cs +++ b/tests/Geometry/3D/NurbsCurveTests.cs @@ -1,17 +1,15 @@ -using System; using System.Collections.Generic; using System.Linq; using Paramdigma.Core.Geometry; +using Paramdigma.Core.Tests.Conversions; using Xunit; using Xunit.Abstractions; -using Paramdigma.Core.Tests.Conversions; using RG = Rhino.Geometry; namespace Paramdigma.Core.Tests.Geometry._3D { public class NurbsCurveTests { - private readonly ITestOutputHelper testOutputHelper; private readonly List controlPoints = new List { new Point3d(0, 0, 0), @@ -20,23 +18,28 @@ public class NurbsCurveTests new Point3d(0, 7, 0), new Point3d(0, 9, 0) }; - - private NurbsCurve curve => new NurbsCurve(this.controlPoints,3); + + private readonly ITestOutputHelper testOutputHelper; + + + public NurbsCurveTests(ITestOutputHelper testOutputHelper) => + this.testOutputHelper = testOutputHelper; + + + private NurbsCurve curve => new NurbsCurve(this.controlPoints, 3); private RG.NurbsCurve rhCurve { get { - var rhcrv = RG.Curve.CreateControlPointCurve(this.controlPoints.Select(pt => pt.ToRhino()), 3); + var rhcrv = RG.Curve.CreateControlPointCurve( + this.controlPoints.Select(pt => pt.ToRhino()), + 3); rhcrv.Domain = new RG.Interval(0, 1); return rhcrv.ToNurbsCurve(); } } - - public NurbsCurveTests(ITestOutputHelper testOutputHelper) - { - this.testOutputHelper = testOutputHelper; - } + [Theory] [InlineData(0)] @@ -45,11 +48,12 @@ public NurbsCurveTests(ITestOutputHelper testOutputHelper) [InlineData(1.0)] public void CanGet_PointAt(double t) { - var point = curve.PointAt(t); - var rhPoint = rhCurve.PointAt(t); + var point = this.curve.PointAt(t); + var rhPoint = this.rhCurve.PointAt(t); Assert.True(point.DistanceTo(rhPoint.ToCore()) < Settings.Tolerance); } - + + [Theory] [InlineData(0)] [InlineData(0.1)] @@ -57,21 +61,23 @@ public void CanGet_PointAt(double t) [InlineData(1.0)] public void CanGet_TangentAt(double t) { - var vector = curve.TangentAt(t); - var rhVector = rhCurve.TangentAt(t); + var vector = this.curve.TangentAt(t); + var rhVector = this.rhCurve.TangentAt(t); Assert.True((vector - rhVector.ToCore()).Length < Settings.Tolerance); } - + + [Theory] [ClassData(typeof(NurbsCurveUnitParamData))] public void CanGet_NormalAt(double t) { - var vector = curve.NormalAt(t); - var rhVector = rhCurve.DerivativeAt(t, 2)[2]; + var vector = this.curve.NormalAt(t); + var rhVector = this.rhCurve.DerivativeAt(t, 2)[2]; var length = (vector - rhVector.ToCore().Unit()).Length; Assert.True(length < Settings.Tolerance); } - + + [Theory] [InlineData(0)] [InlineData(0.1)] @@ -79,8 +85,8 @@ public void CanGet_NormalAt(double t) [InlineData(1.0)] public void CanGet_BiNormalAt(double t) { - var vector = curve.BinormalAt(t); - var rhVector = rhCurve.DerivativeAt(t, 3)[3]; + var vector = this.curve.BinormalAt(t); + var rhVector = this.rhCurve.DerivativeAt(t, 3)[3]; var length = (vector - rhVector.ToCore().Unit()).Length; Assert.True(length < Settings.Tolerance); } diff --git a/tests/Geometry/3D/NurbsTests.cs b/tests/Geometry/3D/NurbsTests.cs index d951eb1..ced047f 100644 --- a/tests/Geometry/3D/NurbsTests.cs +++ b/tests/Geometry/3D/NurbsTests.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Diagnostics; using Paramdigma.Core.Collections; @@ -12,21 +11,24 @@ public class NurbsTests { private readonly ITestOutputHelper testOutputHelper; - public NurbsTests(ITestOutputHelper testOutputHelper) - { + + public NurbsTests(ITestOutputHelper testOutputHelper) => this.testOutputHelper = testOutputHelper; - } + public Matrix FlatGrid(int size) { var m = new Matrix(size); for (var i = 0; i < size; i++) - for (var j = 0; j < size; j++) - m[i, j] = new Point3d(i, j, 0); + { + for (var j = 0; j < size; j++) + m[i, j] = new Point3d(i, j, 0); + } return m; } + [Theory] [InlineData(0.0, 0.0)] public void Decasteljau2_Works(double u, double v) @@ -38,6 +40,7 @@ public void Decasteljau2_Works(double u, double v) Assert.NotNull(pt); } + [Fact] public void Decasteljau1_Works() { @@ -47,6 +50,7 @@ public void Decasteljau1_Works() var pt = NurbsCalculator.DeCasteljau1(points.ToArray(), points.Count - 1, 1); } + //[Fact] public void NurbsCurvePoint_Works() { @@ -62,15 +66,31 @@ public void NurbsCurvePoint_Works() const int n = 100; for (var i = 0; i <= n; i++) { - var pt = NurbsCalculator.CurvePoint(3, 1, u, new[] {p0, p1, p2, p3}, (double)i / n); - var pt2 = NurbsCalculator.CurvePoint(3, 2, u2, new[] {p0, p1, p2, p3}, (double)i / n); - var pt3 = NurbsCalculator.CurvePoint(3, 3, u3, new[] {p0, p1, p2, p3}, (double)i / n); + var pt = NurbsCalculator.CurvePoint( + 3, + 1, + u, + new[] {p0, p1, p2, p3}, + ( double ) i / n); + var pt2 = NurbsCalculator.CurvePoint( + 3, + 2, + u2, + new[] {p0, p1, p2, p3}, + ( double ) i / n); + var pt3 = NurbsCalculator.CurvePoint( + 3, + 3, + u3, + new[] {p0, p1, p2, p3}, + ( double ) i / n); } watch.Stop(); - testOutputHelper.WriteLine(watch.Elapsed.ToString()); + this.testOutputHelper.WriteLine(watch.Elapsed.ToString()); } + [Fact] public void TestKnotVector() { diff --git a/tests/Geometry/3D/PlaneTests.cs b/tests/Geometry/3D/PlaneTests.cs index 9644995..04aaaee 100644 --- a/tests/Geometry/3D/PlaneTests.cs +++ b/tests/Geometry/3D/PlaneTests.cs @@ -16,6 +16,7 @@ public void CanBe_Cloned() Assert.True(!ReferenceEquals(pln, plnC)); } + [Fact] public void CanBe_Compared() { @@ -25,6 +26,7 @@ public void CanBe_Compared() Assert.Equal(expected.GetHashCode(), actual.GetHashCode()); } + [Fact] public void CanBe_Created() { @@ -37,6 +39,7 @@ public void CanBe_Created() var planeC = new Plane(ptC, ptA, ptB); } + [Fact] public void CanBe_Flipped() { @@ -48,6 +51,7 @@ public void CanBe_Flipped() Assert.Equal(xy.ZAxis, -flipped.ZAxis); } + [Fact] public void CanCompute_ClosestPoint() { @@ -60,6 +64,7 @@ public void CanCompute_ClosestPoint() Assert.True(dist == 1); } + [Fact] public void CanCompute_Points() { @@ -72,6 +77,7 @@ public void CanCompute_Points() Assert.True(ptB == expectedPtB); } + [Fact] public void CanConvert_ToString() { @@ -80,6 +86,7 @@ public void CanConvert_ToString() Console.WriteLine(s); } + [Fact] public void CanCreate_SpecialPlanes() { @@ -88,6 +95,7 @@ public void CanCreate_SpecialPlanes() var ptXZ = Plane.WorldXZ; } + [Fact] public void CanRemap_FromXYPlane() { @@ -98,6 +106,7 @@ public void CanRemap_FromXYPlane() Assert.Equal(expected, result); } + [Fact] public void CanRemap_ToXYPlane() { @@ -108,6 +117,7 @@ public void CanRemap_ToXYPlane() Assert.Equal(expected, result); } + [Fact] public void LinearPoints_ThrowError() { diff --git a/tests/Geometry/3D/Point3dData.cs b/tests/Geometry/3D/Point3dData.cs index 6168865..45eef2b 100644 --- a/tests/Geometry/3D/Point3dData.cs +++ b/tests/Geometry/3D/Point3dData.cs @@ -12,6 +12,7 @@ public IEnumerator GetEnumerator() yield return new object[] {new Point3d(2, 2, -1), new Point3d(2, 2, -1)}; } + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); } } \ No newline at end of file diff --git a/tests/Geometry/3D/Point3dTests.cs b/tests/Geometry/3D/Point3dTests.cs index ce6f503..a037ded 100644 --- a/tests/Geometry/3D/Point3dTests.cs +++ b/tests/Geometry/3D/Point3dTests.cs @@ -6,6 +6,14 @@ namespace Paramdigma.Core.Tests.Geometry { public class Point3dTests { + public static IEnumerable UnsetPointData => new List + { + new object[] {new Point3d()}, + new object[] {Point3d.Unset}, + new object[] {new Point4d()} + }; + + [Theory] [ClassData(typeof(Point3dEqualDataset))] public void EqualsAndHashCode_HaveConsistentResults(Point3d pt, Point3d pt2) @@ -17,6 +25,7 @@ public void EqualsAndHashCode_HaveConsistentResults(Point3d pt, Point3d pt2) Assert.False(pt != pt2); } + [Theory] [MemberData(nameof(UnsetPointData))] public void CanToggleUnset_WithX(BasePoint pt) @@ -26,6 +35,7 @@ public void CanToggleUnset_WithX(BasePoint pt) Assert.False(pt.IsUnset); } + [Theory] [MemberData(nameof(UnsetPointData))] public void CanToggleUnset_WithY(BasePoint pt) @@ -35,6 +45,7 @@ public void CanToggleUnset_WithY(BasePoint pt) Assert.False(pt.IsUnset); } + [Theory] [MemberData(nameof(UnsetPointData))] public void CanToggleUnset_WithZ(BasePoint pt) @@ -44,7 +55,6 @@ public void CanToggleUnset_WithZ(BasePoint pt) Assert.False(pt.IsUnset); } - public static IEnumerable UnsetPointData => new List {new object[] {new Point3d()}, new object[] {Point3d.Unset}, new object[] {new Point4d()}}; [Fact] public void Can_OperateOnItself() @@ -65,6 +75,7 @@ public void Can_OperateOnItself() Assert.True(pt2 == new Point3d(-1, 0, 0)); } + [Fact] public void CanBe_Added() { @@ -78,6 +89,7 @@ public void CanBe_Added() Assert.True(ptA + ptB == ptResult); } + [Fact] public void CanBe_Created() { @@ -86,12 +98,13 @@ public void CanBe_Created() var pt4 = new Point4d(1, 0, 0, 1); var npt2 = new Point3d(pt2); var npt4 = new Point3d(pt4); - var npt5 = (Point3d)pt4; + var npt5 = ( Point3d ) pt4; Assert.True(pt3 == npt2); Assert.True(pt3 == npt4); Assert.True(pt3 == npt5); } + [Fact] public void CanBe_Divided() { @@ -104,6 +117,7 @@ public void CanBe_Divided() Assert.True(ptA / m == ptResult); } + [Fact] public void CanBe_Multiplied() { @@ -116,6 +130,7 @@ public void CanBe_Multiplied() Assert.True(ptA * m == ptResult); } + [Fact] public void CanBe_Negated() { @@ -127,6 +142,7 @@ public void CanBe_Negated() Assert.True(-ptA == ptResult); } + [Fact] public void CanBe_Substracted() { @@ -135,12 +151,13 @@ public void CanBe_Substracted() const double c = 4.11; var ptA = new Point3d(a, b, c); var v = new Vector3d(b, c, a); - var ptB = (Point3d)v; + var ptB = ( Point3d ) v; var ptResult = new Point3d(a - b, b - c, c - a); Assert.True(ptA - ptB == ptResult); Assert.True(ptA - v == ptResult); } + [Fact] public void CanConvert_ToArray() { diff --git a/tests/Geometry/3D/Point4dTests.cs b/tests/Geometry/3D/Point4dTests.cs index d6df987..a4373d9 100644 --- a/tests/Geometry/3D/Point4dTests.cs +++ b/tests/Geometry/3D/Point4dTests.cs @@ -19,6 +19,7 @@ public void CanBe_Added() Assert.True(ptA + ptB == ptResult); } + [Fact] public void CanBe_Added_WithVector() { @@ -33,6 +34,7 @@ public void CanBe_Added_WithVector() Assert.True(ptA + v == ptResult); } + [Fact] public void CanBe_Created() { @@ -43,6 +45,7 @@ public void CanBe_Created() Assert.Equal(pt42, pt4); } + [Fact] public void CanBe_Divided() { @@ -56,6 +59,7 @@ public void CanBe_Divided() Assert.True(ptA / m == ptResult); } + [Fact] public void CanBe_Multiplied() { @@ -70,6 +74,7 @@ public void CanBe_Multiplied() Assert.True(m * ptA == ptResult); } + [Fact] public void CanBe_Negated() { @@ -83,6 +88,7 @@ public void CanBe_Negated() Assert.True(-ptA == ptResult); } + [Fact] public void CanBe_Subtracted() { @@ -98,6 +104,7 @@ public void CanBe_Subtracted() Assert.Equal(expected, actual); } + [Fact] public void CanCheck_Equality() { @@ -107,8 +114,8 @@ public void CanCheck_Equality() const double d = 1.344; var ptA = new Point4d(a, b, c, d); - var expectedEqual = new Point4d(a + (Settings.Tolerance / 2), b, c, d); - var expectedNotEqual = new Point4d(a + (Settings.Tolerance * 2), b, c, d); + var expectedEqual = new Point4d(a + Settings.Tolerance / 2, b, c, d); + var expectedNotEqual = new Point4d(a + Settings.Tolerance * 2, b, c, d); Assert.True(ptA == expectedEqual); Assert.Equal(ptA.GetHashCode(), expectedEqual.GetHashCode()); Assert.True(ptA != expectedNotEqual); @@ -116,6 +123,7 @@ public void CanCheck_Equality() Assert.False(ptA == null); } + [Fact] public void CanCreate_FromPointAndWeight() { @@ -126,6 +134,7 @@ public void CanCreate_FromPointAndWeight() Assert.Equal(weight, pt4.Weight); } + [Fact] public void CanToggle_IsUnset_OnWeightChange() { diff --git a/tests/Geometry/3D/Polyline3dTests.cs b/tests/Geometry/3D/Polyline3dTests.cs index 5b8acae..4d5dcfc 100644 --- a/tests/Geometry/3D/Polyline3dTests.cs +++ b/tests/Geometry/3D/Polyline3dTests.cs @@ -17,6 +17,7 @@ private Polyline GetTestPolyline(int count) return new Polyline(knots); } + [Fact] public void CanAccess_UpdatedSegmentList() { @@ -26,6 +27,7 @@ public void CanAccess_UpdatedSegmentList() Assert.Equal(4, poly.Segments.Count); } + [Fact] public void CanAdd_Knot() { @@ -37,6 +39,7 @@ public void CanAdd_Knot() Assert.Equal(knotCount + 1, poly.Knots.Count); } + [Fact] public override void CanCheck_Validity() { @@ -50,6 +53,7 @@ public override void CanCheck_Validity() Assert.False(poly.IsValid); } + [Fact] public void CanEnumerate_Knots() { @@ -58,6 +62,7 @@ public void CanEnumerate_Knots() Assert.NotNull(knot); } + [Fact] public override void CanGet_BiNormal() { @@ -66,6 +71,7 @@ public override void CanGet_BiNormal() Assert.NotNull(poly.BinormalAt(1)); } + [Fact] public override void CanGet_Length() { @@ -73,10 +79,11 @@ public override void CanGet_Length() { var poly = this.GetTestPolyline(i); var length = poly.Length; - Assert.True(length == i, $"Length {length} is not {i}"); + Assert.True(Math.Abs(length - i) < Settings.Tolerance, $"Length {length} is not {i}"); } } + [Fact] public override void CanGet_Normal() { @@ -85,6 +92,7 @@ public override void CanGet_Normal() Assert.NotNull(poly.NormalAt(1)); } + [Fact] public override void CanGet_PerpFrame() { @@ -93,6 +101,7 @@ public override void CanGet_PerpFrame() Assert.NotNull(poly.FrameAt(1)); } + [Fact] public override void CanGet_PointAt() { @@ -102,6 +111,7 @@ public override void CanGet_PointAt() Assert.Equal(expected, pt); } + [Fact] public override void CanGet_Tangent() { @@ -110,6 +120,7 @@ public override void CanGet_Tangent() Assert.NotNull(poly.TangentAt(1)); } + [Fact] public void CanInsert_Knot() { @@ -122,6 +133,7 @@ public void CanInsert_Knot() Assert.Equal(poly[0], poly[2]); } + [Fact] public void CanRemove_Knot() { @@ -136,6 +148,7 @@ public void CanRemove_Knot() Assert.NotEqual(unexpected, poly[0]); } + [Fact] public void CanRemove_Knot_ThrowsException() { @@ -145,6 +158,7 @@ public void CanRemove_Knot_ThrowsException() Assert.Throws(() => poly2.RemoveKnotAt(0)); } + [Fact] public void CanRemove_KnotAtIndex() { @@ -157,6 +171,7 @@ public void CanRemove_KnotAtIndex() Assert.Equal(knotCount - 1, poly.Knots.Count); } + [Fact] public void CanToggle_IsClosed() { diff --git a/tests/Geometry/3D/Ray3dTests.cs b/tests/Geometry/3D/Ray3dTests.cs index 723c285..c01562f 100644 --- a/tests/Geometry/3D/Ray3dTests.cs +++ b/tests/Geometry/3D/Ray3dTests.cs @@ -15,6 +15,7 @@ public void CanCompute_PointAt() Assert.Equal(expected, actual); } + [Fact] public void CanCreate_AndThrowExceptions() { diff --git a/tests/Geometry/3D/SphereTests.cs b/tests/Geometry/3D/SphereTests.cs index 667fc4d..662585a 100644 --- a/tests/Geometry/3D/SphereTests.cs +++ b/tests/Geometry/3D/SphereTests.cs @@ -10,6 +10,7 @@ public class SphereTests [Fact] public void CanCompute_FrameAtParameter() { } + [Fact] public void CanCompute_NormalAtParameter() { @@ -19,6 +20,7 @@ public void CanCompute_NormalAtParameter() Assert.Equal(expected, actual); } + [Fact] public void ComputeClosestParam_ThenPointAtParam_GivesSamePoint() { @@ -30,6 +32,7 @@ public void ComputeClosestParam_ThenPointAtParam_GivesSamePoint() Assert.Equal(pt, sphere.PointAt(param)); } + [Fact] public void ComputeClosestPoint_GivesAccurateResult() { @@ -38,6 +41,7 @@ public void ComputeClosestPoint_GivesAccurateResult() Assert.Equal(new Point3d(1, 0, 0), sphere.ClosestPointTo(pt)); } + [Fact] public void ComputeDistance_GivesAccurateResult() { @@ -46,6 +50,7 @@ public void ComputeDistance_GivesAccurateResult() Assert.Equal(3.0, sphere.DistanceTo(pt)); } + [Fact] public void Create_SphereWithEmptyConstructor_ReturnsXYPlaneUnitSphere() { @@ -56,6 +61,7 @@ public void Create_SphereWithEmptyConstructor_ReturnsXYPlaneUnitSphere() Assert.Equal(Interval.Unit, sphere.DomainV); } + [Fact] public void Create_SphereWithPlaneAndRadius_ReturnsValidSphere() { @@ -66,7 +72,9 @@ public void Create_SphereWithPlaneAndRadius_ReturnsValidSphere() Assert.Equal(Interval.Unit, sphere.DomainV); } + [Fact] - public void Create_SphereWithZeroRadius_ThrowsException() => Assert.Throws(() => new Sphere(Plane.WorldXY, 0)); + public void Create_SphereWithZeroRadius_ThrowsException() => + Assert.Throws(() => new Sphere(Plane.WorldXY, 0)); } } \ No newline at end of file diff --git a/tests/Geometry/3D/Vector3dTests.cs b/tests/Geometry/3D/Vector3dTests.cs index af907c2..6d3ebcd 100644 --- a/tests/Geometry/3D/Vector3dTests.cs +++ b/tests/Geometry/3D/Vector3dTests.cs @@ -19,6 +19,7 @@ public void Can_ComputeAngle() Assert.True(Math.Abs(a2 - q) <= Settings.Tolerance); } + [Fact] public void CanBe_Added() { @@ -32,6 +33,7 @@ public void CanBe_Added() Assert.True(vA + vB == ptResult); } + [Fact] public void CanBe_ConvertedToString() { @@ -41,6 +43,7 @@ public void CanBe_ConvertedToString() Assert.True(s == result); } + [Fact] public void CanBe_Created() { @@ -53,6 +56,7 @@ public void CanBe_Created() Assert.True(pt == newVp); } + [Fact] public void CanBe_Divided() { @@ -65,6 +69,7 @@ public void CanBe_Divided() Assert.True(v / m == ptResult); } + [Fact] public void CanBe_Multiplied() { @@ -77,6 +82,7 @@ public void CanBe_Multiplied() Assert.True(v * m == ptResult); } + [Fact] public void CanBe_Negated() { @@ -88,6 +94,7 @@ public void CanBe_Negated() Assert.True(-v == ptResult); } + [Fact] public void CanBe_Substracted() { @@ -100,6 +107,7 @@ public void CanBe_Substracted() Assert.True(vA - vB == ptResult); } + [Fact] public void EqualsAndHashCode_HaveConsistentResults() { diff --git a/tests/Geometry/3D/VectorNd_Tests.cs b/tests/Geometry/3D/VectorNd_Tests.cs index 3ac8c0b..4aac8b1 100644 --- a/tests/Geometry/3D/VectorNd_Tests.cs +++ b/tests/Geometry/3D/VectorNd_Tests.cs @@ -7,15 +7,59 @@ namespace Paramdigma.Core.Tests { public class VectorNdTests : VectorEntityTests { - public static IEnumerable VectorAddData => new List {new object[] {new VectorNd(0, 0, 0, 9, 3), new VectorNd(4, 5, 6), new VectorNd(4, 5, 6, 9, 3)}, new object[] {new VectorNd(3, 5, 0, 3), new VectorNd(4, 5, 6, 1, 3, 5), new VectorNd(7, 10, 6, 4, 3, 5)}}; + public static IEnumerable VectorAddData => new List + { + new object[] + { + new VectorNd(0, 0, 0, 9, 3), new VectorNd(4, 5, 6), new VectorNd(4, 5, 6, 9, 3) + }, + new object[] + { + new VectorNd(3, 5, 0, 3), + new VectorNd( + 4, + 5, + 6, + 1, + 3, + 5), + new VectorNd( + 7, + 10, + 6, + 4, + 3, + 5) + } + }; + + public static IEnumerable VectorDivideData => new List + { + new object[] {new VectorNd(0, 0, 0), 4, new VectorNd(0, 0, 0)}, + new object[] {new VectorNd(3, 5, 1), 2, new VectorNd(1.5, 2.5, 0.5)} + }; - public static IEnumerable VectorDivideData => new List {new object[] {new VectorNd(0, 0, 0), 4, new VectorNd(0, 0, 0)}, new object[] {new VectorNd(3, 5, 1), 2, new VectorNd(1.5, 2.5, 0.5)}}; + public static IEnumerable VectorMultiplyData => new List + { + new object[] {new VectorNd(0, 0, 0), 5, new VectorNd(0, 0, 0)}, + new object[] {new VectorNd(3, 5, 2), 6, new VectorNd(18, 30, 12)} + }; - public static IEnumerable VectorMultiplyData => new List {new object[] {new VectorNd(0, 0, 0), 5, new VectorNd(0, 0, 0)}, new object[] {new VectorNd(3, 5, 2), 6, new VectorNd(18, 30, 12)}}; + public static IEnumerable VectorSubstractData => new List + { + new object[] + { + new VectorNd(0, 0, 0), new VectorNd(4, 5, 6), new VectorNd(-4, -5, -6) + }, + new object[] {new VectorNd(3, 5, 0), new VectorNd(4, 5, 6), new VectorNd(-1, 0, -6)} + }; - public static IEnumerable VectorSubstractData => new List {new object[] {new VectorNd(0, 0, 0), new VectorNd(4, 5, 6), new VectorNd(-4, -5, -6)}, new object[] {new VectorNd(3, 5, 0), new VectorNd(4, 5, 6), new VectorNd(-1, 0, -6)}}; + public static IEnumerable IsEqualData => new List + { + new object[] {new VectorNd(3, 3, 3), new VectorNd(3, 3, 3 + 1E-12)}, + new object[] {new VectorNd(4, 5, 6), new VectorNd(4 + 1E-9, 5 + 1E-8, 6)} + }; - public static IEnumerable IsEqualData => new List {new object[] {new VectorNd(3, 3, 3), new VectorNd(3, 3, 3 + 1E-12)}, new object[] {new VectorNd(4, 5, 6), new VectorNd(4 + 1E-9, 5 + 1E-8, 6)}}; [Theory] [MemberData(nameof(VectorAddData))] @@ -25,36 +69,53 @@ public override void CanAdd(VectorNd a, VectorNd b, VectorNd expected) Assert.Equal(c, expected); } + [Theory] [MemberData(nameof(VectorAddData))] - public override void CanAdd_Itself(VectorNd a, VectorNd b, VectorNd expected) => Assert.Equal(a + b, expected); + public override void CanAdd_Itself(VectorNd a, VectorNd b, VectorNd expected) => + Assert.Equal(a + b, expected); + [Theory] [MemberData(nameof(VectorDivideData))] - public override void CanDivide_New(VectorNd a, double scalar, VectorNd expected) => Assert.Equal(a / scalar, expected); + public override void CanDivide_New(VectorNd a, double scalar, VectorNd expected) => + Assert.Equal(a / scalar, expected); + [Theory] [MemberData(nameof(VectorMultiplyData))] - public override void CanMultiply_New(VectorNd a, double scalar, VectorNd expected) => Assert.Equal(a * scalar, expected); + public override void CanMultiply_New(VectorNd a, double scalar, VectorNd expected) => + Assert.Equal(a * scalar, expected); + [Theory] [MemberData(nameof(VectorSubstractData))] - public override void CanSubstract_New(VectorNd a, VectorNd b, VectorNd expected) => Assert.Equal(a - b, expected); + public override void CanSubstract_New(VectorNd a, VectorNd b, VectorNd expected) => + Assert.Equal(a - b, expected); + [Theory] [MemberData(nameof(VectorSubstractData))] - public override void CanSubstract_ToItself(VectorNd a, VectorNd b, VectorNd expected) => Assert.Equal(a - b, expected); + public override void CanSubstract_ToItself(VectorNd a, VectorNd b, VectorNd expected) => + Assert.Equal(a - b, expected); + [Theory] [MemberData(nameof(IsEqualData))] - public override void IsEqual_HasEqualHashcodes(VectorNd a, VectorNd b) => Assert.Equal(a.GetHashCode(), b.GetHashCode()); + public override void IsEqual_HasEqualHashcodes(VectorNd a, VectorNd b) => + Assert.Equal(a.GetHashCode(), b.GetHashCode()); + [Theory] [MemberData(nameof(IsEqualData))] public override void IsEqual_WithinTolerance(VectorNd a, VectorNd b) => Assert.Equal(a, b); - public override void CanMultiply_Itself(VectorNd a, double scalar, VectorNd expected) => throw new NotImplementedException(); - public override void CanDivide_Itself(VectorNd a, double scalar, VectorNd expected) => throw new NotImplementedException(); + public override void CanMultiply_Itself(VectorNd a, double scalar, VectorNd expected) => + throw new NotImplementedException(); + + + public override void CanDivide_Itself(VectorNd a, double scalar, VectorNd expected) => + throw new NotImplementedException(); } } \ No newline at end of file diff --git a/tests/Optimization/GradientDescentOptionsTests.cs b/tests/Optimization/GradientDescentOptionsTests.cs index 3905317..294dd0b 100644 --- a/tests/Optimization/GradientDescentOptionsTests.cs +++ b/tests/Optimization/GradientDescentOptionsTests.cs @@ -19,6 +19,7 @@ public void CanCreate_Default() Assert.Equal(expected, actual); } + [Fact] public void CanCreate_DefaultSmall() { @@ -33,6 +34,7 @@ public void CanCreate_DefaultSmall() Assert.Equal(expected, actual); } + [Fact] public void CanCreate_FromExisting() { diff --git a/tests/Optimization/GradientDescentTests.cs b/tests/Optimization/GradientDescentTests.cs index 24b07f9..f6f8dd9 100644 --- a/tests/Optimization/GradientDescentTests.cs +++ b/tests/Optimization/GradientDescentTests.cs @@ -11,7 +11,10 @@ public class GradientDescentTests public void GradientDescent_Line() { var line = new Line(Point3d.WorldOrigin, new Point3d(1, 1, 0)); - var gd = new GradientDescent(GradientDescentOptions.Default) {Options = {MaxIterations = 1}}; + var gd = new GradientDescent(GradientDescentOptions.Default) + { + Options = {MaxIterations = 1} + }; var input = 1; gd.Options.MaxIterations = 100; diff --git a/tests/Optimization/KMeansClusteringTests.cs b/tests/Optimization/KMeansClusteringTests.cs index 82e586f..8b2df34 100644 --- a/tests/Optimization/KMeansClusteringTests.cs +++ b/tests/Optimization/KMeansClusteringTests.cs @@ -13,7 +13,10 @@ public class KMeansClusteringTests { private readonly ITestOutputHelper testOutputHelper; - public KMeansClusteringTests(ITestOutputHelper testOutputHelper) => this.testOutputHelper = testOutputHelper; + + public KMeansClusteringTests(ITestOutputHelper testOutputHelper) => + this.testOutputHelper = testOutputHelper; + public List createClusterAround(Point3d pt, double radius, int count) { @@ -31,6 +34,7 @@ public List createClusterAround(Point3d pt, double radius, int count) return cluster; } + [Theory] [InlineData(4, 20)] [InlineData(6, 18)] @@ -44,7 +48,7 @@ public void KMeans_MainTest(int expectedClusters, int expectedClusterCount) for (var i = 0; i < expectedClusters; i++) { - var pt = cir.PointAt((double)i / expectedClusters); + var pt = cir.PointAt(( double ) i / expectedClusters); pts.Add(pt); vectors.AddRange(this.createClusterAround(pt, 1, expectedClusterCount)); } @@ -63,19 +67,20 @@ public void KMeans_MainTest(int expectedClusters, int expectedClusterCount) //Assert the Iteration completed event has been raised Assert.True(eventCheck); // Then - kMeans.Clusters.ForEach(cluster => - { - Assert.NotEmpty(cluster); - var first = new Point3d(cluster[0][0], cluster[0][1], cluster[0][2]); - var closest = pts.First(pt => pt.DistanceTo(first) <= 2); - foreach (var vector in cluster) + kMeans.Clusters.ForEach( + cluster => { - var pt = new Point3d(vector[0], vector[1], vector[2]); - var dist = pt.DistanceTo(closest); - //testOutputHelper.WriteLine($"Distance: {dist}"); - Assert.True(dist <= 2, $"Distance was bigger: {dist}"); - } - }); + Assert.NotEmpty(cluster); + var first = new Point3d(cluster[0][0], cluster[0][1], cluster[0][2]); + var closest = pts.First(pt => pt.DistanceTo(first) <= 2); + foreach (var vector in cluster) + { + var pt = new Point3d(vector[0], vector[1], vector[2]); + var dist = pt.DistanceTo(closest); + //testOutputHelper.WriteLine($"Distance: {dist}"); + Assert.True(dist <= 2, $"Distance was bigger: {dist}"); + } + }); } } } \ No newline at end of file diff --git a/tests/RhinoConversions.cs b/tests/RhinoConversions.cs index 079289c..8af4873 100644 --- a/tests/RhinoConversions.cs +++ b/tests/RhinoConversions.cs @@ -5,12 +5,19 @@ namespace Paramdigma.Core.Tests.Conversions { public static class RhinoConversions { - public static Point3d ToCore(this RG.Point3d point) => new Point3d(point.X,point.Y,point.Z); - public static RG.Point3d ToRhino(this Point3d point) => new RG.Point3d(point.X,point.Y,point.Z); - - public static Vector3d ToCore(this RG.Vector3d vector) => new Vector3d(vector.X,vector.Y,vector.Z); - - public static RG.Vector3d ToRhino(this Vector3d vector) => new RG.Vector3d(vector.X,vector.Y,vector.Z); + public static Point3d ToCore(this RG.Point3d point) => + new Point3d(point.X, point.Y, point.Z); + + public static RG.Point3d ToRhino(this Point3d point) => + new RG.Point3d(point.X, point.Y, point.Z); + + + public static Vector3d ToCore(this RG.Vector3d vector) => + new Vector3d(vector.X, vector.Y, vector.Z); + + + public static RG.Vector3d ToRhino(this Vector3d vector) => + new RG.Vector3d(vector.X, vector.Y, vector.Z); } } \ No newline at end of file diff --git a/tests/Utilities/JsonFileDataAttribute.cs b/tests/Utilities/JsonFileDataAttribute.cs index d44d291..3603a01 100644 --- a/tests/Utilities/JsonFileDataAttribute.cs +++ b/tests/Utilities/JsonFileDataAttribute.cs @@ -10,13 +10,15 @@ namespace Paramdigma.Core.Tests { /// /// Data Attribute to extract text data out of JSON files - /// From: https://andrewlock.net/creating-a-custom-xunit-theory-test-dataattribute-to-load-data-from-json-files/ + /// From: + /// https://andrewlock.net/creating-a-custom-xunit-theory-test-dataattribute-to-load-data-from-json-files/ /// public class JsonFileDataAttribute : DataAttribute { private readonly string filePath; private readonly string propertyName; + /// /// Load data from a JSON file as the data source for a theory /// @@ -24,17 +26,22 @@ public class JsonFileDataAttribute : DataAttribute public JsonFileDataAttribute(string filePath) : this(filePath, null) { } + /// /// Load data from a JSON file as the data source for a theory /// /// The absolute or relative path to the JSON file to load - /// The name of the property on the JSON file that contains the data for the test + /// + /// The name of the property on the JSON file that contains the data for the + /// test + /// public JsonFileDataAttribute(string filePath, string propertyName) { this.filePath = filePath; this.propertyName = propertyName; } + /// public override IEnumerable GetData(MethodInfo testMethod) { @@ -43,8 +50,8 @@ public override IEnumerable GetData(MethodInfo testMethod) // Get the absolute path to the JSON file var path = Path.IsPathRooted(this.filePath) - ? this.filePath - : Path.GetRelativePath(Directory.GetCurrentDirectory(), this.filePath); + ? this.filePath + : Path.GetRelativePath(Directory.GetCurrentDirectory(), this.filePath); if (!File.Exists(path)) throw new ArgumentException($"Could not find file at path: {path}"); diff --git a/tests/Utilities/ResourcesTests.cs b/tests/Utilities/ResourcesTests.cs index a4b62b6..29eaa58 100644 --- a/tests/Utilities/ResourcesTests.cs +++ b/tests/Utilities/ResourcesTests.cs @@ -2,25 +2,31 @@ using Xunit; using Xunit.Abstractions; -namespace Paramdigma.Core.Utilities +namespace Paramdigma.Core.Tests { public class ResourcesTests { - public ResourcesTests(ITestOutputHelper testOutputHelper) => this.testOutputHelper = testOutputHelper; - private readonly ITestOutputHelper testOutputHelper; + + public ResourcesTests(ITestOutputHelper testOutputHelper) => + this.testOutputHelper = testOutputHelper; + + [Fact] public void ResetSettingsValues_FromResource() { - this.testOutputHelper.WriteLine(Settings.Tolerance.ToString(CultureInfo.CurrentCulture)); + this.testOutputHelper.WriteLine( + Settings.Tolerance.ToString(CultureInfo.CurrentCulture)); this.testOutputHelper.WriteLine(Settings.MaxDecimals.ToString()); this.testOutputHelper.WriteLine(Settings.GetDefaultTesselationLevel().ToString()); Settings.SetTolerance(0.1); - this.testOutputHelper.WriteLine(Settings.Tolerance.ToString(CultureInfo.CurrentCulture)); + this.testOutputHelper.WriteLine( + Settings.Tolerance.ToString(CultureInfo.CurrentCulture)); this.testOutputHelper.WriteLine(Settings.MaxDecimals.ToString()); Settings.Reset(); - this.testOutputHelper.WriteLine(Settings.Tolerance.ToString(CultureInfo.CurrentCulture)); + this.testOutputHelper.WriteLine( + Settings.Tolerance.ToString(CultureInfo.CurrentCulture)); this.testOutputHelper.WriteLine(Settings.MaxDecimals.ToString()); } }