VL.NetTopologySuite
0.0.1-alpha
dotnet add package VL.NetTopologySuite --version 0.0.1-alpha
NuGet\Install-Package VL.NetTopologySuite -Version 0.0.1-alpha
<PackageReference Include="VL.NetTopologySuite" Version="0.0.1-alpha" />
<PackageVersion Include="VL.NetTopologySuite" Version="0.0.1-alpha" />
<PackageReference Include="VL.NetTopologySuite" />
paket add VL.NetTopologySuite --version 0.0.1-alpha
#r "nuget: VL.NetTopologySuite, 0.0.1-alpha"
#:package VL.NetTopologySuite@0.0.1-alpha
#addin nuget:?package=VL.NetTopologySuite&version=0.0.1-alpha&prerelease
#tool nuget:?package=VL.NetTopologySuite&version=0.0.1-alpha&prerelease
VL.NetTopologySuite
NetTopologySuite made natural inside vvvv gamma. Not another GIS framework.
Status:
0.0.1-alpha, working, unpublished. 39 nodes in six categories, 126 tests, 15 help patches, every node opens one on F1. Every category has been seen running in vvvv gamma 7.4 (2026-08-14 to 2026-09-25), all fifteen help patches were reviewed by hand in the editor, and the packed package installs from a local feed with its dependencies and compiles every shipped help patch (tools\Test-Install.ps1, 2026-09-25). Nothing is on nuget.org yet; the release steps and the decisions still open are in docs/RELEASE.md. The table below says exactly what has been shown.
The mental model
Coordinates
↓
Geometry
↓
Spatial operation
↓
Geometry
Every node hands back a native NetTopologySuite type — Point, LineString, Polygon,
Geometry — never a wrapper of our own. So the output of any operation is the input to the next
one, and a geometry made here goes straight into anything else that speaks NTS:
VL.NetTopologySuite
↓
NTS Geometry
↓
other packages, such as VL.Mapsui
Neither package depends on the other. They share the library, not each other.
What is verified, and what is not
The kinds of verification prove different things, and being vague about which one you have is how a package oversells itself:
| proves | run | |
|---|---|---|
dotnet test |
the arithmetic is right | ✅ 126 tests, ~300 ms, no network |
tools\Test-VLPatch.ps1 |
the .vl documents are well formed, labels do not collide, every node has an F1 flag |
✅ 16 documents, 39 of 39 nodes flagged |
tools\Test-VLPackage.ps1 |
the package can structurally contribute nodes | ✅ passes |
tools\Compile-HelpPatches.ps1 (vvvvc) |
every node in a patch resolved — an unresolved one has its links dropped and vanishes from the generated C#, so the script reads the C# | ✅ all 15 help patches |
tools\Test-Install.ps1 |
the packed package installs from a feed with its dependencies, and every help patch inside it compiles with that install as the only package repository | ✅ 2026-09-25 |
| the vvvv GUI | a node appears under the right category, with the right label, computing the right value | ✅ every category; all 15 help patches seen 2026-09-24, reviewed by hand 2026-09-25 |
| F1 on a node | the node opens its help patch | ✅ all 39 nodes, 2026-09-24 |
What the GUI showed, category by category:
NTS.Geometry/NTS.IO/NTS.Operation(2026-08-14):Create a pointoutputsPOINT (139.7671 35.6812);Create a polygongives a unit square withArea1.00 and an empty validity reason;Read and write WKTround-trips a polygon at SRID 0;Buffer a geometrytakes area 1.00 to 2.20 with a 0.25 buffer, matching 1 + 4×0.25 + ≈π×0.25², and back to 1.00 by intersecting with the original.NTS.Feature(2026-08-23, through VL.Overworld's Tutorial 08, and 2026-09-24 inHowTo Attach attributes to a geometry).NTS.Index(2026-08-23, through Tutorial 11): 100,000 points, a mouse-driven query polygon,Indexes Builtholding at 1 while the mouse moved, indexed and brute-force counts equal.NTS.Network(2026-08-23 through Tutorial 13; 2026-09-24 inHowTo Find the shortest path, which draws its town with VL.Skia):Networks Builtstays at 1 while From and To move,Foundturns False on an island, the teal path follows the streets.[Name]on a method is honoured, so the nodes render asRead WKT,Write WKT,Nearest Points. Fluent operations get anOutputpin, the rest getResult— confirmed in the generated C#.
Two things the tooling caught that the eye would not:
LastCategoryFullNamein a.vlis a hint, not the truth. Set it toNTS.Wrong, recompile, and every node still resolves. A green compile proves a node exists and nothing about its category. Only the NodeBrowser does. That is why the GUI has its own row above.- A green
vvvvcexit code proves nothing either. An unresolved node has its links dropped silently.Compile-HelpPatches.ps1therefore reads the generated*.vl.1.csand looks for each node's call.
The nodes
Thirty-nine, in six categories. No node takes more than three inputs, except where a fourth is a default you will rarely touch.
NTS.Geometry — making geometry
| Node | in → out |
|---|---|
Coordinate |
X, Y → Coordinate |
CoordinateZ |
X, Y, Z → CoordinateZ |
Split |
Coordinate → X, Y, Z |
GeometryFactory |
SRID → GeometryFactory |
Point |
Coordinate → Point |
LineString |
spread of Coordinate → LineString |
LinearRing |
spread of Coordinate → LinearRing (closes the ring for you) |
Polygon |
LinearRing shell, spread of LinearRing holes → Polygon |
MultiPoint |
spread of Point → MultiPoint |
MultiLineString |
spread of LineString → MultiLineString |
MultiPolygon |
spread of Polygon → MultiPolygon |
GeometryCollection |
spread of Geometry → GeometryCollection |
NTS.Geometry — reading it back
| Node | in → out |
|---|---|
GeometryType |
Geometry → the OGC name |
IsEmpty |
Geometry → bool |
SRID |
Geometry → int |
IsValid |
Geometry → bool, reason, location |
Area |
Geometry → float |
Length |
Geometry → float |
Centroid |
Geometry → Point |
Bounds |
Geometry → MinX, MinY, MaxX, MaxY |
Coordinates |
Geometry → spread of Coordinate |
Geometries |
Geometry → spread of Geometry |
NTS.Feature — attaching data to geometry
| Node | in → out |
|---|---|
Feature |
Geometry, Dictionary of attributes → Feature |
Split |
Feature → Geometry, Dictionary of attributes |
The type is NetTopologySuite.Features.Feature — the NTS team's own neutral model, not a wrapper
of ours. These two moved here from VL.Mapsui on 2026-08-22, because a feature has to be
constructible without a map engine: VL.GeoJSON writes them, VL.Mapsui draws and picks them, and a
patch can make one by hand. The reasoning and the field-wide evidence are in
docs/ARCHITECTURE.md.
NTS.Operation
Buffer · Intersection · Union · Difference · Distance · Nearest Points · Intersects · Contains · Within
NTS.IO
Read WKT · Write WKT
NTS.Index — asking many geometries a question without asking each one
| Node | in → out |
|---|---|
SpatialIndex |
spread of Geometry → STRtree, Count, Indexes Built |
Query |
STRtree, search Geometry → Candidates (spread of Geometry), Candidate Count |
The package's first process node (2026-08-23). An index is built once, held, and rebuilt only
when the set of geometry references changes — never when only the spread wrapper is new, and
never by comparing coordinates. Watch Indexes Built: it should reach 1 and stay. If it climbs
every frame, the geometries upstream are being re-created every frame and the index is doing
nothing for you — Read WKT upstream does exactly that, and the help patches put it in a Cache
region for that reason.
Candidates are not results. Query returns the geometries whose bounding boxes intersect the
search geometry's bounding box — NTS's words: "items whose bounds intersect the given envelope" —
and never looks at the geometry itself. Finish with the exact predicate you meant (Intersects,
Contains, Distance) on the candidates. The index did not answer your question; it narrowed who
gets asked. Reasoning and the lifecycle contract in
docs/ARCHITECTURE.md.
NTS.Network — close does not mean reachable
| Node | in → out |
|---|---|
Network |
spread of LineString → Network, Node Count, Edge Count, Networks Built |
ShortestPath |
Network, From Point, To Point, Max Snap Distance → Path (LineString), Length, Found, From Snap Distance, To Snap Distance |
NetTopologySuite ships no shortest-path capability, so this is an algorithm of ours. It was built
as NTS.Experimental.Network in 2026-08 for VL.Overworld's Tutorial 13 and promoted to
NTS.Network on 2026-08-28 after a scope review with two real consumers
(docs/NETWORK-SCOPE-PROPOSAL.md).
Connectivity is exact shared endpoints — no tolerance, no auto-noding, a crossing is not a
junction, an interior vertex is shape. Cost is length, edges are undirected, From/To snap to the
nearest node within Max Snap Distance and the snap distances are pins. Found = false is a
result. One sentence of scope, a long non-scope list in docs/ROADMAP.md, and no
promise of a routing library.
Everything else NetTopologySuite offers — and it is a large library — stays reachable through VL's raw .NET nodes. See docs/ARCHITECTURE.md.
Four things that will bite you
Each is measured, not inherited from documentation.
1. NTS geometries are not as immutable as everyone says. Operations return new geometries, but
coordinate storage is shared and writable: NTS's own factory.CreatePoint(c) keeps the caller's
Coordinate, and geometry.Coordinates[0].X = 5 moves the geometry. This package copies on the
way in and on the way out, so it cannot happen through these nodes. It is the main reason they
exist rather than using VL's reflection nodes on GeometryFactory directly.
2. Units follow the coordinates, and nothing warns you. Buffer(geometry, 0.001) on longitude
and latitude is a thousandth of a degree — about 111 m near the equator, less further from it,
and not a constant number of metres anywhere. Area on lon/lat is in square degrees. Project to
a metric reference system before doing metric work.
3. An SRID is a label, not a transformation. Setting it to 4326 does not reproject anything and does not check that the numbers are longitude and latitude. The default is 0, meaning unset, which is NTS's own default and the honest one for a library that has not seen your data. Worse: mixing SRIDs never throws — a 4326 geometry intersected with an SRID 0 one returns 4326 without complaint — so a wrong CRS gives a confident wrong answer. Reprojection belongs in a different package.
4. Coordinate order is X first. Longitude then latitude, which is the opposite of how they are usually spoken, and the most common bug in this domain.
Help patches
Fifteen, in help\VL.NetTopologySuite\, in the order the Help Browser shows them. Press F1 on
any node of this package to open the one that teaches it.
| Topic | Patch |
|---|---|
| Start here | Explanation Overview of available nodes — every node, one line each |
| Making geometry | HowTo Create a point · HowTo Create a linestring · HowTo Create a polygon · HowTo Group geometries · HowTo Work with Z |
| Looking at geometry | HowTo Inspect a geometry |
| Text in, geometry out | HowTo Read and write WKT |
| Spatial operations | HowTo Buffer a geometry · HowTo Combine two geometries · HowTo Test how geometries relate · HowTo Measure distance |
| Features | HowTo Attach attributes to a geometry |
| Many geometries | HowTo Query many geometries fast |
| Networks | HowTo Find the shortest path — draws its town and the path with VL.Skia |
They are written the way the vvvv community writes help: a one-line heading, the wired nodes, and short notes beside them — a style measured over 389 shipped HowTos and nine community packs, in docs/HELP-PATCH-STYLE.md.
No numbers in the filenames, deliberately. The convention across vvvv's own packs is the five
prefixes — Explanation, HowTo, Reference, Example, Tutorial — with Help.xml doing the
ordering. These were numbered 01 03 04 06 at first, and every gap read as a broken install.
Help.xml is the only place order lives, and tools\Test-VLPatch.ps1 checks that it accounts
for every patch on disk and names none that is missing.
Building it
Needs the .NET 8 SDK and vvvv gamma 7.2 or newer (7.4 is what this was built against).
Everything else — NuGet.exe, vvvvc.exe — ships inside vvvv.
.\build.ps1 # build + stage dist\ (refuses to run while vvvv is open)
dotnet test test\VL.NetTopologySuite.Tests\VL.NetTopologySuite.Tests.csproj
.\tools\Test-VLPackage.ps1 # static package checks, no vvvv needed
.\tools\Test-VLPatch.ps1 # structural checks on every .vl, label arithmetic, F1 flags
.\pack.ps1 # pack into dist\feed\
.\tools\Compile-HelpPatches.ps1 # vvvvc on every help patch, then READS the generated C#
.\tools\Test-Install.ps1 # install the packed package from dist\feed like a user would
# Open a help patch in vvvv with the right package repositories (or double-click Open-HelpPatch.cmd):
.\tools\Open-HelpPatch.ps1 "Buffer"
build.ps1 refuses to run while vvvv is open, deliberately: a running vvvv holds the staged
assemblies, and would not pick up the change anyway. dist\VL.NetTopologySuite\help is a junction
to the repository's help folder, so a patch saved in vvvv is the one git sees.
Until the package is on nuget.org, a vvvv document can use it by pointing vvvv at the staged
folder: vvvv.exe MyPatch.vl --package-repositories <repo>\dist;<repo>\deps.
Documentation
| docs/RULES.md | ⭐ the packaging and runtime rules, carried from the sibling repositories. Read before adding a node. |
| docs/ARCHITECTURE.md | why each node exists, what stays raw, and the decisions behind both |
| docs/AUDIT.md | the audit this package was designed from, including everything measured against NTS |
| docs/HELP-PATCH-STYLE.md | how vvvv help patches are written, measured from shipped packs, and how F1 finds them |
| docs/NETWORK-SCOPE-PROPOSAL.md | the review that promoted the network from experimental, and its evidence |
| docs/ROADMAP.md | what is next, what is deliberately absent, and what will never be here |
| docs/RELEASE.md | the release checklist, what each step proves, and the decisions still open |
docs/RULES.md is not general advice. Every rule in it is followed by what it cost — nine
releases that installed and contributed zero nodes, and a home network taken down by a node written
as a public static method. It transfers; a link to another repository's copy would not.
Licence
MIT. NetTopologySuite is BSD-3-Clause and is declared as a dependency rather than redistributed.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- NetTopologySuite (>= 2.6.0)
- NetTopologySuite.Features (>= 2.1.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on VL.NetTopologySuite:
| Package | Downloads |
|---|---|
|
VL.Mapsui
EARLY - not ready for real work yet. A real map engine as nodes for vvvv gamma. Tile layers from OpenStreetMap or any XYZ service, your own geometry drawn on top, labels taken from your data, and a Pick node that tells you which feature you are pointing at. Deliberately not one all-in-one map node. The pieces are Mapsui's own - Map, layers, Navigator - so a patch composes them, decides for itself how the mouse drives the map, and can put its own layers on it. That is what a patching environment is for. Geometry crosses the boundary as NetTopologySuite, so whatever produced it - a file, a service, VL.NetTopologySuite, a ForEach over a record of your own - never has to know that Mapsui will draw it. 32 nodes and 19 help patches, from the smallest working map to styling by a value; every node opens one on F1. The node surface can still change between prereleases, and Mapsui's editing and WMS/WFS surfaces are not wrapped yet. Requires vvvv gamma 7.4 or newer (.NET 8). Install with: nuget install VL.Mapsui -pre |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.0.1-alpha | 67 | 9/25/2026 |
0.0.1-alpha - The first release, a prerelease. 39 nodes in six categories - NTS.Geometry,
NTS.Feature, NTS.Operation, NTS.IO, NTS.Index, NTS.Network - 126 tests, 15 help patches, and
F1 on every node opens one. Verified in vvvv gamma 7.4. Coordinates are copied on the way in
and out, so a geometry cannot be moved behind your back. Not ready for real work: the node
surface may still change between prereleases.