GeomPP 0.6.0
See the version list below for details.
dotnet add package GeomPP --version 0.6.0
NuGet\Install-Package GeomPP -Version 0.6.0
<PackageReference Include="GeomPP" Version="0.6.0" />
<PackageVersion Include="GeomPP" Version="0.6.0" />
<PackageReference Include="GeomPP" />
paket add GeomPP --version 0.6.0
#r "nuget: GeomPP, 0.6.0"
#:package GeomPP@0.6.0
#addin nuget:?package=GeomPP&version=0.6.0
#tool nuget:?package=GeomPP&version=0.6.0
C# bindings for geompp, a C++20 geometry library.
Provides Point2D/3D, Vector2D/3D, Line2D/3D, Ray2D/3D, LineSegment2D/3D,
Polyline2D/3D, Triangle2D/3D, Polygon2D/3D, BBox2D/3D, Plane — with full
operator support, intersection queries, WKT serialization, and file I/O.
Built with C++/CLI for Windows x64. Targets both .NET 10 and .NET Framework 4.8.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0-windows7.0 is compatible. |
| .NET Framework | net48 is compatible. net481 was computed. |
-
.NETFramework 4.8
- No dependencies.
-
net10.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 | 98 | 8/15/2026 |
| 0.17.2 | 92 | 8/14/2026 |
| 0.16.2 | 87 | 8/6/2026 |
| 0.15.1 | 119 | 7/24/2026 |
| 0.14.0 | 104 | 7/21/2026 |
| 0.13.0 | 117 | 7/9/2026 |
| 0.12.0 | 103 | 7/8/2026 |
| 0.11.0 | 110 | 7/4/2026 |
| 0.10.1 | 124 | 6/23/2026 |
| 0.9.1 | 222 | 6/17/2026 |
| 0.8.2 | 117 | 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 | 103 | 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.6.0` · C# / NuGet — tagged `csharp-v0.6.0` · Python / PyPI — tagged `python-v0.6.0`
> Touches `Polyline2D`, `Polyline3D`, `Polygon2D`, `Polygon3D`, `Triangle2D`, `Triangle3D`.
### Changed
**C++ core / Python bindings**
- `Polyline2D::Make` and `Polyline3D::Make` — fixed: now call `remove_collinear(points)` instead of `remove_collinear(remove_duplicates(points))`. `remove_duplicates` removed all duplicate points regardless of position, silently corrupting self-intersecting or backtracking paths; `remove_collinear` already handles consecutive duplicates as a degenerate collinear triplet, so the extra pass was both wrong and redundant.
- `Polygon2D::Make` and `Polygon3D::Make` (no-holes overload) — fixed: now call `remove_collinear(points)`, consistent with the with-holes overload. Previously the no-holes path only called `remove_duplicates`, skipping collinear simplification.
- `remove_duplicates_from_sorted_list()` renamed to `remove_consecutive_duplicates()` (Point2D and Point3D overloads). The old name was misleading — the function removes consecutive equal elements, not all duplicates from a sorted container. Affects `geompp::remove_consecutive_duplicates`, `geompp.remove_consecutive_duplicates` (Python), and all internal callers (`Polygon2D::Make`, `Polygon3D::Make`, `Triangle2D::Intersection`).
**C++ core**
- `Polyline2D::Length()` and `Polyline3D::Length()` — now inline cached getters; value is pre-computed in `Make()` and stored as a private member. No change to public API.
- `Polygon2D::Perimeter()` and `Polygon3D::Perimeter()` — same inline-cached pattern. No change to public API.
- `Polyline2D::operator=` and `Polyline3D::operator=` — now copy the cached `LENGTH` member.
- `Polygon2D::operator=` and `Polygon3D::operator=` — now copy the cached `PERIMETER` member (and `PLANE` for 3D).
- `Polyline2D::AlmostEquals()` and `Polyline3D::AlmostEquals()` — added fast-rejection on `LENGTH` difference before comparing vertices.
- `Polyline2D::Contains()` and `Polyline3D::Contains()` — rewritten with `std::ranges::any_of` over `ToSegments()`.
- `Polyline2D::DistanceTo()` and `Polyline3D::DistanceTo()` — rewritten with `std::ranges::min` + `views::transform` over `ToSegments()`; no intermediate allocation.
- `Polyline2D::ProjectOnto()` and `Polyline3D::ProjectOnto()` — fixed double segment construction; now carries the best projected point directly through the loop.
- `Polyline2D::Location()` and `Polyline3D::Location()` — fixed double `segs[i]` construction per iteration; each segment is now materialized once with `auto seg = segs[i]`.
- `Polyline2D::Interpolate()` and `Polyline3D::Interpolate()` — now throws `std::invalid_argument` when `pct` is outside `[0, 1]`; previously clamped silently.
- `Triangle2D::Contains()` — inlines the removed `Location()` math directly; behaviour unchanged.
- `Triangle2D::DistanceTo()` — reverted to `throw std::runtime_error("not implemented")`; previous implementation was incorrect.
### Added
**Python / PyPI**
- `LineSegment2D.project_onto()`, `LineSegment3D.project_onto()`, `Ray2D.project_onto()`, `Ray3D.project_onto()`, `Polyline2D.project_onto()`, `Polyline3D.project_onto()` — bound from the existing C++ `ProjectOnto(Point)` method; was callable from C++ and C# but missing from Python bindings.
### Fixed
**C++ core**
- `Polyline2D::Location()` and `Polyline3D::Location()` — corrected unit mismatch: `seg.Location(point)` returns a [0, 1] fraction but was treated as a raw length accumulator; result is now `(tot_len + seg.Location(point) * seg.Length()) / LENGTH`.
- `Polyline2D::Interpolate()` and `Polyline3D::Interpolate()` — corrected unit mismatch: `pct` ∈ [0, 1] was compared directly against cumulative segment lengths; fixed by computing `target = pct * LENGTH` before the selection loop.
- `WktParser::FromWkt()` — `LINESTRING` WKT strings were silently parsed as `Line2D`/`Line3D` because the `LINE` prefix check ran before the `LINESTRING` check; fixed by moving the `LINESTRING` branch first.
**C# / NuGet**
- `Line2D` binding — removed spurious `Location(Point2D^)` declaration and implementation; the backing `geompp::Line2D` has no such method, causing a build failure.
### Removed (breaking)
**C++ core**
- `Polygon2D::Location()` and `Polygon3D::Location()` — removed; function had no meaningful geometric definition for a polygon.
- `Polygon2D::Interpolate()` and `Polygon3D::Interpolate()` — removed; function had no meaningful geometric definition for a polygon.
- `Triangle2D::Location()` — removed; returned parametric `(s,t)` coordinates as a `Point2D`, which is a type misuse and leaked an internal implementation detail.
- `Triangle3D::Location()` — removed (was unimplemented stub).
**C# / NuGet (breaking)**
- `Polygon2D.Location()`, `Polygon3D.Location()`, `Polygon2D.Interpolate()`, `Polygon3D.Interpolate()` — removed.
- `Triangle2D.Location()` and `Triangle3D.Location()` — removed.
**Python / PyPI (breaking)**
- `Polygon2D.location()`, `Polygon3D.location()`, `Polygon2D.interpolate()`, `Polygon3D.interpolate()` — removed.
- `Triangle2D.location()` and `Triangle3D.location()` — removed.
### Tests
**C++ (`geompp_tests`)**
- `test_polygon2d.cpp`: added `ToSegments`.
- `test_polygon3d.cpp`: added `ToSegments`.
- `test_polyline2d.cpp`: updated `Interpolate` — replaced clamp-assertions with `EXPECT_ANY_THROW` for out-of-range `pct`.
- `test_polyline3d.cpp`: same as above.
- `test_triangle2d.cpp`: replaced `Location`-based roundtrip assertion in `Interpolate` test with `Contains(Centroid())`; added outside-returns-nullopt cases; replaced `DistanceTo` test body with `EXPECT_ANY_THROW`.
- `test_triangle3d.cpp`: removed `Location` test.
**Python (`geompp_python/tests`)**
- `TestPolygon2D`, `TestPolygon3D`, `TestPolyline2D`, `TestPolyline3D`: added `test_to_segments`.
- `TestPolyline2D`, `TestPolyline3D`: updated `test_interpolate` — added `pytest.raises` for out-of-range `pct`.
- `TestTriangle2D`: removed `test_location`; expanded `test_interpolate` (vertex checks, outside returns `None`).
- `TestTriangle3D`: added `test_interpolate` (vertices, centroid, outside returns `None`).
**C# (`geompp_csharp/tests`)**
- `Vector2D`: added ~12 tests covering `AlmostEquals`, arithmetic operators, `Length`, `Dot`, `Cross`, `Normalize`, `Perp`, `IsParallel`, `IsPerpendicular`.
- `WktParser`: added 10 tests (`Open_ValidFile_NoThrow`, `Next_Returns*` for Point2D/3D, LineSegment2D/3D, Polyline2D/3D, `Next_SkipsComments`, `FromWkt_Point2D`, `ToWkt_Point2D`); all file-using tests wrapped in `using (var parser = ...)` blocks to ensure `Dispose()` closes the `std::ifstream` before `File.Delete`.
- `GeometryCollection2D` and `GeometryCollection3D`: added ~15 tests each covering `Add`, `Get`, `Size`, `AlmostEquals`, `ToWkt`, `FromWkt`, `ToFile`/`FromFile`.
- `Polyline2D` / `Polyline3D`: corrected `DistanceTo_PointAboveSegment` — expected distance changed from `3.0` to `2.0`: for polyline `(0,0)→(4,0)→(4,4)` and point `(2,3)`, the nearest point is on the vertical segment at `(4,3)`, distance 2.
**Python (`geompp_python/tests`)**
- `TestPolyline2D` / `TestPolyline3D`: corrected `test_project_onto` — expected `project_onto(Point(2,3))` updated to `Point(3,3)` (nearest, distance 1) from `Point(2,0)` (distance 3).
---