All notable changes to this project are documented here. The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
12.0.0 - 2026-06-14
Area()now returns a non-negative magnitude. Previously it returned the signed shoelace area, which was negative for clockwise-wound polygons. (#7)MaxIndex()andFindMinMaxInOn()now throwInvalidOperationExceptionon an empty sequence, matching the LINQMax()/Min()convention (previouslyMaxIndex()threwArgumentOutOfRangeExceptionfrom an internal index access andFindMinMaxInOn()returned an inverted(double.MaxValue, double.MinValue)range).Scale()on an empty sequence still returns an empty sequence. (#9)AsTime(TimeSpan)no longer leaves a trailing", "separator and now returns"0 ms"forTimeSpan.Zero, consistent with theAsTime(milliseconds)overload. (#10)
- Removed the redundant
Scale<T>(IEnumerable<double>)overload whose type parameter was never used. Use the non-genericScale()(0..1 normalisation) instead. (#8)
- Black-box test coverage for previously-untested public surface (
HsVtoArgb,Head/Tail/HeadAndTail,PluralizeWhenNeeded,AsTime(TimeSpan),FindMinMaxInOn,Scale(),MaxIndex). - Code coverage upload to Codecov from CI, and a SonarCloud analysis workflow (see
SONAR_SETUP.md).
DeepCopyis now a dependency-free, reflection-based deep clone (copies private/inherited fields, preserves shared references and cycles, no[Serializable]/parameterless-ctor requirement).- Removed the
Newtonsoft.Jsondependency and theJsonSerializerSettingsoverload ofDeepCopy.
- Multi-targeted (
netstandard2.0,net8.0), modernised dependencies, fixed correctness bugs.
InClosedRange/InOpenRange(inverted semantics — useInRangeExclusive/InRangeInclusive) andConstructLine(useConstructLineFromRadians/ConstructLineFromDegrees).