GeomPP 0.14.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package GeomPP --version 0.14.0
                    
NuGet\Install-Package GeomPP -Version 0.14.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="GeomPP" Version="0.14.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="GeomPP" Version="0.14.0" />
                    
Directory.Packages.props
<PackageReference Include="GeomPP" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add GeomPP --version 0.14.0
                    
#r "nuget: GeomPP, 0.14.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package GeomPP@0.14.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=GeomPP&version=0.14.0
                    
Install as a Cake Addin
#tool nuget:?package=GeomPP&version=0.14.0
                    
Install as a Cake Tool

GeomPP — C# Bindings

C++/CLI bindings for geompp, targeting Windows x64.

Available on NuGet as GeomPP.

Supports .NET 8, .NET 9, .NET 10, and .NET Framework 4.8.

Changelog — full release notes for every version.


Install

dotnet add package GeomPP

or in your .csproj:

<PackageReference Include="GeomPP" Version="0.8.0" />
Platform .Net .Net Framework
Windows x64 8 · 9 · 10 4.8

Supported types

Type 2D 3D
Point
Vector
Line
Ray
LineSegment
Polyline
Triangle
Polygon
BBox
BBall
BRect2D
BPrism3D
Plane
View2D
GeometryCollection
WktParser

All types expose ToWkt(), FromWkt(), ToFile(), FromFile(), AlmostEquals(), and the same operators available in the C++ library.

Decimal precision for all <=> or AlmostEquals() or compare(a,b, epsilon) functions are managed by a global, thread local variable. It is best to set it up at the beginning of your program (in your main). The defalt is 3 decimals, or 0.001 tolorance.

G.Precision.DecimalPrecision = 6; // default: G.Precision.DP_THREE

Intersection methods return object (null when there is no intersection); use C# pattern matching to extract the result type:

var result = line.Intersection(segment);
if (result is G.Point2D p)       { /* point intersection */ }
if (result is G.LineSegment2D s) { /* overlap */ }

Platform note

GeomPP is built with C++/CLI and is Windows x64 only. It will not run on Linux, macOS, or 32-bit processes.


How to use it

You can look at the test suite to see detailed usage.

A quick list of code examples per topic is provided here.

👉 View Full Code Examples on Github


Build on Windows x64 manually

Build the C# DLL

# from the main directory, geompp

# .NET 8 (LTS, supported until Nov 2026)
msbuild geompp_csharp\GeomPP_Net8.vcxproj /p:Platform=x64 /p:GeomppBuildRoot="$PWD\build_win" [/p:Configuration=Release]

# .NET 9 (STS)
msbuild geompp_csharp\GeomPP_Net9.vcxproj /p:Platform=x64 /p:GeomppBuildRoot="$PWD\build_win" [/p:Configuration=Release]

# .NET 10 (LTS)
msbuild geompp_csharp\GeomPP.vcxproj /p:Platform=x64 /p:GeomppBuildRoot="$PWD\build_win" [/p:Configuration=Release]

# .NET Framework 4.8
msbuild geompp_csharp\GeomPP_Net48.vcxproj /p:Platform=x64 /p:GeomppBuildRoot="$PWD\build_win" [/p:Configuration=Release]

# run smoke tests, after build from the main directory geompp
dotnet test geompp_csharp\tests\GeomPPTests.csproj [-p:GeomPPConfiguration=Release]
Product Compatible and additional computed target framework versions.
.NET net8.0-windows7.0 is compatible.  net9.0-windows was computed.  net9.0-windows7.0 is compatible.  net10.0-windows was computed.  net10.0-windows7.0 is compatible. 
.NET Framework net48 is compatible.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETFramework 4.8

    • No dependencies.
  • net10.0-windows7.0

    • No dependencies.
  • net8.0-windows7.0

    • No dependencies.
  • net9.0-windows7.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.17.3 100 8/15/2026
0.17.2 92 8/14/2026
0.16.2 88 8/6/2026
0.15.1 120 7/24/2026
0.14.0 105 7/21/2026
0.13.0 118 7/9/2026
0.12.0 105 7/8/2026
0.11.0 111 7/4/2026
0.10.1 125 6/23/2026
0.9.1 224 6/17/2026
0.8.2 118 5/18/2026
0.8.0 111 5/18/2026
0.7.0 104 5/6/2026
0.6.0 104 5/4/2026
0.5.0 104 5/1/2026
0.4.0 115 4/27/2026
0.1.2 124 4/13/2026
0.1.1 123 4/13/2026
0.1.0 125 4/9/2026

> C++ library — tagged `v0.14.0` · C# / NuGet — tagged `csharp-v0.14.0` · Python / PyPI — tagged `python-v0.14.0`

> Quadratic Bezier corner smoothing: `bezier_smoothing_2()` rounds a polyline corner (p0, p1, p2) with a quadratic Bezier arc (density-based or exact-count, with a tunable tiny-edge skip threshold), and `Polyline2D::Expand()` / `Polyline3D::Expand()` — the inverse of `Reduce()` — apply it to every inner corner of a polyline via a new `polyline_expansion()` free function.

### Added

**C++ core**
- `bezier_smoothing_2(PointT p0, PointT p1, PointT p2, double smoothness, double min_distance, double min_segment_length = DOUBLE_EPSILON)` (`calc_utils2d.hpp`) — trims tangent points into p1 by up to `smoothness` (∈ [0,1]) fraction of the shorter adjacent edge, then samples the resulting quadratic Bezier arc via De Casteljau's algorithm at roughly `min_distance` apart. An adjacent edge at or below `min_segment_length` isn't trimmed into (that tangent point falls back to `p1`); if both are, the whole corner collapses to `p1` (no curve). Templated over `PointT`; explicit-instantiated for `Point2D`/`Point3D`. Throws `std::invalid_argument` if `min_distance <= 0`.
- `bezier_smoothing_2(PointT p0, PointT p1, PointT p2, double smoothness, int num_segments, double min_segment_length = DOUBLE_EPSILON)` — same tangent trimming and sampling, but takes an exact segment count instead of a distance-derived one; a distinct overload rather than a parameter that reinterprets `min_distance`, since the two controls don't share a unit. Throws `std::invalid_argument` if `num_segments < 1`.
- `PolylineExpansionParams` (`constants.hpp`) — bundles `smoothness`, a `Mode` (`FixedSegments` / `MinDistance`) mirroring `bezier_smoothing_2`'s two overloads, `segments_per_corner`, `min_distance`, and `min_segment_length`.
- `polyline_expansion(std::vector<PointT> const& input, PolylineExpansionParams const& settings)` (`calc_utils2d.hpp`) — rounds every inner corner of a raw point list via `bezier_smoothing_2`, deduplicating consecutive points (a corner fully skipped by `min_segment_length`, or two adjacent corners' arcs meeting exactly at a shared edge's midpoint — each corner's trim is independently capped at half its shared edge, so adjacent arcs can touch but never cross) rather than emitting zero-length segments. Templated over `PointT`; explicit-instantiated for `Point2D`/`Point3D`.
- `Polyline2D::Expand(PolylineExpansionParams const& settings = PolylineExpansionParams{})` / `Polyline3D::Expand(...)` — the inverse of `Reduce()`: adds vertices rather than removing them. Thin wrappers delegating to `polyline_expansion()`.

**Python bindings**
- `bezier_smoothing_2(p0, p1, p2, smoothness, min_distance, min_segment_length=DOUBLE_EPSILON)` and `bezier_smoothing_2(p0, p1, p2, smoothness, num_segments, min_segment_length=DOUBLE_EPSILON)` — bound for both `Point2D` and `Point3D`; overload resolution follows pybind11's no-conversion-first pass, matching the C++ int-vs-double disambiguation.
- `PolylineExpansionMode` (`FixedSegments`, `MinDistance`), `PolylineExpansionParams(smoothness=0.5, mode=FixedSegments, segments_per_corner=4, min_distance=0.1, min_segment_length=DOUBLE_EPSILON)`, `polyline_expansion(points, settings)`.
- `Polyline2D.expand(settings=PolylineExpansionParams())` / `Polyline3D.expand(...)`.

**C# bindings**
- `GeomUtil.BezierSmoothing2(Point2D^, Point2D^, Point2D^, double, double)` / `(..., int)` — and the `Point3D^` overloads — plus `minSegmentLength` overloads of each.
- `PolylineExpansionMode`, `PolylineExpansionParams` (explicit-backing-field properties, matching this codebase's convention — no C++/CLI auto-properties elsewhere), `GeomUtil.PolylineExpansion(points, settings)`.
- `Polyline2D.Expand()` / `Polyline2D.Expand(PolylineExpansionParams^)` — and the `Polyline3D` equivalents.

### Fixed

- A pre-release iteration of `polyline_expansion()`/`Expand()` read a corner's `p0`/`p1` back out of the *already-built* output buffer instead of the original input knots — this broke the invariant that each corner's trim is bounded by its true adjacent-edge length (adjacent corners' arcs could no longer be guaranteed to meet without crossing), and on the very first corner processed could even set `p1 == p2`. Never released; caught during validation before landing. All `p0`/`p1`/`p2` are read directly from the original knot list, unconditionally.
- `size_t` → `std::size_t` normalized throughout `calc_utils2d.cpp`.

### Tests

- `test_calc_utils2d.cpp`: `BezierSmoothing2_*` — both overloads' throw paths, trimmed-tangent endpoint values (hand-verified), `smoothness=0` sharp-corner collapse, coincident-endpoint degeneracy (no NaN), exact point-count for `num_segments`, and `MinSegmentLength_*` (single-side skip, both-side skip, `DOUBLE_EPSILON` default, explicit-zero opt-out). `PolylineExpansion_*` — two-point no-op, single-corner trim, a dedicated multi-corner regression test proving each corner uses its own original knots, `min_segment_length` full-corner skip.
- `test_polyline2d.cpp` / `test_polyline3d.cpp`: `Expand_*` — unchanged below 3 knots, trimmed-tangent endpoints, `min_segment_length` full-skip matches the original polyline exactly, `MinDistance` mode density scaling, thrown-precondition propagation from `bezier_smoothing_2`.
- `test_geompp.py`: `TestBezierSmoothing2FreeFunction`, `TestPolylineExpansionParams`, `TestPolylineExpansionFreeFunction`, `TestPolyline2DExpand`, `TestPolyline3DExpand` — same coverage as the C++ suite, plus `Point3D` cases.
- `Program.cs`: equivalent `BezierSmoothing2_*`, `PolylineExpansionParams_*`, `PolylineExpansion_*`, `Polyline2D_Expand_*`, `Polyline3D_Expand_*` coverage.

---